Merge "Default face lockout should be duration==0"
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index fea6979..1da8b09 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -360,7 +360,7 @@
public static class DevicePorts.DevicePort {
ctor public DevicePorts.DevicePort();
method @Nullable public String getAddress();
- method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.AudioFormat> getEncodedFormats();
+ method @Nullable public java.util.List<java.lang.String> getEncodedFormats();
method @Nullable public android.audio.policy.configuration.V7_0.Gains getGains();
method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.Profile> getProfile();
method @Nullable public android.audio.policy.configuration.V7_0.Role getRole();
@@ -368,7 +368,7 @@
method @Nullable public String getType();
method @Nullable public boolean get_default();
method public void setAddress(@Nullable String);
- method public void setEncodedFormats(@Nullable java.util.List<android.audio.policy.configuration.V7_0.AudioFormat>);
+ method public void setEncodedFormats(@Nullable java.util.List<java.lang.String>);
method public void setGains(@Nullable android.audio.policy.configuration.V7_0.Gains);
method public void setRole(@Nullable android.audio.policy.configuration.V7_0.Role);
method public void setTagName(@Nullable String);
@@ -527,10 +527,10 @@
public static class SurroundFormats.Format {
ctor public SurroundFormats.Format();
- method @Nullable public android.audio.policy.configuration.V7_0.AudioFormat getName();
- method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.AudioFormat> getSubformats();
- method public void setName(@Nullable android.audio.policy.configuration.V7_0.AudioFormat);
- method public void setSubformats(@Nullable java.util.List<android.audio.policy.configuration.V7_0.AudioFormat>);
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<java.lang.String> getSubformats();
+ method public void setName(@Nullable String);
+ method public void setSubformats(@Nullable java.util.List<java.lang.String>);
}
public class SurroundSound {
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 6784828..56b3a27 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -774,13 +774,13 @@
</xs:sequence>
</xs:complexType>
<xs:simpleType name="audioFormatsList">
- <xs:list itemType="audioFormat" />
+ <xs:list itemType="extendableAudioFormat" />
</xs:simpleType>
<xs:complexType name="surroundFormats">
<xs:sequence>
<xs:element name="format" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
- <xs:attribute name="name" type="audioFormat" use="required"/>
+ <xs:attribute name="name" type="extendableAudioFormat" use="required"/>
<xs:attribute name="subformats" type="audioFormatsList" />
</xs:complexType>
</xs:element>
diff --git a/audio/7.0/types.hal b/audio/7.0/types.hal
index 6cac9c9..2d42129 100644
--- a/audio/7.0/types.hal
+++ b/audio/7.0/types.hal
@@ -44,8 +44,10 @@
* A substitute for POSIX timespec.
*/
struct TimeSpec {
- uint64_t tvSec; // seconds
- uint64_t tvNSec; // nanoseconds
+ /** Seconds. */
+ uint64_t tvSec;
+ /** Nanoseconds. */
+ uint64_t tvNSec;
};
struct ParameterValue {
@@ -85,8 +87,10 @@
* Used by streams opened in mmap mode.
*/
struct MmapPosition {
- int64_t timeNanoseconds; // time stamp in ns, CLOCK_MONOTONIC
- int32_t positionFrames; // increasing 32 bit frame count reset when IStream.stop() is called
+ /** Timestamp in ns, CLOCK_MONOTONIC. */
+ int64_t timeNanoseconds;
+ /** Increasing 32 bit frame count reset when IStream.stop() is called. */
+ int32_t positionFrames;
};
/**
@@ -128,9 +132,12 @@
*/
@export(name="audio_microphone_channel_mapping_t", value_prefix="AUDIO_MICROPHONE_CHANNEL_MAPPING_")
enum AudioMicrophoneChannelMapping : uint32_t {
- UNUSED = 0, /* Channel not used */
- DIRECT = 1, /* Channel used and signal not processed */
- PROCESSED = 2, /* Channel used and signal has some processing */
+ /** Channel not used. */
+ UNUSED = 0,
+ /** Channel used and signal not processed. */
+ DIRECT = 1,
+ /** Channel used and signal has some processing. */
+ PROCESSED = 2,
};
/**
@@ -179,7 +186,8 @@
* Used by StreamIn and Device
*/
struct MicrophoneInfo {
- /** Unique alphanumeric id for microphone. Guaranteed to be the same
+ /**
+ * Unique alphanumeric id for microphone. Guaranteed to be the same
* even after rebooting.
*/
string deviceId;
@@ -187,18 +195,21 @@
* Device specific information
*/
DeviceAddress deviceAddress;
- /** Each element of the vector must describe the channel with the same
- * index.
+ /**
+ * Each element of the vector must describe the channel with the same
+ * index.
*/
vec<AudioMicrophoneChannelMapping> channelMapping;
/** Location of the microphone in regard to the body of the device */
AudioMicrophoneLocation location;
- /** Identifier to help group related microphones together
- * e.g. microphone arrays should belong to the same group
+ /**
+ * Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
*/
AudioMicrophoneGroup group;
- /** Index of this microphone within the group.
- * (group, index) must be unique within the same device.
+ /**
+ * Index of this microphone within the group.
+ * (group, index) must be unique within the same device.
*/
uint32_t indexInTheGroup;
/** Level in dBFS produced by a 1000 Hz tone at 94 dB SPL */
@@ -209,17 +220,20 @@
float minSpl;
/** Standard polar pattern of the microphone */
AudioMicrophoneDirectionality directionality;
- /** Vector with ordered frequency responses (from low to high frequencies)
- * with the frequency response of the microphone.
- * Levels are in dB, relative to level at 1000 Hz
+ /**
+ * Vector with ordered frequency responses (from low to high frequencies)
+ * with the frequency response of the microphone.
+ * Levels are in dB, relative to level at 1000 Hz
*/
vec<AudioFrequencyResponsePoint> frequencyResponse;
- /** Position of the microphone's capsule in meters, from the
- * bottom-left-back corner of the bounding box of device.
+ /**
+ * Position of the microphone's capsule in meters, from the
+ * bottom-left-back corner of the bounding box of device.
*/
AudioMicrophoneCoordinate position;
- /** Normalized point to signal the main orientation of the microphone's
- * capsule. sqrt(x^2 + y^2 + z^2) = 1
+ /**
+ * Normalized point to signal the main orientation of the microphone's
+ * capsule. sqrt(x^2 + y^2 + z^2) = 1
*/
AudioMicrophoneCoordinate orientation;
};
@@ -262,7 +276,6 @@
// frameworks/base/media/java/android/media/AudioTrack.java
/**
* Disable any Dual Mono presentation effect.
- *
*/
OFF = 0,
/**
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 7148d76..414eede 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
@@ -18,6 +18,8 @@
#define ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
#include <sys/types.h>
+#include <algorithm>
+#include <cctype>
#include <android_audio_policy_configuration_V7_0.h>
@@ -210,6 +212,43 @@
return isOutputDevice(stringToAudioDevice(device));
}
+static inline bool isVendorExtension(const std::string& device) {
+ // Must match the "vendorExtension" rule from the XSD file.
+ static const std::string vendorPrefix = "VX_";
+ return device.size() > vendorPrefix.size() &&
+ device.substr(0, vendorPrefix.size()) == vendorPrefix &&
+ std::all_of(device.begin() + vendorPrefix.size(), device.end(),
+ [](unsigned char c) { return c == '_' || std::isalnum(c); });
+}
+
+static inline bool isUnknownAudioChannelMask(const std::string& mask) {
+ return stringToAudioChannelMask(mask) == AudioChannelMask::UNKNOWN;
+}
+
+static inline bool isUnknownAudioDevice(const std::string& device) {
+ return stringToAudioDevice(device) == AudioDevice::UNKNOWN && !isVendorExtension(device);
+}
+
+static inline bool isUnknownAudioFormat(const std::string& format) {
+ return stringToAudioFormat(format) == AudioFormat::UNKNOWN && !isVendorExtension(format);
+}
+
+static inline bool isUnknownAudioGainMode(const std::string& mode) {
+ return stringToAudioGainMode(mode) == AudioGainMode::UNKNOWN;
+}
+
+static inline bool isUnknownAudioSource(const std::string& source) {
+ return stringToAudioSource(source) == AudioSource::UNKNOWN;
+}
+
+static inline bool isUnknownAudioStreamType(const std::string& streamType) {
+ return stringToAudioStreamType(streamType) == AudioStreamType::UNKNOWN;
+}
+
+static inline bool isUnknownAudioUsage(const std::string& usage) {
+ return stringToAudioUsage(usage) == AudioUsage::UNKNOWN;
+}
+
} // namespace android::audio::policy::configuration::V7_0
#endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 631d524..ed56c73 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -118,9 +118,9 @@
* Base configuration attributes applicable to any stream of audio.
*/
struct AudioConfigBase {
- AudioFormat format; // 'DEFAULT' means 'unspecified'
+ AudioFormat format; // empty means 'unspecified'
uint32_t sampleRateHz; // 0 means 'unspecified'
- vec<AudioChannelMask> channelMask; // empty means 'unspecified'
+ AudioChannelMask channelMask; // empty means 'unspecified'
};
/**
@@ -167,10 +167,18 @@
AudioDevice deviceType;
safe_union Address {
/**
- * The address may be left unspecified if 'device' specifies
- * a physical device unambiguously.
+ * String uniquely identifying the device among other devices
+ * of the same type. Can be empty in case there is only one device
+ * of this type.
+ *
+ * Depending on the device type, its id may be assigned by the framework
+ * (this is done for REMOTE_SUBMIX), or specified in the audio policy
+ * configuration file (typically done for BUS devices), or assigned
+ * by the HAL service. In any case, both framework and HAL must
+ * never attempt to parse the value of the id. If the address must
+ * be parsed, one of the members below must be used instead of 'id'.
*/
- Monostate unspecified;
+ string id;
/** IEEE 802 MAC address. Set for Bluetooth devices. */
uint8_t[6] mac;
/** IPv4 Address. Set for IPv4 devices. */
@@ -182,10 +190,6 @@
int32_t card;
int32_t device;
} alsa;
- /** Arbitrary BUS device unique address. Not interpreted by the framework. */
- string bus;
- /** Arbitrary REMOTE_SUBMIX device unique address. Not interpreted by the HAL. */
- string rSubmix;
} address;
};
@@ -328,14 +332,22 @@
* A gain stage is always attached to an audio port.
*/
struct AudioGain {
- vec<AudioGainMode> mode; // modes of operation
- AudioChannelMask channelMask; // channels which gain can be controlled
- int32_t minValue; // minimum gain value in millibels
- int32_t maxValue; // maximum gain value in millibels
- int32_t defaultValue; // default gain value in millibels
- uint32_t stepValue; // gain step in millibels
- uint32_t minRampMs; // minimum ramp duration in ms
- uint32_t maxRampMs; // maximum ramp duration in ms
+ /** Modes of operation. */
+ vec<AudioGainMode> mode;
+ /** Channels which gain can be controlled. */
+ AudioChannelMask channelMask;
+ /** Minimum gain value in millibels. */
+ int32_t minValue;
+ /** Maximum gain value in millibels. */
+ int32_t maxValue;
+ /** Default gain value in millibels. */
+ int32_t defaultValue;
+ /** Gain step in millibels. */
+ uint32_t stepValue;
+ /** Ramp duration in ms. */
+ uint32_t minRampMs;
+ /** Maximum ramp duration in ms. */
+ uint32_t maxRampMs;
};
/**
@@ -343,16 +355,20 @@
* given port.
*/
struct AudioGainConfig {
- int32_t index; // index of the corresponding AudioGain in AudioPort.gains
- vec<AudioGainMode> mode; // modes of operation
- AudioChannelMask channelMask; // channels which gain value follows
+ /** Index of the corresponding AudioGain in AudioPort.gains. */
+ int32_t index;
+ /** Modes of operation. */
+ vec<AudioGainMode> mode;
+ /** Channels which gain value follows. */
+ AudioChannelMask channelMask;
/**
* Gain values in millibels for each channel ordered from LSb to MSb in
* channel mask. The number of values is 1 in joint mode or
- * popcount(channel_mask).
+ * the number of channels in the channel mask.
*/
- int32_t[4 * 8] values;
- uint32_t rampDurationMs; // ramp duration in ms
+ vec<int32_t> values;
+ /** Ramp duration in ms. */
+ uint32_t rampDurationMs;
};
@@ -409,7 +425,7 @@
* parameters (or none) may be set. See the documentation of the
* AudioConfigBase struct.
*/
- AudioConfigBase config;
+ AudioConfigBase base;
/** Associated gain control. */
safe_union OptionalGain {
Monostate unspecified;
@@ -439,6 +455,8 @@
vec<AudioProfile> profiles;
/** List of gain controls attached to the port. */
vec<AudioGain> gains;
+ /** Parameters that depend on the actual port role. */
+ AudioPortExtendedInfo ext;
/**
* Current configuration of the audio port, may have all the fields left
* unspecified.
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
new file mode 100644
index 0000000..1a66282
--- /dev/null
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -0,0 +1,847 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#define LOG_TAG "HidlUtils"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <common/all-versions/VersionUtils.h>
+
+#include "HidlUtils.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace CPP_VERSION {
+namespace implementation {
+
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+#define CONVERT_CHECKED(expr, result) \
+ if (status_t status = (expr); status != NO_ERROR) { \
+ result = status; \
+ }
+
+status_t HidlUtils::audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask) {
+ *channelMask = audio_channel_index_mask_to_string(halChannelMask);
+ if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown index channel mask value 0x%X", halChannelMask);
+ *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioInputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask) {
+ *channelMask = audio_channel_in_mask_to_string(halChannelMask);
+ if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown input channel mask value 0x%X", halChannelMask);
+ *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioOutputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask) {
+ *channelMask = audio_channel_out_mask_to_string(halChannelMask);
+ if (!channelMask->empty() && !xsd::isUnknownAudioChannelMask(*channelMask)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown output channel mask value 0x%X", halChannelMask);
+ *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput,
+ AudioChannelMask* channelMask) {
+ if (halChannelMask != AUDIO_CHANNEL_NONE) {
+ if (audio_channel_mask_is_valid(halChannelMask)) {
+ switch (audio_channel_mask_get_representation(halChannelMask)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ return isInput ? audioInputChannelMaskFromHal(halChannelMask, channelMask)
+ : audioOutputChannelMaskFromHal(halChannelMask, channelMask);
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ // Index masks do not have direction.
+ return audioIndexChannelMaskFromHal(halChannelMask, channelMask);
+ // no default
+ }
+ }
+ *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return BAD_VALUE;
+ }
+ *channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return NO_ERROR;
+}
+
+status_t HidlUtils::audioChannelMaskToHal(const AudioChannelMask& channelMask,
+ audio_channel_mask_t* halChannelMask) {
+ if (!xsd::isUnknownAudioChannelMask(channelMask) &&
+ audio_channel_mask_from_string(channelMask.c_str(), halChannelMask)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown channel mask \"%s\"", channelMask.c_str());
+ *halChannelMask = AUDIO_CHANNEL_NONE;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioConfigBaseFromHal(const audio_config_base_t& halConfigBase, bool isInput,
+ AudioConfigBase* configBase) {
+ status_t result = NO_ERROR;
+ configBase->sampleRateHz = halConfigBase.sample_rate;
+ CONVERT_CHECKED(
+ audioChannelMaskFromHal(halConfigBase.channel_mask, isInput, &configBase->channelMask),
+ result);
+ CONVERT_CHECKED(audioFormatFromHal(halConfigBase.format, &configBase->format), result);
+ return result;
+}
+
+status_t HidlUtils::audioConfigBaseToHal(const AudioConfigBase& configBase,
+ audio_config_base_t* halConfigBase) {
+ status_t result = NO_ERROR;
+ halConfigBase->sample_rate = configBase.sampleRateHz;
+ CONVERT_CHECKED(audioChannelMaskToHal(configBase.channelMask, &halConfigBase->channel_mask),
+ result);
+ CONVERT_CHECKED(audioFormatToHal(configBase.format, &halConfigBase->format), result);
+ return result;
+}
+
+status_t HidlUtils::audioDeviceTypeFromHal(audio_devices_t halDevice, AudioDevice* device) {
+ *device = audio_device_to_string(halDevice);
+ if (!device->empty() && !xsd::isUnknownAudioDevice(*device)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio device value 0x%X", halDevice);
+ *device = toString(xsd::AudioDevice::AUDIO_DEVICE_NONE);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioDeviceTypeToHal(const AudioDevice& device, audio_devices_t* halDevice) {
+ if (!xsd::isUnknownAudioDevice(device) && audio_device_from_string(device.c_str(), halDevice)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio device \"%s\"", device.c_str());
+ *halDevice = AUDIO_DEVICE_NONE;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioFormatFromHal(audio_format_t halFormat, AudioFormat* format) {
+ *format = audio_format_to_string(halFormat);
+ if (!format->empty() && !xsd::isUnknownAudioFormat(*format)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio format value 0x%X", halFormat);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioFormatToHal(const AudioFormat& format, audio_format_t* halFormat) {
+ if (!xsd::isUnknownAudioFormat(format) && audio_format_from_string(format.c_str(), halFormat)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio format \"%s\"", format.c_str());
+ *halFormat = AUDIO_FORMAT_DEFAULT;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioGainModeMaskFromHal(audio_gain_mode_t halGainModeMask,
+ hidl_vec<AudioGainMode>* gainModeMask) {
+ status_t status = NO_ERROR;
+ std::vector<AudioGainMode> result;
+ for (uint32_t bit = 0; bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
+ audio_gain_mode_t flag = static_cast<audio_gain_mode_t>(1u << bit);
+ if ((flag & halGainModeMask) == flag) {
+ AudioGainMode flagStr = audio_gain_mode_to_string(flag);
+ if (!flagStr.empty() && !xsd::isUnknownAudioGainMode(flagStr)) {
+ result.push_back(flagStr);
+ } else {
+ ALOGE("Unknown audio gain mode value 0x%X", flag);
+ status = BAD_VALUE;
+ }
+ }
+ }
+ *gainModeMask = result;
+ return status;
+}
+
+status_t HidlUtils::audioGainModeMaskToHal(const hidl_vec<AudioGainMode>& gainModeMask,
+ audio_gain_mode_t* halGainModeMask) {
+ status_t status = NO_ERROR;
+ *halGainModeMask = {};
+ for (const auto& gainMode : gainModeMask) {
+ audio_gain_mode_t halGainMode;
+ if (!xsd::isUnknownAudioGainMode(gainMode) &&
+ audio_gain_mode_from_string(gainMode.c_str(), &halGainMode)) {
+ *halGainModeMask = static_cast<audio_gain_mode_t>(*halGainModeMask | halGainMode);
+ } else {
+ ALOGE("Unknown audio gain mode \"%s\"", gainMode.c_str());
+ status = BAD_VALUE;
+ }
+ }
+ return status;
+}
+
+status_t HidlUtils::audioSourceFromHal(audio_source_t halSource, AudioSource* source) {
+ *source = audio_source_to_string(halSource);
+ if (!source->empty() && !xsd::isUnknownAudioSource(*source)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio source value 0x%X", halSource);
+ *source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioSourceToHal(const AudioSource& source, audio_source_t* halSource) {
+ if (!xsd::isUnknownAudioSource(source) && audio_source_from_string(source.c_str(), halSource)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio source \"%s\"", source.c_str());
+ *halSource = AUDIO_SOURCE_DEFAULT;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioStreamTypeFromHal(audio_stream_type_t halStreamType,
+ AudioStreamType* streamType) {
+ *streamType = audio_stream_type_to_string(halStreamType);
+ if (!streamType->empty() && !xsd::isUnknownAudioStreamType(*streamType)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio stream type value 0x%X", halStreamType);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioStreamTypeToHal(const AudioStreamType& streamType,
+ audio_stream_type_t* halStreamType) {
+ if (!xsd::isUnknownAudioStreamType(streamType) &&
+ audio_stream_type_from_string(streamType.c_str(), halStreamType)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio stream type \"%s\"", streamType.c_str());
+ *halStreamType = AUDIO_STREAM_DEFAULT;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, bool isInput,
+ AudioConfig* config) {
+ status_t result = NO_ERROR;
+ audio_config_base_t halConfigBase = {halConfig.sample_rate, halConfig.channel_mask,
+ halConfig.format};
+ CONVERT_CHECKED(audioConfigBaseFromHal(halConfigBase, isInput, &config->base), result);
+ CONVERT_CHECKED(audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo), result);
+ config->frameCount = halConfig.frame_count;
+ return result;
+}
+
+status_t HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
+ status_t result = NO_ERROR;
+ *halConfig = AUDIO_CONFIG_INITIALIZER;
+ audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
+ CONVERT_CHECKED(audioConfigBaseToHal(config.base, &halConfigBase), result);
+ halConfig->sample_rate = halConfigBase.sample_rate;
+ halConfig->channel_mask = halConfigBase.channel_mask;
+ halConfig->format = halConfigBase.format;
+ CONVERT_CHECKED(audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info), result);
+ halConfig->frame_count = config.frameCount;
+ return result;
+}
+
+status_t HidlUtils::audioGainConfigFromHal(const struct audio_gain_config& halConfig, bool isInput,
+ AudioGainConfig* config) {
+ status_t result = NO_ERROR;
+ config->index = halConfig.index;
+ CONVERT_CHECKED(audioGainModeMaskFromHal(halConfig.mode, &config->mode), result);
+ CONVERT_CHECKED(audioChannelMaskFromHal(halConfig.channel_mask, isInput, &config->channelMask),
+ result);
+ if (halConfig.mode & AUDIO_GAIN_MODE_JOINT) {
+ config->values.resize(1);
+ config->values[0] = halConfig.values[0];
+ }
+ if (halConfig.mode & (AUDIO_GAIN_MODE_CHANNELS | AUDIO_GAIN_MODE_RAMP)) {
+ config->values.resize(__builtin_popcount(halConfig.channel_mask));
+ for (size_t i = 0; i < config->values.size(); ++i) {
+ config->values[i] = halConfig.values[i];
+ }
+ }
+ config->rampDurationMs = halConfig.ramp_duration_ms;
+ return result;
+}
+
+status_t HidlUtils::audioGainConfigToHal(const AudioGainConfig& config,
+ struct audio_gain_config* halConfig) {
+ status_t result = NO_ERROR;
+ halConfig->index = config.index;
+ CONVERT_CHECKED(audioGainModeMaskToHal(config.mode, &halConfig->mode), result);
+ CONVERT_CHECKED(audioChannelMaskToHal(config.channelMask, &halConfig->channel_mask), result);
+ memset(halConfig->values, 0, sizeof(halConfig->values));
+ if (halConfig->mode & AUDIO_GAIN_MODE_JOINT) {
+ if (config.values.size() > 0) {
+ halConfig->values[0] = config.values[0];
+ } else {
+ ALOGE("Empty values vector in AudioGainConfig");
+ result = BAD_VALUE;
+ }
+ }
+ if (halConfig->mode & (AUDIO_GAIN_MODE_CHANNELS | AUDIO_GAIN_MODE_RAMP)) {
+ size_t channelCount = __builtin_popcount(halConfig->channel_mask);
+ size_t valuesCount = config.values.size();
+ if (channelCount != valuesCount) {
+ ALOGE("Wrong number of values in AudioGainConfig, expected: %zu, found: %zu",
+ channelCount, valuesCount);
+ result = BAD_VALUE;
+ if (channelCount < valuesCount) {
+ valuesCount = channelCount;
+ }
+ }
+ for (size_t i = 0; i < valuesCount; ++i) {
+ halConfig->values[i] = config.values[i];
+ }
+ }
+ halConfig->ramp_duration_ms = config.rampDurationMs;
+ return result;
+}
+
+status_t HidlUtils::audioGainFromHal(const struct audio_gain& halGain, bool isInput,
+ AudioGain* gain) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioGainModeMaskFromHal(halGain.mode, &gain->mode), result);
+ CONVERT_CHECKED(audioChannelMaskFromHal(halGain.channel_mask, isInput, &gain->channelMask),
+ result);
+ gain->minValue = halGain.min_value;
+ gain->maxValue = halGain.max_value;
+ gain->defaultValue = halGain.default_value;
+ gain->stepValue = halGain.step_value;
+ gain->minRampMs = halGain.min_ramp_ms;
+ gain->maxRampMs = halGain.max_ramp_ms;
+ return result;
+}
+
+status_t HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioGainModeMaskToHal(gain.mode, &halGain->mode), result);
+ CONVERT_CHECKED(audioChannelMaskToHal(gain.channelMask, &halGain->channel_mask), result);
+ halGain->min_value = gain.minValue;
+ halGain->max_value = gain.maxValue;
+ halGain->default_value = gain.defaultValue;
+ halGain->step_value = gain.stepValue;
+ halGain->min_ramp_ms = gain.minRampMs;
+ halGain->max_ramp_ms = gain.maxRampMs;
+ return result;
+}
+
+status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
+ if (halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST ||
+ halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT ||
+ halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED ||
+ halUsage == AUDIO_USAGE_NOTIFICATION_EVENT) {
+ halUsage = AUDIO_USAGE_NOTIFICATION;
+ }
+ *usage = audio_usage_to_string(halUsage);
+ if (!usage->empty() && !xsd::isUnknownAudioUsage(*usage)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio usage %d", halUsage);
+ *usage = toString(xsd::AudioUsage::AUDIO_USAGE_UNKNOWN);
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioUsageToHal(const AudioUsage& usage, audio_usage_t* halUsage) {
+ if (!xsd::isUnknownAudioUsage(usage) && audio_usage_from_string(usage.c_str(), halUsage)) {
+ return NO_ERROR;
+ }
+ ALOGE("Unknown audio usage \"%s\"", usage.c_str());
+ *halUsage = AUDIO_USAGE_UNKNOWN;
+ return BAD_VALUE;
+}
+
+status_t HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
+ AudioOffloadInfo* offload) {
+ status_t result = NO_ERROR;
+ audio_config_base_t halConfigBase = {halOffload.sample_rate, halOffload.channel_mask,
+ halOffload.format};
+ CONVERT_CHECKED(audioConfigBaseFromHal(halConfigBase, false /*isInput*/, &offload->base),
+ result);
+ CONVERT_CHECKED(audioStreamTypeFromHal(halOffload.stream_type, &offload->streamType), result);
+ offload->bitRatePerSecond = halOffload.bit_rate;
+ offload->durationMicroseconds = halOffload.duration_us;
+ offload->hasVideo = halOffload.has_video;
+ offload->isStreaming = halOffload.is_streaming;
+ offload->bitWidth = halOffload.bit_width;
+ offload->bufferSize = halOffload.offload_buffer_size;
+ CONVERT_CHECKED(audioUsageFromHal(halOffload.usage, &offload->usage), result);
+ if (halOffload.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+ offload->encapsulationMode =
+ static_cast<AudioEncapsulationMode>(halOffload.encapsulation_mode);
+ offload->contentId = halOffload.content_id;
+ offload->syncId = halOffload.sync_id;
+ } else {
+ offload->encapsulationMode = AudioEncapsulationMode::NONE;
+ offload->contentId = 0;
+ offload->syncId = 0;
+ }
+ return result;
+}
+
+status_t HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload,
+ audio_offload_info_t* halOffload) {
+ status_t result = NO_ERROR;
+ *halOffload = AUDIO_INFO_INITIALIZER;
+ audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
+ CONVERT_CHECKED(audioConfigBaseToHal(offload.base, &halConfigBase), result);
+ halOffload->sample_rate = halConfigBase.sample_rate;
+ halOffload->channel_mask = halConfigBase.channel_mask;
+ halOffload->format = halConfigBase.format;
+ CONVERT_CHECKED(audioStreamTypeToHal(offload.streamType, &halOffload->stream_type), result);
+ halOffload->bit_rate = offload.bitRatePerSecond;
+ halOffload->duration_us = offload.durationMicroseconds;
+ halOffload->has_video = offload.hasVideo;
+ halOffload->is_streaming = offload.isStreaming;
+ halOffload->bit_width = offload.bitWidth;
+ halOffload->offload_buffer_size = offload.bufferSize;
+ CONVERT_CHECKED(audioUsageToHal(offload.usage, &halOffload->usage), result);
+ halOffload->encapsulation_mode =
+ static_cast<audio_encapsulation_mode_t>(offload.encapsulationMode);
+ halOffload->content_id = offload.contentId;
+ halOffload->sync_id = offload.syncId;
+ return result;
+}
+
+status_t HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig,
+ AudioPortConfig* config) {
+ status_t result = NO_ERROR;
+ bool isInput = false;
+ config->id = halConfig.id;
+ CONVERT_CHECKED(audioPortExtendedInfoFromHal(halConfig.role, halConfig.type,
+ halConfig.ext.device, halConfig.ext.mix,
+ halConfig.ext.session, &config->ext, &isInput),
+ result);
+ if (audio_port_config_has_input_direction(&halConfig) != isInput) {
+ ALOGE("Inconsistent port config direction data, is input: %d (hal) != %d (converter)",
+ audio_port_config_has_input_direction(&halConfig), isInput);
+ result = BAD_VALUE;
+ }
+ if (halConfig.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+ config->base.sampleRateHz = halConfig.sample_rate;
+ } else {
+ config->base.sampleRateHz = {};
+ }
+ if (halConfig.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+ CONVERT_CHECKED(
+ audioChannelMaskFromHal(halConfig.channel_mask, isInput, &config->base.channelMask),
+ result);
+ } else {
+ config->base.channelMask = {};
+ }
+ if (halConfig.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+ CONVERT_CHECKED(audioFormatFromHal(halConfig.format, &config->base.format), result);
+ } else {
+ config->base.format = {};
+ }
+ if (halConfig.config_mask & AUDIO_PORT_CONFIG_GAIN) {
+ config->gain.config({});
+ CONVERT_CHECKED(audioGainConfigFromHal(halConfig.gain, isInput, &config->gain.config()),
+ result);
+ } else {
+ config->gain.unspecified({});
+ }
+ return result;
+}
+
+status_t HidlUtils::audioPortConfigToHal(const AudioPortConfig& config,
+ struct audio_port_config* halConfig) {
+ status_t result = NO_ERROR;
+ memset(halConfig, 0, sizeof(audio_port_config));
+ halConfig->id = config.id;
+ halConfig->config_mask = {};
+ if (config.base.sampleRateHz != 0) {
+ halConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+ halConfig->sample_rate = config.base.sampleRateHz;
+ }
+ if (!config.base.channelMask.empty()) {
+ halConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+ CONVERT_CHECKED(audioChannelMaskToHal(config.base.channelMask, &halConfig->channel_mask),
+ result);
+ }
+ if (!config.base.format.empty()) {
+ halConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+ CONVERT_CHECKED(audioFormatToHal(config.base.format, &halConfig->format), result);
+ }
+ if (config.gain.getDiscriminator() ==
+ AudioPortConfig::OptionalGain::hidl_discriminator::config) {
+ halConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+ CONVERT_CHECKED(audioGainConfigToHal(config.gain.config(), &halConfig->gain), result);
+ }
+ CONVERT_CHECKED(audioPortExtendedInfoToHal(config.ext, &halConfig->role, &halConfig->type,
+ &halConfig->ext.device, &halConfig->ext.mix,
+ &halConfig->ext.session),
+ result);
+ return result;
+}
+
+status_t HidlUtils::audioPortExtendedInfoFromHal(
+ audio_port_role_t role, audio_port_type_t type,
+ const struct audio_port_config_device_ext& device,
+ const struct audio_port_config_mix_ext& mix,
+ const struct audio_port_config_session_ext& session, AudioPortExtendedInfo* ext,
+ bool* isInput) {
+ status_t result = NO_ERROR;
+ *isInput = false;
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ ext->unspecified({});
+ break;
+ case AUDIO_PORT_TYPE_DEVICE: {
+ *isInput = role == AUDIO_PORT_ROLE_SOURCE;
+ ext->device({});
+ CONVERT_CHECKED(deviceAddressFromHal(device.type, device.address, &ext->device()),
+ result);
+ break;
+ }
+ case AUDIO_PORT_TYPE_MIX: {
+ *isInput = role == AUDIO_PORT_ROLE_SINK;
+ ext->mix({});
+ ext->mix().ioHandle = mix.handle;
+ if (role == AUDIO_PORT_ROLE_SOURCE) {
+ ext->mix().useCase.stream({});
+ CONVERT_CHECKED(
+ audioStreamTypeFromHal(mix.usecase.stream, &ext->mix().useCase.stream()),
+ result);
+ } else if (role == AUDIO_PORT_ROLE_SINK) {
+ ext->mix().useCase.source({});
+ CONVERT_CHECKED(
+ audioSourceFromHal(mix.usecase.source, &ext->mix().useCase.source()),
+ result);
+ }
+ break;
+ }
+ case AUDIO_PORT_TYPE_SESSION: {
+ ext->session(session.session);
+ break;
+ }
+ }
+ return result;
+}
+
+status_t HidlUtils::audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext,
+ audio_port_role_t* role, audio_port_type_t* type,
+ struct audio_port_config_device_ext* device,
+ struct audio_port_config_mix_ext* mix,
+ struct audio_port_config_session_ext* session) {
+ status_t result = NO_ERROR;
+ switch (ext.getDiscriminator()) {
+ case AudioPortExtendedInfo::hidl_discriminator::unspecified:
+ *role = AUDIO_PORT_ROLE_NONE;
+ *type = AUDIO_PORT_TYPE_NONE;
+ break;
+ case AudioPortExtendedInfo::hidl_discriminator::device:
+ *role = xsd::isOutputDevice(ext.device().deviceType) ? AUDIO_PORT_ROLE_SINK
+ : AUDIO_PORT_ROLE_SOURCE;
+ *type = AUDIO_PORT_TYPE_DEVICE;
+ CONVERT_CHECKED(deviceAddressToHal(ext.device(), &device->type, device->address),
+ result);
+ break;
+ case AudioPortExtendedInfo::hidl_discriminator::mix:
+ *type = AUDIO_PORT_TYPE_MIX;
+ switch (ext.mix().useCase.getDiscriminator()) {
+ case AudioPortExtendedInfo::AudioPortMixExt::UseCase::hidl_discriminator::stream:
+ *role = AUDIO_PORT_ROLE_SOURCE;
+ CONVERT_CHECKED(
+ audioStreamTypeToHal(ext.mix().useCase.stream(), &mix->usecase.stream),
+ result);
+ break;
+ case AudioPortExtendedInfo::AudioPortMixExt::UseCase::hidl_discriminator::source:
+ *role = AUDIO_PORT_ROLE_SINK;
+ CONVERT_CHECKED(
+ audioSourceToHal(ext.mix().useCase.source(), &mix->usecase.source),
+ result);
+ break;
+ }
+ mix->handle = ext.mix().ioHandle;
+ break;
+ case AudioPortExtendedInfo::hidl_discriminator::session:
+ *role = AUDIO_PORT_ROLE_NONE;
+ *type = AUDIO_PORT_TYPE_SESSION;
+ session->session = static_cast<audio_session_t>(ext.session());
+ break;
+ }
+ return result;
+}
+
+status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
+ struct audio_port_v7 halPortV7 = {};
+ audio_populate_audio_port_v7(&halPort, &halPortV7);
+ return audioPortFromHal(halPortV7, port);
+}
+
+status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
+ status_t result = NO_ERROR;
+ struct audio_port_v7 halPortV7 = {};
+ CONVERT_CHECKED(audioPortToHal(port, &halPortV7), result);
+ if (!audio_populate_audio_port(&halPortV7, halPort)) {
+ result = BAD_VALUE;
+ }
+ return result;
+}
+
+status_t HidlUtils::audioPortFromHal(const struct audio_port_v7& halPort, AudioPort* port) {
+ status_t result = NO_ERROR;
+ bool isInput = false;
+ port->id = halPort.id;
+ port->name.setToExternal(halPort.name, strlen(halPort.name));
+ // HAL uses slightly different but convertible structures for the extended info in port
+ // and port config structures.
+ struct audio_port_config_device_ext halDevice = {};
+ struct audio_port_config_mix_ext halMix = {};
+ struct audio_port_config_session_ext halSession = {};
+ switch (halPort.type) {
+ case AUDIO_PORT_TYPE_NONE:
+ break;
+ case AUDIO_PORT_TYPE_DEVICE:
+ halDevice.type = halPort.ext.device.type;
+ memcpy(halDevice.address, halPort.ext.device.address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ halMix.handle = halPort.ext.mix.handle;
+ break;
+ case AUDIO_PORT_TYPE_SESSION:
+ halSession.session = halPort.ext.session.session;
+ break;
+ }
+ 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);
+ }
+ 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);
+ }
+ CONVERT_CHECKED(audioPortConfigFromHal(halPort.active_config, &port->activeConfig), result);
+ return result;
+}
+
+status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* halPort) {
+ status_t result = NO_ERROR;
+ halPort->id = port.id;
+ strncpy(halPort->name, port.name.c_str(), AUDIO_PORT_MAX_NAME_LEN);
+ halPort->name[AUDIO_PORT_MAX_NAME_LEN - 1] = '\0';
+ if (port.name.size() >= AUDIO_PORT_MAX_NAME_LEN) {
+ 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);
+ }
+ 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);
+ halPort->num_gains = AUDIO_PORT_MAX_GAINS;
+ result = BAD_VALUE;
+ }
+ for (size_t i = 0; i < halPort->num_gains; ++i) {
+ CONVERT_CHECKED(audioGainToHal(port.gains[i], &halPort->gains[i]), result);
+ }
+ // HAL uses slightly different but convertible structures for the extended info in port
+ // and port config structures.
+ struct audio_port_config_device_ext halDevice = {};
+ struct audio_port_config_mix_ext halMix = {};
+ struct audio_port_config_session_ext halSession = {};
+ CONVERT_CHECKED(audioPortExtendedInfoToHal(port.ext, &halPort->role, &halPort->type, &halDevice,
+ &halMix, &halSession),
+ result);
+ switch (halPort->type) {
+ case AUDIO_PORT_TYPE_NONE:
+ break;
+ case AUDIO_PORT_TYPE_DEVICE:
+ halPort->ext.device.type = halDevice.type;
+ memcpy(halPort->ext.device.address, halDevice.address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ halPort->ext.mix.handle = halMix.handle;
+ break;
+ case AUDIO_PORT_TYPE_SESSION:
+ halPort->ext.session.session = halSession.session;
+ break;
+ }
+ CONVERT_CHECKED(audioPortConfigToHal(port.activeConfig, &halPort->active_config), result);
+ return result;
+}
+
+status_t HidlUtils::audioProfileFromHal(const struct audio_profile& halProfile, bool isInput,
+ AudioProfile* profile) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioFormatFromHal(halProfile.format, &profile->format), result);
+ profile->sampleRates.resize(halProfile.num_sample_rates);
+ for (size_t i = 0; i < halProfile.num_sample_rates; ++i) {
+ profile->sampleRates[i] = halProfile.sample_rates[i];
+ }
+ profile->channelMasks.resize(halProfile.num_channel_masks);
+ for (size_t i = 0; i < halProfile.num_channel_masks; ++i) {
+ CONVERT_CHECKED(audioChannelMaskFromHal(halProfile.channel_masks[i], isInput,
+ &profile->channelMasks[i]),
+ result);
+ }
+ return result;
+}
+
+status_t HidlUtils::audioProfileToHal(const AudioProfile& profile,
+ struct audio_profile* halProfile) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioFormatToHal(profile.format, &halProfile->format), result);
+ memset(halProfile->sample_rates, 0, sizeof(halProfile->sample_rates));
+ halProfile->num_sample_rates = profile.sampleRates.size();
+ if (halProfile->num_sample_rates > AUDIO_PORT_MAX_SAMPLING_RATES) {
+ ALOGE("HIDL Audio profile has too many sample rates: %u", halProfile->num_sample_rates);
+ halProfile->num_sample_rates = AUDIO_PORT_MAX_SAMPLING_RATES;
+ result = BAD_VALUE;
+ }
+ for (size_t i = 0; i < halProfile->num_sample_rates; ++i) {
+ halProfile->sample_rates[i] = profile.sampleRates[i];
+ }
+ memset(halProfile->channel_masks, 0, sizeof(halProfile->channel_masks));
+ halProfile->num_channel_masks = profile.channelMasks.size();
+ if (halProfile->num_channel_masks > AUDIO_PORT_MAX_CHANNEL_MASKS) {
+ ALOGE("HIDL Audio profile has too many channel masks: %u", halProfile->num_channel_masks);
+ halProfile->num_channel_masks = AUDIO_PORT_MAX_CHANNEL_MASKS;
+ result = BAD_VALUE;
+ }
+ for (size_t i = 0; i < halProfile->num_channel_masks; ++i) {
+ CONVERT_CHECKED(
+ audioChannelMaskToHal(profile.channelMasks[i], &halProfile->channel_masks[i]),
+ status);
+ }
+ return result;
+}
+
+status_t HidlUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
+ const char* halDeviceAddress, DeviceAddress* device) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioDeviceTypeFromHal(halDeviceType, &device->deviceType), result);
+ if (audio_is_a2dp_out_device(halDeviceType) || audio_is_a2dp_in_device(halDeviceType)) {
+ device->address.mac({});
+ if (halDeviceAddress != nullptr) {
+ auto& mac = device->address.mac();
+ int status = sscanf(halDeviceAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1],
+ &mac[2], &mac[3], &mac[4], &mac[5]);
+ if (status != 6) {
+ ALOGE("BT A2DP device \"%s\" MAC address \"%s\" is invalid",
+ device->deviceType.c_str(), halDeviceAddress);
+ result = BAD_VALUE;
+ }
+ } else {
+ ALOGE("BT A2DP device \"%s\" does not have a MAC address", halDeviceAddress);
+ result = BAD_VALUE;
+ }
+ } else if (halDeviceType == AUDIO_DEVICE_OUT_IP || halDeviceType == AUDIO_DEVICE_IN_IP) {
+ device->address.ipv4({});
+ if (halDeviceAddress != nullptr) {
+ auto& ipv4 = device->address.ipv4();
+ int status = sscanf(halDeviceAddress, "%hhu.%hhu.%hhu.%hhu", &ipv4[0], &ipv4[1],
+ &ipv4[2], &ipv4[3]);
+ if (status != 4) {
+ ALOGE("IP device \"%s\" IPv4 address \"%s\" is invalid", device->deviceType.c_str(),
+ halDeviceAddress);
+ result = BAD_VALUE;
+ }
+ } else {
+ ALOGE("IP device \"%s\" does not have an IPv4 address", device->deviceType.c_str());
+ result = BAD_VALUE;
+ }
+ } else if (audio_is_usb_out_device(halDeviceType) || audio_is_usb_in_device(halDeviceType)) {
+ device->address.alsa({});
+ if (halDeviceAddress != nullptr) {
+ auto& alsa = device->address.alsa();
+ int status = sscanf(halDeviceAddress, "card=%d;device=%d", &alsa.card, &alsa.device);
+ if (status != 2) {
+ ALOGE("USB device \"%s\" ALSA address \"%s\" is invalid",
+ device->deviceType.c_str(), halDeviceAddress);
+ result = BAD_VALUE;
+ }
+ } else {
+ ALOGE("USB device \"%s\" does not have ALSA address", device->deviceType.c_str());
+ result = BAD_VALUE;
+ }
+ } else {
+ // Any other device type uses the 'id' field.
+ device->address.id(halDeviceAddress != nullptr ? halDeviceAddress : "");
+ }
+ return result;
+}
+
+status_t HidlUtils::deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+ char* halDeviceAddress) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(audioDeviceTypeToHal(device.deviceType, halDeviceType), result);
+ memset(halDeviceAddress, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ if (audio_is_a2dp_out_device(*halDeviceType) || audio_is_a2dp_in_device(*halDeviceType)) {
+ if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::mac) {
+ const auto& mac = device.address.mac();
+ snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+ "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4],
+ mac[5]);
+ } else {
+ ALOGE("BT A2DP device \"%s\" does not have MAC address set", device.deviceType.c_str());
+ result = BAD_VALUE;
+ }
+ } else if (*halDeviceType == AUDIO_DEVICE_OUT_IP || *halDeviceType == AUDIO_DEVICE_IN_IP) {
+ if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::ipv4) {
+ const auto& ipv4 = device.address.ipv4();
+ snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%d.%d.%d.%d", ipv4[0],
+ ipv4[1], ipv4[2], ipv4[3]);
+ } else {
+ ALOGE("IP device \"%s\" does not have IPv4 address set", device.deviceType.c_str());
+ result = BAD_VALUE;
+ }
+ } else if (audio_is_usb_out_device(*halDeviceType) || audio_is_usb_in_device(*halDeviceType)) {
+ if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::alsa) {
+ const auto& alsa = device.address.alsa();
+ snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d", alsa.card,
+ alsa.device);
+ } else {
+ ALOGE("USB device \"%s\" does not have ALSA address set", device.deviceType.c_str());
+ result = BAD_VALUE;
+ }
+ } else {
+ // Any other device type uses the 'id' field.
+ if (device.address.getDiscriminator() == DeviceAddress::Address::hidl_discriminator::id) {
+ snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%s",
+ device.address.id().c_str());
+ }
+ }
+ return result;
+}
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace common
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index a72c8dc..b83a58a 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -39,14 +39,19 @@
],
}
+filegroup {
+ name: "android.hardware.audio.common-util@2-6",
+ srcs: [
+ "HidlUtils.cpp",
+ "UuidUtils.cpp",
+ ],
+}
+
cc_defaults {
name: "android.hardware.audio.common-util_default",
defaults: ["hidl_defaults"],
vendor_available: true,
- srcs: [
- "HidlUtils.cpp",
- ],
export_include_dirs: ["."],
@@ -69,6 +74,7 @@
cc_library_shared {
name: "android.hardware.audio.common@2.0-util",
defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [":android.hardware.audio.common-util@2-6"],
shared_libs: [
"android.hardware.audio.common@2.0",
],
@@ -82,6 +88,7 @@
cc_library_shared {
name: "android.hardware.audio.common@4.0-util",
defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [":android.hardware.audio.common-util@2-6"],
shared_libs: [
"android.hardware.audio.common@4.0",
],
@@ -95,6 +102,7 @@
cc_library_shared {
name: "android.hardware.audio.common@5.0-util",
defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [":android.hardware.audio.common-util@2-6"],
shared_libs: [
"android.hardware.audio.common@5.0",
],
@@ -108,6 +116,7 @@
cc_library_shared {
name: "android.hardware.audio.common@6.0-util",
defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [":android.hardware.audio.common-util@2-6"],
shared_libs: [
"android.hardware.audio.common@6.0",
],
@@ -118,12 +127,18 @@
],
}
-cc_library_shared {
- enabled: false,
+cc_library {
name: "android.hardware.audio.common@7.0-util",
defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [
+ "7.0/HidlUtils.cpp",
+ "UuidUtils.cpp",
+ ],
shared_libs: [
"android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "libbase",
+ "libxml2",
],
cflags: [
"-DMAJOR_VERSION=7",
@@ -131,3 +146,35 @@
"-include common/all-versions/VersionMacro.h",
],
}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of conversion utilities.
+cc_test {
+ name: "android.hardware.audio.common@7.0-util_tests",
+ defaults: ["android.hardware.audio.common-util_default"],
+
+ srcs: ["tests/hidlutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.
+ static_libs: [
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.common@7.0",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/common/all-versions/default/HidlUtils.cpp b/audio/common/all-versions/default/HidlUtils.cpp
index a470c9c..ab3c1c7 100644
--- a/audio/common/all-versions/default/HidlUtils.cpp
+++ b/audio/common/all-versions/default/HidlUtils.cpp
@@ -37,13 +37,14 @@
return status;
}
-void HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
+status_t HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
memset(halConfig, 0, sizeof(audio_config_t));
halConfig->sample_rate = config.sampleRateHz;
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
halConfig->format = static_cast<audio_format_t>(config.format);
audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info);
halConfig->frame_count = config.frameCount;
+ return NO_ERROR;
}
void HidlUtils::audioGainConfigFromHal(const struct audio_gain_config& halConfig,
@@ -57,8 +58,8 @@
config->rampDurationMs = halConfig.ramp_duration_ms;
}
-void HidlUtils::audioGainConfigToHal(const AudioGainConfig& config,
- struct audio_gain_config* halConfig) {
+status_t HidlUtils::audioGainConfigToHal(const AudioGainConfig& config,
+ struct audio_gain_config* halConfig) {
halConfig->index = config.index;
halConfig->mode = static_cast<audio_gain_mode_t>(config.mode);
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
@@ -67,6 +68,7 @@
halConfig->values[i] = config.values[i];
}
halConfig->ramp_duration_ms = config.rampDurationMs;
+ return NO_ERROR;
}
void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
@@ -80,7 +82,7 @@
gain->maxRampMs = halGain.max_ramp_ms;
}
-void HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
+status_t HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
halGain->mode = static_cast<audio_gain_mode_t>(gain.mode);
halGain->channel_mask = static_cast<audio_channel_mask_t>(gain.channelMask);
halGain->min_value = gain.minValue;
@@ -89,22 +91,26 @@
halGain->step_value = gain.stepValue;
halGain->min_ramp_ms = gain.minRampMs;
halGain->max_ramp_ms = gain.maxRampMs;
+ return NO_ERROR;
}
-AudioUsage HidlUtils::audioUsageFromHal(const audio_usage_t halUsage) {
+status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
switch (halUsage) {
case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
case AUDIO_USAGE_NOTIFICATION_EVENT:
- return AudioUsage::NOTIFICATION;
+ *usage = AudioUsage::NOTIFICATION;
+ break;
default:
- return static_cast<AudioUsage>(halUsage);
+ *usage = static_cast<AudioUsage>(halUsage);
}
+ return NO_ERROR;
}
-audio_usage_t HidlUtils::audioUsageToHal(const AudioUsage usage) {
- return static_cast<audio_usage_t>(usage);
+status_t HidlUtils::audioUsageToHal(const AudioUsage& usage, audio_usage_t* halUsage) {
+ *halUsage = static_cast<audio_usage_t>(usage);
+ return NO_ERROR;
}
status_t HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
@@ -119,7 +125,7 @@
offload->isStreaming = halOffload.is_streaming;
offload->bitWidth = halOffload.bit_width;
offload->bufferSize = halOffload.offload_buffer_size;
- offload->usage = audioUsageFromHal(halOffload.usage);
+ audioUsageFromHal(halOffload.usage, &offload->usage);
#if MAJOR_VERSION >= 6
if (halOffload.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
offload->encapsulationMode =
@@ -139,11 +145,11 @@
return BAD_VALUE;
}
#endif
- return OK;
+ return NO_ERROR;
}
-void HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload,
- audio_offload_info_t* halOffload) {
+status_t HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload,
+ audio_offload_info_t* halOffload) {
*halOffload = AUDIO_INFO_INITIALIZER;
halOffload->sample_rate = offload.sampleRateHz;
halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
@@ -155,7 +161,7 @@
halOffload->is_streaming = offload.isStreaming;
halOffload->bit_width = offload.bitWidth;
halOffload->offload_buffer_size = offload.bufferSize;
- halOffload->usage = audioUsageToHal(offload.usage);
+ audioUsageToHal(offload.usage, &halOffload->usage);
#if MAJOR_VERSION >= 6
halOffload->encapsulation_mode =
static_cast<audio_encapsulation_mode_t>(offload.encapsulationMode);
@@ -164,10 +170,11 @@
#else
// offload doesn't contain encapsulationMode, contentId, syncId, so this is OK.
#endif
+ return NO_ERROR;
}
-void HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig,
- AudioPortConfig* config) {
+status_t HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig,
+ AudioPortConfig* config) {
config->id = halConfig.id;
config->role = AudioPortRole(halConfig.role);
config->type = AudioPortType(halConfig.type);
@@ -201,10 +208,11 @@
break;
}
}
+ return NO_ERROR;
}
-void HidlUtils::audioPortConfigToHal(const AudioPortConfig& config,
- struct audio_port_config* halConfig) {
+status_t HidlUtils::audioPortConfigToHal(const AudioPortConfig& config,
+ struct audio_port_config* halConfig) {
memset(halConfig, 0, sizeof(audio_port_config));
halConfig->id = config.id;
halConfig->role = static_cast<audio_port_role_t>(config.role);
@@ -242,27 +250,10 @@
break;
}
}
+ return NO_ERROR;
}
-void HidlUtils::audioPortConfigsFromHal(unsigned int numHalConfigs,
- const struct audio_port_config* halConfigs,
- hidl_vec<AudioPortConfig>* configs) {
- configs->resize(numHalConfigs);
- for (unsigned int i = 0; i < numHalConfigs; ++i) {
- audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
- }
-}
-
-std::unique_ptr<audio_port_config[]> HidlUtils::audioPortConfigsToHal(
- const hidl_vec<AudioPortConfig>& configs) {
- std::unique_ptr<audio_port_config[]> halConfigs(new audio_port_config[configs.size()]);
- for (size_t i = 0; i < configs.size(); ++i) {
- audioPortConfigToHal(configs[i], &halConfigs[i]);
- }
- return halConfigs;
-}
-
-void HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
+status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
port->id = halPort.id;
port->role = AudioPortRole(halPort.role);
port->type = AudioPortType(halPort.type);
@@ -305,9 +296,10 @@
break;
}
}
+ return NO_ERROR;
}
-void HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
+status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
memset(halPort, 0, sizeof(audio_port));
halPort->id = port.id;
halPort->role = static_cast<audio_port_role_t>(port.role);
@@ -356,22 +348,7 @@
break;
}
}
-}
-
-void HidlUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
- uuid->timeLow = halUuid.timeLow;
- uuid->timeMid = halUuid.timeMid;
- uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
- uuid->variantAndClockSeqHigh = halUuid.clockSeq;
- memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
-}
-
-void HidlUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
- halUuid->timeLow = uuid.timeLow;
- halUuid->timeMid = uuid.timeMid;
- halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
- halUuid->clockSeq = uuid.variantAndClockSeqHigh;
- memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
+ return NO_ERROR;
}
} // namespace implementation
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index ef6dee3..4e609ca 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -34,40 +34,123 @@
using namespace ::android::hardware::audio::common::CPP_VERSION;
-class HidlUtils {
- public:
- // A failure here indicates a platform config that is incompatible with
- // the compiled HIDL interface version.
+struct HidlUtils {
+#if MAJOR_VERSION < 7
static status_t audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config);
-
- static void audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
static void audioGainConfigFromHal(const struct audio_gain_config& halConfig,
AudioGainConfig* config);
- static void audioGainConfigToHal(const AudioGainConfig& config,
- struct audio_gain_config* halConfig);
static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain);
- static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
- static AudioUsage audioUsageFromHal(const audio_usage_t halUsage);
- static audio_usage_t audioUsageToHal(const AudioUsage usage);
- // A failure here indicates a platform offload info that is incompatible with
- // the compiled HIDL interface version.
+#else
+ static status_t audioConfigFromHal(const audio_config_t& halConfig, bool isInput,
+ AudioConfig* config);
+ static status_t audioGainConfigFromHal(const struct audio_gain_config& halConfig, bool isInput,
+ AudioGainConfig* config);
+ static status_t audioGainFromHal(const struct audio_gain& halGain, bool isInput,
+ AudioGain* gain);
+#endif
+ static status_t audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
+ static status_t audioGainConfigToHal(const AudioGainConfig& config,
+ struct audio_gain_config* halConfig);
+ static status_t audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
+ static status_t audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage);
+ static status_t audioUsageToHal(const AudioUsage& usage, audio_usage_t* halUsage);
static status_t audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
AudioOffloadInfo* offload);
- static void audioOffloadInfoToHal(const AudioOffloadInfo& offload,
- audio_offload_info_t* halOffload);
- static void audioPortConfigFromHal(const struct audio_port_config& halConfig,
- AudioPortConfig* config);
- static void audioPortConfigToHal(const AudioPortConfig& config,
- struct audio_port_config* halConfig);
- static void audioPortConfigsFromHal(unsigned int numHalConfigs,
- const struct audio_port_config* halConfigs,
- hidl_vec<AudioPortConfig>* configs);
+ static status_t audioOffloadInfoToHal(const AudioOffloadInfo& offload,
+ audio_offload_info_t* halOffload);
+ static status_t audioPortConfigFromHal(const struct audio_port_config& halConfig,
+ AudioPortConfig* config);
+ static status_t audioPortConfigToHal(const AudioPortConfig& config,
+ struct audio_port_config* halConfig);
+ static status_t audioPortConfigsFromHal(unsigned int numHalConfigs,
+ const struct audio_port_config* halConfigs,
+ hidl_vec<AudioPortConfig>* configs) {
+ status_t result = NO_ERROR;
+ configs->resize(numHalConfigs);
+ for (unsigned int i = 0; i < numHalConfigs; ++i) {
+ if (status_t status = audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
+ status != NO_ERROR) {
+ result = status;
+ }
+ }
+ return result;
+ }
+ static status_t audioPortConfigsToHal(const hidl_vec<AudioPortConfig>& configs,
+ std::unique_ptr<audio_port_config[]>* halConfigs) {
+ status_t result = NO_ERROR;
+ halConfigs->reset(new audio_port_config[configs.size()]);
+ for (size_t i = 0; i < configs.size(); ++i) {
+ if (status_t status = audioPortConfigToHal(configs[i], &(*halConfigs)[i]);
+ status != NO_ERROR) {
+ result = status;
+ }
+ }
+ return result;
+ }
+
+ // PLEASE DO NOT USE, will be removed in a couple of days
static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal(
- const hidl_vec<AudioPortConfig>& configs);
- static void audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
- static void audioPortToHal(const AudioPort& port, struct audio_port* halPort);
- static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
- static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+ const hidl_vec<AudioPortConfig>& configs) {
+ std::unique_ptr<audio_port_config[]> halConfigs;
+ (void)audioPortConfigsToHal(configs, &halConfigs);
+ return halConfigs;
+ }
+
+ static status_t audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
+ static status_t audioPortToHal(const AudioPort& port, struct audio_port* halPort);
+#if MAJOR_VERSION >= 7
+ static status_t audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput,
+ AudioChannelMask* channelMask);
+ static status_t audioChannelMaskToHal(const AudioChannelMask& channelMask,
+ audio_channel_mask_t* halChannelMask);
+ static status_t audioConfigBaseFromHal(const audio_config_base_t& halConfigBase, bool isInput,
+ AudioConfigBase* configBase);
+ static status_t audioConfigBaseToHal(const AudioConfigBase& configBase,
+ audio_config_base_t* halConfigBase);
+ static status_t audioDeviceTypeFromHal(audio_devices_t halDevice, AudioDevice* device);
+ static status_t audioDeviceTypeToHal(const AudioDevice& device, audio_devices_t* halDevice);
+ static status_t audioFormatFromHal(audio_format_t halFormat, AudioFormat* format);
+ static status_t audioFormatToHal(const AudioFormat& format, audio_format_t* halFormat);
+ static status_t audioGainModeMaskFromHal(audio_gain_mode_t halGainModeMask,
+ hidl_vec<AudioGainMode>* gainModeMask);
+ static status_t audioGainModeMaskToHal(const hidl_vec<AudioGainMode>& gainModeMask,
+ audio_gain_mode_t* halGainModeMask);
+ static status_t audioPortFromHal(const struct audio_port_v7& halPort, AudioPort* port);
+ static status_t audioPortToHal(const AudioPort& port, struct audio_port_v7* halPort);
+ static status_t audioProfileFromHal(const struct audio_profile& halProfile, bool isInput,
+ AudioProfile* profile);
+ static status_t audioProfileToHal(const AudioProfile& profile,
+ struct audio_profile* halProfile);
+ static status_t audioSourceFromHal(audio_source_t halSource, AudioSource* source);
+ static status_t audioSourceToHal(const AudioSource& source, audio_source_t* halSource);
+ static status_t audioStreamTypeFromHal(audio_stream_type_t halStreamType,
+ AudioStreamType* streamType);
+ static status_t audioStreamTypeToHal(const AudioStreamType& streamType,
+ audio_stream_type_t* halStreamType);
+ static status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+ char* halDeviceAddress);
+ static status_t deviceAddressFromHal(audio_devices_t halDeviceType,
+ const char* halDeviceAddress, DeviceAddress* device);
+
+ private:
+ static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask);
+ static status_t audioInputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask);
+ static status_t audioOutputChannelMaskFromHal(audio_channel_mask_t halChannelMask,
+ AudioChannelMask* channelMask);
+ static status_t audioPortExtendedInfoFromHal(
+ audio_port_role_t role, audio_port_type_t type,
+ const struct audio_port_config_device_ext& device,
+ const struct audio_port_config_mix_ext& mix,
+ const struct audio_port_config_session_ext& session, AudioPortExtendedInfo* ext,
+ bool* isInput);
+ static status_t audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext,
+ audio_port_role_t* role, audio_port_type_t* type,
+ struct audio_port_config_device_ext* device,
+ struct audio_port_config_mix_ext* mix,
+ struct audio_port_config_session_ext* session);
+#endif
};
} // namespace implementation
diff --git a/audio/common/all-versions/default/TEST_MAPPING b/audio/common/all-versions/default/TEST_MAPPING
new file mode 100644
index 0000000..4316ccf
--- /dev/null
+++ b/audio/common/all-versions/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "android.hardware.audio.common@7.0-util_tests"
+ }
+ ]
+}
diff --git a/audio/common/all-versions/default/UuidUtils.cpp b/audio/common/all-versions/default/UuidUtils.cpp
new file mode 100644
index 0000000..85edc7b
--- /dev/null
+++ b/audio/common/all-versions/default/UuidUtils.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "UuidUtils.h"
+
+#include <common/all-versions/VersionUtils.h>
+#include <string.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace CPP_VERSION {
+namespace implementation {
+
+void UuidUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
+ uuid->timeLow = halUuid.timeLow;
+ uuid->timeMid = halUuid.timeMid;
+ uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
+ uuid->variantAndClockSeqHigh = halUuid.clockSeq;
+ memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
+}
+
+void UuidUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
+ halUuid->timeLow = uuid.timeLow;
+ halUuid->timeMid = uuid.timeMid;
+ halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
+ halUuid->clockSeq = uuid.variantAndClockSeqHigh;
+ memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
+}
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace common
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/common/all-versions/default/UuidUtils.h b/audio/common/all-versions/default/UuidUtils.h
new file mode 100644
index 0000000..38db48a
--- /dev/null
+++ b/audio/common/all-versions/default/UuidUtils.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_Uuid_Utils_H_
+#define android_hardware_audio_Uuid_Utils_H_
+
+// clang-format off
+#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// clang-format on
+
+#include <system/audio.h>
+
+using ::android::hardware::hidl_vec;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace CPP_VERSION {
+namespace implementation {
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+
+class UuidUtils {
+ public:
+ static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
+ static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+};
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace common
+} // namespace audio
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_audio_Uuid_Utils_H_
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
new file mode 100644
index 0000000..bfc99e6
--- /dev/null
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "HidlUtils_Test"
+#include <log/log.h>
+
+#include <HidlUtils.h>
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <system/audio.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+static constexpr audio_channel_mask_t kInvalidHalChannelMask =
+ static_cast<audio_channel_mask_t>(0xFFFFFFFFU);
+static constexpr audio_devices_t kInvalidHalDevice = static_cast<audio_devices_t>(0xFFFFFFFFU);
+static constexpr audio_format_t kInvalidHalFormat = static_cast<audio_format_t>(0xFFFFFFFFU);
+static constexpr audio_gain_mode_t kInvalidHalGainMode =
+ static_cast<audio_gain_mode_t>(0xFFFFFFFFU);
+static constexpr audio_source_t kInvalidHalSource = static_cast<audio_source_t>(0xFFFFFFFFU);
+static constexpr audio_stream_type_t kInvalidHalStreamType =
+ static_cast<audio_stream_type_t>(0xFFFFFFFFU);
+static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU);
+
+TEST(HidlUtils, ConvertInvalidChannelMask) {
+ AudioChannelMask invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(AUDIO_CHANNEL_INVALID,
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(AUDIO_CHANNEL_INVALID, true /*isInput*/,
+ &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(kInvalidHalChannelMask,
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(kInvalidHalChannelMask,
+ true /*isInput*/, &invalid));
+ audio_channel_mask_t halInvalid;
+ // INVALID channel mask is not in XSD thus it's not allowed for transfer over HIDL.
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskToHal("AUDIO_CHANNEL_INVALID", &halInvalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskToHal("random string", &halInvalid));
+}
+
+// Might move these to the audio_policy_configuration_V7_0-enums library
+// if there would be usages in the default wrapper code. In that case,
+// it would be better to reimplement these methods using a proper switch statement
+// over all known enum values.
+static bool isInputChannelMask(xsd::AudioChannelMask channelMask) {
+ return toString(channelMask).find("_CHANNEL_IN_") != std::string::npos;
+}
+
+static bool isOutputChannelMask(xsd::AudioChannelMask channelMask) {
+ return toString(channelMask).find("_CHANNEL_OUT_") != std::string::npos;
+}
+
+static bool isIndexChannelMask(xsd::AudioChannelMask channelMask) {
+ return toString(channelMask).find("_CHANNEL_INDEX_") != std::string::npos;
+}
+
+TEST(HidlUtils, ConvertChannelMask) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioChannelMask>{}) {
+ const AudioChannelMask channelMask = toString(enumVal);
+ audio_channel_mask_t halChannelMask, halChannelMaskBack;
+ AudioChannelMask channelMaskBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskToHal(channelMask, &halChannelMask))
+ << "Conversion of \"" << channelMask << "\" failed";
+ EXPECT_EQ(enumVal != xsd::AudioChannelMask::AUDIO_CHANNEL_NONE,
+ audio_channel_mask_is_valid(halChannelMask))
+ << "Validity of \"" << channelMask << "\" is not as expected";
+ if (bool isInput = isInputChannelMask(enumVal); isInput || isOutputChannelMask(enumVal)) {
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioChannelMaskFromHal(halChannelMask, isInput, &channelMaskBack))
+ << "Conversion of " << (isInput ? "input" : "output") << " channel mask "
+ << halChannelMask << " failed";
+ // Due to aliased values, the result of 'fromHal' might not be the same
+ // as 'channelMask', thus we need to compare the results of 'toHal' conversion instead.
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioChannelMaskToHal(channelMaskBack, &halChannelMaskBack))
+ << "Conversion of \"" << channelMaskBack << "\" failed";
+ EXPECT_EQ(halChannelMask, halChannelMaskBack);
+ } else if (isIndexChannelMask(enumVal) ||
+ enumVal == xsd::AudioChannelMask::AUDIO_CHANNEL_NONE) {
+ // Conversions for indexed masks and "none" must not depend on the provided direction.
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskFromHal(halChannelMask, true /*isInput*/,
+ &channelMaskBack))
+ << "Conversion of indexed / none channel mask " << halChannelMask
+ << " failed (as input channel mask)";
+ EXPECT_EQ(channelMask, channelMaskBack);
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskFromHal(
+ halChannelMask, false /*isInput*/, &channelMaskBack))
+ << "Conversion of indexed / none channel mask " << halChannelMask
+ << " failed (as output channel mask)";
+ EXPECT_EQ(channelMask, channelMaskBack);
+ } else {
+ FAIL() << "Unrecognized channel mask \"" << channelMask << "\"";
+ }
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidConfigBase) {
+ AudioConfigBase invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal({.sample_rate = 0,
+ .channel_mask = kInvalidHalChannelMask,
+ .format = kInvalidHalFormat},
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal({.sample_rate = 0,
+ .channel_mask = kInvalidHalChannelMask,
+ .format = kInvalidHalFormat},
+ true /*isInput*/, &invalid));
+ audio_config_base_t halInvalid;
+ invalid.sampleRateHz = 0;
+ invalid.channelMask = "random string";
+ invalid.format = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertConfigBase) {
+ AudioConfigBase configBase;
+ configBase.sampleRateHz = 44100;
+ configBase.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ configBase.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ audio_config_base_t halConfigBase;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseToHal(configBase, &halConfigBase));
+ AudioConfigBase configBaseBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioConfigBaseFromHal(halConfigBase, false /*isInput*/, &configBaseBack));
+ EXPECT_EQ(configBase, configBaseBack);
+}
+
+TEST(HidlUtils, ConvertInvalidDeviceType) {
+ AudioDevice invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioDeviceTypeFromHal(kInvalidHalDevice, &invalid));
+ audio_devices_t halInvalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioDeviceTypeToHal("random string", &halInvalid));
+}
+
+TEST(HidlUtils, ConvertDeviceType) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioDevice>{}) {
+ const AudioDevice deviceType = toString(enumVal);
+ audio_devices_t halDeviceType, halDeviceTypeBack;
+ AudioDevice deviceTypeBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeToHal(deviceType, &halDeviceType))
+ << "Conversion of \"" << deviceType << "\" failed";
+ if (enumVal != xsd::AudioDevice::AUDIO_DEVICE_NONE) {
+ EXPECT_TRUE(audio_is_input_device(halDeviceType) ||
+ audio_is_output_device(halDeviceType))
+ << "Device \"" << deviceType << "\" is neither input, nor output device";
+ } else {
+ EXPECT_FALSE(audio_is_input_device(halDeviceType));
+ EXPECT_FALSE(audio_is_output_device(halDeviceType));
+ }
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeFromHal(halDeviceType, &deviceTypeBack))
+ << "Conversion of device type " << halDeviceType << " failed";
+ // Due to aliased values, the result of 'fromHal' might not be the same
+ // as 'deviceType', thus we need to compare the results of 'toHal' conversion instead.
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeToHal(deviceTypeBack, &halDeviceTypeBack))
+ << "Conversion of \"" << deviceTypeBack << "\" failed";
+ EXPECT_EQ(halDeviceType, halDeviceTypeBack);
+ }
+}
+
+// The enums module is too small to have unit tests on its own.
+TEST(HidlUtils, VendorExtension) {
+ EXPECT_TRUE(xsd::isVendorExtension("VX_GOOGLE_VR_42"));
+ EXPECT_FALSE(xsd::isVendorExtension("random string"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_GOOGLE_$$"));
+}
+
+TEST(HidlUtils, ConvertInvalidDeviceAddress) {
+ DeviceAddress invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,
+ nullptr, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,
+ "", &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_IP, nullptr, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_IP, "", &invalid));
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_USB_HEADSET, nullptr, &invalid));
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_USB_HEADSET, "", &invalid));
+
+ audio_devices_t halInvalid;
+ char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {};
+ invalid = {};
+ invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress));
+ invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_IP);
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress));
+ invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET);
+ EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress));
+}
+
+static void ConvertDeviceAddress(const DeviceAddress& device) {
+ audio_devices_t halDeviceType;
+ char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {};
+ EXPECT_EQ(NO_ERROR, HidlUtils::deviceAddressToHal(device, &halDeviceType, halDeviceAddress));
+ DeviceAddress deviceBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, &deviceBack));
+ EXPECT_EQ(device, deviceBack);
+}
+
+TEST(HidlUtils, ConvertUniqueDeviceAddress) {
+ DeviceAddress speaker;
+ speaker.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER);
+ ConvertDeviceAddress(speaker);
+}
+
+TEST(HidlUtils, ConvertA2dpDeviceAddress) {
+ DeviceAddress a2dpSpeaker;
+ a2dpSpeaker.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+ a2dpSpeaker.address.mac(std::array<uint8_t, 6>{1, 2, 3, 4, 5, 6});
+ ConvertDeviceAddress(a2dpSpeaker);
+}
+
+TEST(HidlUtils, ConvertIpv4DeviceAddress) {
+ DeviceAddress ipv4;
+ ipv4.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_IP);
+ ipv4.address.ipv4(std::array<uint8_t, 4>{1, 2, 3, 4});
+ ConvertDeviceAddress(ipv4);
+}
+
+TEST(HidlUtils, ConvertUsbDeviceAddress) {
+ DeviceAddress usbHeadset;
+ usbHeadset.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET);
+ usbHeadset.address.alsa({1, 2});
+ ConvertDeviceAddress(usbHeadset);
+}
+
+TEST(HidlUtils, ConvertBusDeviceAddress) {
+ DeviceAddress bus;
+ bus.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BUS);
+ bus.address.id("bus_device");
+ ConvertDeviceAddress(bus);
+}
+
+TEST(HidlUtils, ConvertRSubmixDeviceAddress) {
+ DeviceAddress rSubmix;
+ rSubmix.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX);
+ rSubmix.address.id(AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
+ ConvertDeviceAddress(rSubmix);
+}
+
+TEST(HidlUtils, ConvertVendorDeviceAddress) {
+ // The address part is not mandatory, both cases must work.
+ {
+ DeviceAddress vendor;
+ vendor.deviceType = "VX_GOOGLE_VR";
+ audio_devices_t halDeviceType;
+ char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {};
+ // Ignore the result. Vendors will also add the extended device into
+ // the list of devices in audio-hal-enums.h. Without that, the conversion
+ // officially fails, but it still maps the device type to NONE.
+ (void)HidlUtils::deviceAddressToHal(vendor, &halDeviceType, halDeviceAddress);
+ EXPECT_EQ(AUDIO_DEVICE_NONE, halDeviceType);
+ EXPECT_EQ(0, strnlen(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ }
+ {
+ DeviceAddress vendor;
+ vendor.deviceType = "VX_GOOGLE_VR";
+ vendor.address.id("vr1");
+ audio_devices_t halDeviceType;
+ char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {};
+ // Ignore the result. Vendors will also add the extended device into
+ // the list of devices in audio-hal-enums.h. Without that, the conversion
+ // officially fails, but it still maps the device type to NONE and converts
+ // the address.
+ (void)HidlUtils::deviceAddressToHal(vendor, &halDeviceType, halDeviceAddress);
+ EXPECT_EQ(AUDIO_DEVICE_NONE, halDeviceType);
+ EXPECT_EQ(0, strncmp("vr1", halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidFormat) {
+ AudioFormat invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatFromHal(kInvalidHalFormat, &invalid));
+ audio_format_t halInvalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatToHal("random string", &halInvalid));
+}
+
+TEST(HidlUtils, ConvertFormat) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioFormat>{}) {
+ const AudioFormat format = toString(enumVal);
+ audio_format_t halFormat;
+ AudioFormat formatBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioFormatToHal(format, &halFormat))
+ << "Conversion of \"" << format << "\" failed";
+ EXPECT_TRUE(audio_is_valid_format(halFormat))
+ << "Converted format \"" << format << "\" is invalid";
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioFormatFromHal(halFormat, &formatBack))
+ << "Conversion of format " << halFormat << " failed";
+ EXPECT_EQ(format, formatBack);
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidGainModeMask) {
+ hidl_vec<AudioGainMode> invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainModeMaskFromHal(kInvalidHalGainMode, &invalid));
+ audio_gain_mode_t halInvalid;
+ invalid.resize(1);
+ invalid[0] = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainModeMaskToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertGainModeMask) {
+ hidl_vec<AudioGainMode> emptyGainModes;
+ audio_gain_mode_t halEmptyGainModes;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskToHal(emptyGainModes, &halEmptyGainModes));
+ hidl_vec<AudioGainMode> emptyGainModesBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioGainModeMaskFromHal(halEmptyGainModes, &emptyGainModesBack));
+ EXPECT_EQ(emptyGainModes, emptyGainModesBack);
+
+ std::vector<std::string> allEnumValues;
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioGainMode>{}) {
+ allEnumValues.push_back(toString(enumVal));
+ }
+ hidl_vec<AudioGainMode> allGainModes;
+ allGainModes.resize(allEnumValues.size());
+ for (size_t i = 0; i < allEnumValues.size(); ++i) {
+ allGainModes[i] = allEnumValues[i];
+ }
+ audio_gain_mode_t halAllGainModes;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskToHal(allGainModes, &halAllGainModes));
+ hidl_vec<AudioGainMode> allGainModesBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskFromHal(halAllGainModes, &allGainModesBack));
+ EXPECT_EQ(allGainModes, allGainModesBack);
+}
+
+TEST(HidlUtils, ConvertInvalidSource) {
+ AudioSource invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceFromHal(kInvalidHalSource, &invalid));
+ audio_source_t halInvalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceToHal("random string", &halInvalid));
+}
+
+TEST(HidlUtils, ConvertSource) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioSource>{}) {
+ const AudioSource source = toString(enumVal);
+ audio_source_t halSource;
+ AudioSource sourceBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioSourceToHal(source, &halSource))
+ << "Conversion of \"" << source << "\" failed";
+ EXPECT_EQ(enumVal != xsd::AudioSource::AUDIO_SOURCE_DEFAULT,
+ audio_is_valid_audio_source(halSource))
+ << "Validity of \"" << source << "\" is not as expected";
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioSourceFromHal(halSource, &sourceBack))
+ << "Conversion of source " << halSource << " failed";
+ EXPECT_EQ(source, sourceBack);
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidStreamType) {
+ AudioStreamType invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioStreamTypeFromHal(kInvalidHalStreamType, &invalid));
+ audio_stream_type_t halInvalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioStreamTypeToHal("random string", &halInvalid));
+}
+
+TEST(HidlUtils, ConvertStreamType) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioStreamType>{}) {
+ const AudioStreamType streamType = toString(enumVal);
+ audio_stream_type_t halStreamType;
+ AudioStreamType streamTypeBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeToHal(streamType, &halStreamType))
+ << "Conversion of \"" << streamType << "\" failed";
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeFromHal(halStreamType, &streamTypeBack))
+ << "Conversion of stream type " << halStreamType << " failed";
+ EXPECT_EQ(streamType, streamTypeBack);
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidGain) {
+ AudioGain invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainFromHal({.mode = kInvalidHalGainMode},
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainFromHal({.mode = kInvalidHalGainMode},
+ true /*isInput*/, &invalid));
+ struct audio_gain halInvalid;
+ invalid.mode.resize(1);
+ invalid.mode[0] = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertGain) {
+ AudioGain gain = {};
+ gain.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ struct audio_gain halGain;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainToHal(gain, &halGain));
+ AudioGain gainBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainFromHal(halGain, false /*isInput*/, &gainBack));
+ EXPECT_EQ(gain, gainBack);
+ struct audio_gain halGainBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainToHal(gainBack, &halGainBack));
+ EXPECT_TRUE(audio_gains_are_equal(&halGain, &halGainBack));
+}
+
+TEST(HidlUtils, ConvertInvalidGainConfig) {
+ AudioGainConfig invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigFromHal({.mode = kInvalidHalGainMode},
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigFromHal({.mode = kInvalidHalGainMode},
+ true /*isInput*/, &invalid));
+ struct audio_gain_config halInvalid;
+ invalid.mode.resize(1);
+ invalid.mode[0] = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertGainConfig) {
+ AudioGainConfig gainConfig = {};
+ gainConfig.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ struct audio_gain_config halGainConfig;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainConfigToHal(gainConfig, &halGainConfig));
+ AudioGainConfig gainConfigBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioGainConfigFromHal(halGainConfig, false /*isInput*/, &gainConfigBack));
+ EXPECT_EQ(gainConfig, gainConfigBack);
+ struct audio_gain_config halGainConfigBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioGainConfigToHal(gainConfigBack, &halGainConfigBack));
+ EXPECT_TRUE(audio_gain_config_are_equal(&halGainConfig, &halGainConfigBack));
+}
+
+TEST(HidlUtils, ConvertInvalidUsage) {
+ AudioUsage invalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioUsageFromHal(kInvalidHalUsage, &invalid));
+ audio_usage_t halInvalid;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioUsageToHal("random string", &halInvalid));
+}
+
+TEST(HidlUtils, ConvertUsage) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioUsage>{}) {
+ const AudioUsage usage = toString(enumVal);
+ audio_usage_t halUsage;
+ AudioUsage usageBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioUsageToHal(usage, &halUsage))
+ << "Conversion of \"" << usage << "\" failed";
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioUsageFromHal(halUsage, &usageBack))
+ << "Conversion of usage " << halUsage << " failed";
+ EXPECT_EQ(usage, usageBack);
+ }
+}
+
+TEST(HidlUtils, ConvertInvalidOffloadInfo) {
+ AudioOffloadInfo invalid;
+ audio_offload_info_t halInvalid = AUDIO_INFO_INITIALIZER;
+ halInvalid.channel_mask = AUDIO_CHANNEL_INVALID;
+ halInvalid.format = kInvalidHalFormat;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioOffloadInfoFromHal(halInvalid, &invalid));
+ invalid.base.channelMask = "random string";
+ invalid.base.format = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioOffloadInfoToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertOffloadInfo) {
+ AudioOffloadInfo offloadInfo = {};
+ offloadInfo.base.sampleRateHz = 44100;
+ offloadInfo.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ offloadInfo.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
+ offloadInfo.bitRatePerSecond = 320;
+ offloadInfo.durationMicroseconds = -1;
+ offloadInfo.bitWidth = 16;
+ offloadInfo.bufferSize = 1024;
+ offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
+ offloadInfo.encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM;
+ offloadInfo.contentId = 42;
+ offloadInfo.syncId = 13;
+ audio_offload_info_t halOffloadInfo;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioOffloadInfoToHal(offloadInfo, &halOffloadInfo));
+ AudioOffloadInfo offloadInfoBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioOffloadInfoFromHal(halOffloadInfo, &offloadInfoBack));
+ EXPECT_EQ(offloadInfo, offloadInfoBack);
+}
+
+TEST(HidlUtils, ConvertInvalidConfig) {
+ AudioConfig invalid;
+ audio_config_t halInvalid = AUDIO_CONFIG_INITIALIZER;
+ halInvalid.channel_mask = AUDIO_CHANNEL_INVALID;
+ halInvalid.format = kInvalidHalFormat;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, true /*isInput*/, &invalid));
+ invalid.base.channelMask = "random string";
+ invalid.base.format = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertConfig) {
+ AudioConfig config = {};
+ config.base.sampleRateHz = 44100;
+ config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ config.offloadInfo.base = config.base;
+ config.offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
+ config.offloadInfo.bitRatePerSecond = 320;
+ config.offloadInfo.durationMicroseconds = -1;
+ config.offloadInfo.bitWidth = 16;
+ config.offloadInfo.bufferSize = 1024;
+ config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
+ config.offloadInfo.encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM;
+ config.offloadInfo.contentId = 42;
+ config.offloadInfo.syncId = 13;
+ audio_config_t halConfig;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(config, &halConfig));
+ AudioConfig configBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, &configBack));
+ EXPECT_EQ(config, configBack);
+}
+
+TEST(HidlUtils, ConvertInvalidAudioProfile) {
+ AudioProfile invalid;
+ struct audio_profile halInvalid = {};
+ halInvalid.format = kInvalidHalFormat;
+ halInvalid.num_sample_rates = 0;
+ halInvalid.num_channel_masks = 1;
+ halInvalid.channel_masks[0] = kInvalidHalChannelMask;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileFromHal(halInvalid, false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileFromHal(halInvalid, true /*isInput*/, &invalid));
+ invalid.format = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertAudioProfile) {
+ 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);
+ struct audio_profile halProfile;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioProfileToHal(profile, &halProfile));
+ AudioProfile profileBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioProfileFromHal(halProfile, false /*isInput*/, &profileBack));
+ EXPECT_EQ(profile, profileBack);
+}
+
+TEST(HidlUtils, ConvertInvalidAudioPortConfig) {
+ AudioPortConfig invalid;
+ struct audio_port_config halInvalid = {};
+ halInvalid.type = AUDIO_PORT_TYPE_MIX;
+ halInvalid.role = AUDIO_PORT_ROLE_NONE; // note: this is valid.
+ halInvalid.config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK;
+ halInvalid.channel_mask = AUDIO_CHANNEL_INVALID;
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortConfigFromHal(halInvalid, &invalid));
+ invalid.base.channelMask = "random string";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortConfigToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertAudioPortConfig) {
+ AudioPortConfig config = {};
+ config.id = 42;
+ config.base.sampleRateHz = 44100;
+ config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ config.gain.config({});
+ config.gain.config().channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ config.ext.device({});
+ config.ext.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER);
+ struct audio_port_config halConfig;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigToHal(config, &halConfig));
+ AudioPortConfig configBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigFromHal(halConfig, &configBack));
+ EXPECT_EQ(config, configBack);
+ struct audio_port_config halConfigBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigToHal(configBack, &halConfigBack));
+ EXPECT_TRUE(audio_port_configs_are_equal(&halConfig, &halConfigBack));
+}
+
+TEST(HidlUtils, ConvertInvalidAudioPort) {
+ AudioPort invalid;
+ struct audio_port_v7 halInvalid = {};
+ halInvalid.type = AUDIO_PORT_TYPE_MIX;
+ halInvalid.role = AUDIO_PORT_ROLE_NONE; // note: this is valid.
+ 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";
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortToHal(invalid, &halInvalid));
+}
+
+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.gains.resize(1);
+ port.gains[0].channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ port.ext.device({});
+ port.ext.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER);
+ // active config left unspecified.
+ struct audio_port_v7 halPort;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortToHal(port, &halPort));
+ AudioPort portBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortFromHal(halPort, &portBack));
+ EXPECT_EQ(port, portBack);
+ struct audio_port_v7 halPortBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioPortToHal(portBack, &halPortBack));
+ EXPECT_TRUE(audio_ports_v7_are_equal(&halPort, &halPortBack));
+}
diff --git a/audio/core/all-versions/default/Conversions.cpp b/audio/core/all-versions/default/Conversions.cpp
index 0db210a..28d8f78 100644
--- a/audio/core/all-versions/default/Conversions.cpp
+++ b/audio/core/all-versions/default/Conversions.cpp
@@ -27,6 +27,7 @@
namespace CPP_VERSION {
namespace implementation {
+// TODO(mnaganov): Use method from HidlUtils for V7
std::string deviceAddressToHal(const DeviceAddress& address) {
// HAL assumes that the address is NUL-terminated.
char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 6260ba1..3c28159 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -283,8 +283,10 @@
const hidl_vec<AudioPortConfig>& sinks) {
Result retval(Result::NOT_SUPPORTED);
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
- std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
+ std::unique_ptr<audio_port_config[]> halSources;
+ HidlUtils::audioPortConfigsToHal(sources, &halSources);
+ std::unique_ptr<audio_port_config[]> halSinks;
+ HidlUtils::audioPortConfigsToHal(sinks, &halSinks);
audio_patch_handle_t halPatch = static_cast<audio_patch_handle_t>(patch);
retval = analyzeStatus("create_audio_patch",
mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
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 eb8cb3f..1612d3c 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -67,8 +67,7 @@
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
#elif MAJOR_VERSION >= 7
- config.base.channelMask.resize(1);
- config.base.channelMask[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
+ config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
config.base.sampleRateHz = 8000;
config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
hidl_vec<hidl_string> flags;
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 63eaea8..941c4bd 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -26,8 +26,7 @@
for (auto sampleRate : sampleRates) {
AudioConfig config{};
// leave offloadInfo to 0
- config.base.channelMask.resize(1);
- config.base.channelMask[0] = toString(channelMask);
+ config.base.channelMask = toString(channelMask);
config.base.sampleRateHz = sampleRate;
config.base.format = format;
configs.push_back(config);
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index c7bfe08..a809a92 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -22,6 +22,8 @@
"libxml2",
],
shared_libs: [
+ "audioclient-types-aidl-unstable-cpp",
+ "libaudioclient_aidl_conversion",
"libbinder",
"libfmq",
],
diff --git a/audio/effect/7.0/types.hal b/audio/effect/7.0/types.hal
index fe4ee51..b0a0709 100644
--- a/audio/effect/7.0/types.hal
+++ b/audio/effect/7.0/types.hal
@@ -202,16 +202,26 @@
* enumeration of the effect engines present in a library.
*/
struct EffectDescriptor {
- Uuid type; // UUID of to the OpenSL ES interface implemented
- // by this effect
- Uuid uuid; // UUID for this particular implementation
- bitfield<EffectFlags> flags; // effect engine capabilities/requirements flags
- uint16_t cpuLoad; // CPU load indication expressed in 0.1 MIPS units
- // as estimated on an ARM9E core (ARMv5TE) with 0 WS
- uint16_t memoryUsage; // data memory usage expressed in KB and includes
- // only dynamically allocated memory
- uint8_t[64] name; // human readable effect name
- uint8_t[64] implementor; // human readable effect implementor name
+ /** UUID of to the OpenSL ES interface implemented by this effect. */
+ Uuid type;
+ /** UUID for this particular implementation. */
+ Uuid uuid;
+ /** Effect engine capabilities/requirements flags. */
+ bitfield<EffectFlags> flags;
+ /**
+ * CPU load indication expressed in 0.1 MIPS units as estimated on
+ * an ARM9E core (ARMv5TE) with 0 WS.
+ */
+ uint16_t cpuLoad;
+ /**
+ * Data memory usage expressed in KB and includes only dynamically
+ * allocated memory.
+ */
+ uint16_t memoryUsage;
+ /** Human readable effect name. */
+ uint8_t[64] name;
+ /** Human readable effect implementor name. */
+ uint8_t[64] implementor;
};
/**
@@ -242,11 +252,16 @@
*/
@export(name="", value_prefix="EFFECT_CONFIG_")
enum EffectConfigParameters : int32_t {
- BUFFER = 0x0001, // buffer field
- SMP_RATE = 0x0002, // samplingRate
- CHANNELS = 0x0004, // channels
- FORMAT = 0x0008, // format
- ACC_MODE = 0x0010, // accessMode
+ /** Buffer field. */
+ BUFFER = 0x0001,
+ /** Sampling rate. */
+ SMP_RATE = 0x0002,
+ /** Channels. */
+ CHANNELS = 0x0004,
+ /** Format. */
+ FORMAT = 0x0008,
+ /** Access mode. */
+ ACC_MODE = 0x0010,
// Note that the 2.0 ALL have been moved to an helper function
};
@@ -270,21 +285,23 @@
@export(name="effect_feature_e", value_prefix="EFFECT_FEATURE_")
enum EffectFeature : int32_t {
- AUX_CHANNELS, // supports auxiliary channels
- // (e.g. dual mic noise suppressor)
+ /** Supports auxiliary channels (e.g. dual mic noise suppressor). */
+ AUX_CHANNELS,
CNT
};
struct EffectAuxChannelsConfig {
- vec<AudioChannelMask> mainChannels; // channel mask for main channels
- vec<AudioChannelMask> auxChannels; // channel mask for auxiliary channels
+ /** Channel mask for main channels. */
+ vec<AudioChannelMask> mainChannels;
+ /** Channel mask for auxiliary channels. */
+ vec<AudioChannelMask> auxChannels;
};
struct EffectOffloadParameter {
- bool isOffload; // true if the playback thread the effect
- // is attached to is offloaded
- AudioIoHandle ioHandle; // io handle of the playback thread
- // the effect is attached to
+ /** True if the playback thread the effect is attached to is offloaded. */
+ bool isOffload;
+ /** I/O handle of the playback thread the effect is attached to. */
+ AudioIoHandle ioHandle;
};
/**
diff --git a/audio/effect/all-versions/default/Conversions.cpp b/audio/effect/all-versions/default/Conversions.cpp
index b1c0b0d..0cc8767 100644
--- a/audio/effect/all-versions/default/Conversions.cpp
+++ b/audio/effect/all-versions/default/Conversions.cpp
@@ -15,7 +15,7 @@
*/
#include "Conversions.h"
-#include "HidlUtils.h"
+#include "UuidUtils.h"
#include <memory.h>
#include <stdio.h>
@@ -31,12 +31,12 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
EffectDescriptor* descriptor) {
- HidlUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
- HidlUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
+ UuidUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
+ UuidUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
descriptor->flags = EnumBitfield<EffectFlags>(halDescriptor.flags);
descriptor->cpuLoad = halDescriptor.cpuLoad;
descriptor->memoryUsage = halDescriptor.memoryUsage;
diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp
index acce7de..b265d3d 100644
--- a/audio/effect/all-versions/default/EffectsFactory.cpp
+++ b/audio/effect/all-versions/default/EffectsFactory.cpp
@@ -24,10 +24,10 @@
#include "Effect.h"
#include "EnvironmentalReverbEffect.h"
#include "EqualizerEffect.h"
-#include "HidlUtils.h"
#include "LoudnessEnhancerEffect.h"
#include "NoiseSuppressionEffect.h"
#include "PresetReverbEffect.h"
+#include "UuidUtils.h"
#include "VirtualizerEffect.h"
#include "VisualizerEffect.h"
#include "common/all-versions/default/EffectMap.h"
@@ -53,7 +53,7 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
// static
sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
@@ -135,7 +135,7 @@
Return<void> EffectsFactory::getDescriptor(const Uuid& uuid, getDescriptor_cb _hidl_cb) {
effect_uuid_t halUuid;
- HidlUtils::uuidToHal(uuid, &halUuid);
+ UuidUtils::uuidToHal(uuid, &halUuid);
effect_descriptor_t halDescriptor;
status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
EffectDescriptor descriptor;
@@ -170,7 +170,7 @@
Return<void> EffectsFactory::createEffectImpl(const Uuid& uuid, int32_t session, int32_t ioHandle,
int32_t device, createEffect_cb _hidl_cb) {
effect_uuid_t halUuid;
- HidlUtils::uuidToHal(uuid, &halUuid);
+ UuidUtils::uuidToHal(uuid, &halUuid);
effect_handle_t handle;
Result retval(Result::OK);
status_t status;
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
index 88c066c..a05fad9 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -42,4 +42,8 @@
SENSOR_DIRTY = 21,
VENDOR = 22,
FIRST_FRAME_RECEIVED = 23,
+ DARK_GLASSES_DETECTED = 24,
+ FACE_COVERING_DETECTED = 25,
+ EYES_NOT_VISIBLE = 26,
+ MOUTH_NOT_VISIBLE = 27,
}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
index 5897cdc..56a600f 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -218,6 +218,30 @@
/**
* The first frame from the camera has been received.
*/
- FIRST_FRAME_RECEIVED = 23
+ FIRST_FRAME_RECEIVED = 23,
+
+ /**
+ * Dark glasses detected. This can be useful for providing relevant feedback to the user and
+ * enabling an alternative authentication logic if the implementation supports it.
+ */
+ DARK_GLASSES_DETECTED = 24,
+
+ /**
+ * A face mask or face covering detected. This can be useful for providing relevant feedback to
+ * the user and enabling an alternative authentication logic if the implementation supports it.
+ */
+ FACE_COVERING_DETECTED = 25,
+
+ /**
+ * Either one or both eyes are not visible in the frame. Prefer to use DARK_GLASSES_DETECTED if
+ * the eyes are not visible due to dark glasses.
+ */
+ EYES_NOT_VISIBLE = 26,
+
+ /**
+ * The mouth is not visible in the frame. Prefer to use MASK_DETECTED if the mouth is not
+ * visible due to a mask.
+ */
+ MOUTH_NOT_VISIBLE = 27,
}
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 8c24f76..43abbe4 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -90,6 +90,7 @@
hci_packet_type_ = static_cast<HciPacketType>(buffer[0]);
if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA &&
hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA &&
+ hci_packet_type_ != HCI_PACKET_TYPE_ISO_DATA &&
hci_packet_type_ != HCI_PACKET_TYPE_EVENT) {
LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
static_cast<int>(hci_packet_type_));
diff --git a/bluetooth/1.0/default/hci_internals.h b/bluetooth/1.0/default/hci_internals.h
index 24e944f..6f7ff90 100644
--- a/bluetooth/1.0/default/hci_internals.h
+++ b/bluetooth/1.0/default/hci_internals.h
@@ -44,6 +44,10 @@
const size_t HCI_EVENT_PREAMBLE_SIZE = 2;
const size_t HCI_LENGTH_OFFSET_EVT = 1;
+// 2 bytes for handle and flags, 2 byte for data length (Volume 4, Part E, 5.4.5)
+const size_t HCI_ISO_PREAMBLE_SIZE = 4;
+const size_t HCI_LENGTH_OFFSET_ISO = 2;
+
const size_t HCI_PREAMBLE_SIZE_MAX = HCI_ACL_PREAMBLE_SIZE;
// Event codes (Volume 2, Part E, 7.7.14)
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 7cb3a11..78ce61d 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -26,17 +26,27 @@
namespace {
-const size_t preamble_size_for_type[] = {
- 0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE,
- HCI_EVENT_PREAMBLE_SIZE};
-const size_t packet_length_offset_for_type[] = {
- 0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO,
- HCI_LENGTH_OFFSET_EVT};
+const size_t preamble_size_for_type[] = {0,
+ HCI_COMMAND_PREAMBLE_SIZE,
+ HCI_ACL_PREAMBLE_SIZE,
+ HCI_SCO_PREAMBLE_SIZE,
+ HCI_EVENT_PREAMBLE_SIZE,
+ HCI_ISO_PREAMBLE_SIZE};
+const size_t packet_length_offset_for_type[] = {0,
+ HCI_LENGTH_OFFSET_CMD,
+ HCI_LENGTH_OFFSET_ACL,
+ HCI_LENGTH_OFFSET_SCO,
+ HCI_LENGTH_OFFSET_EVT,
+ HCI_LENGTH_OFFSET_ISO};
size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) {
size_t offset = packet_length_offset_for_type[type];
- if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset];
- return (((preamble[offset + 1]) << 8) | preamble[offset]);
+ if (type == HCI_PACKET_TYPE_ACL_DATA) {
+ return (((preamble[offset + 1]) << 8) | preamble[offset]);
+ } else if (type == HCI_PACKET_TYPE_ISO_DATA) {
+ return ((((preamble[offset + 1]) & 0x3f) << 8) | preamble[offset]);
+ }
+ return preamble[offset];
}
} // namespace
diff --git a/bluetooth/1.0/default/test/h4_protocol_unittest.cc b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
index 283243d..174861c 100644
--- a/bluetooth/1.0/default/test/h4_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
@@ -190,8 +190,10 @@
void WriteAndExpectInboundIsoData(char* payload) {
// h4 type[1] + handle[2] + size[1]
- char preamble[4] = {HCI_PACKET_TYPE_ISO_DATA, 20, 17, 0};
- preamble[3] = strlen(payload) & 0xFF;
+ char preamble[5] = {HCI_PACKET_TYPE_ISO_DATA, 19, 92, 0, 0};
+ int length = strlen(payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = (length >> 8) & 0x3F;
ALOGD("%s writing", __func__);
TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
index 0f349a4..092038b 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
@@ -55,12 +55,17 @@
const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
AudioConfiguration audioConfig_2_1;
- audioConfig_2_1.codecConfig() = audioConfig.codecConfig();
- audioConfig_2_1.pcmConfig() = {
- .sampleRate = static_cast<SampleRate>(audioConfig.pcmConfig().sampleRate),
- .channelMode = audioConfig.pcmConfig().channelMode,
- .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
- .dataIntervalUs = 0};
+ if (audioConfig.getDiscriminator() ==
+ V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
+ audioConfig_2_1.pcmConfig() = {
+ .sampleRate =
+ static_cast<SampleRate>(audioConfig.pcmConfig().sampleRate),
+ .channelMode = audioConfig.pcmConfig().channelMode,
+ .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
+ .dataIntervalUs = 0};
+ } else {
+ audioConfig_2_1.codecConfig() = audioConfig.codecConfig();
+ }
return startSession_2_1(hostIf, audioConfig_2_1, _hidl_cb);
}
diff --git a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
index c0ec907..37d1281 100644
--- a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
+++ b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
@@ -1043,6 +1043,7 @@
} else {
EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
EXPECT_FALSE(dataMQ.isHandleValid());
+ tempDataMQ.reset(nullptr);
}
};
android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
@@ -1064,6 +1065,8 @@
ASSERT_TRUE(hidl_retval.isOk());
if (is_codec_config_valid) {
EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+ } else {
+ EXPECT_TRUE(tempDataMQ == nullptr);
}
EXPECT_TRUE(audio_provider_2_1_->endSession().isOk());
} // uint32_t (data interval in microseconds)
@@ -1132,6 +1135,7 @@
} else {
EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
EXPECT_FALSE(dataMQ.isHandleValid());
+ tempDataMQ.reset(nullptr);
}
};
android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
index 5468658..ac17d6d 100644
--- a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -32,6 +32,7 @@
unsigned int GetNumberSlots();
unsigned int GetCurrentSlot();
bool MarkBootSuccessful();
+ unsigned int GetActiveBootSlot();
bool SetActiveBootSlot(unsigned int slot);
bool SetSlotAsUnbootable(unsigned int slot);
bool SetSlotBootable(unsigned int slot);
diff --git a/boot/1.1/default/boot_control/libboot_control.cpp b/boot/1.1/default/boot_control/libboot_control.cpp
index 2c6ccaf..9387c32 100644
--- a/boot/1.1/default/boot_control/libboot_control.cpp
+++ b/boot/1.1/default/boot_control/libboot_control.cpp
@@ -261,6 +261,24 @@
return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
}
+unsigned int BootControl::GetActiveBootSlot() {
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ // Use the current slot by default.
+ unsigned int active_boot_slot = current_slot_;
+ unsigned int max_priority = bootctrl.slot_info[current_slot_].priority;
+ // Find the slot with the highest priority.
+ for (unsigned int i = 0; i < num_slots_; ++i) {
+ if (bootctrl.slot_info[i].priority > max_priority) {
+ max_priority = bootctrl.slot_info[i].priority;
+ active_boot_slot = i;
+ }
+ }
+
+ return active_boot_slot;
+}
+
bool BootControl::SetActiveBootSlot(unsigned int slot) {
if (slot >= kMaxNumSlots || slot >= num_slots_) {
// Invalid slot number.
diff --git a/boot/1.2/Android.bp b/boot/1.2/Android.bp
new file mode 100644
index 0000000..e51c5cd
--- /dev/null
+++ b/boot/1.2/Android.bp
@@ -0,0 +1,15 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.boot@1.2",
+ root: "android.hardware",
+ srcs: [
+ "IBootControl.hal",
+ ],
+ interfaces: [
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/boot/1.2/IBootControl.hal b/boot/1.2/IBootControl.hal
new file mode 100644
index 0000000..bb0ad13
--- /dev/null
+++ b/boot/1.2/IBootControl.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.boot@1.2;
+
+import @1.0::IBootControl;
+import @1.0::Slot;
+import @1.1::IBootControl;
+
+interface IBootControl extends @1.1::IBootControl {
+
+ /**
+ * Returns the active slot to boot into on the next boot. If
+ * setActiveBootSlot() has been called, the getter function should return the
+ * same slot as the one provided in the last setActiveBootSlot() call.
+ * The returned value is always guaranteed to be strictly less than the
+ * value returned by getNumberSlots. Slots start at 0 and finish at
+ * getNumberSlots() - 1. For instance, a system with A/B must return 0 or 1.
+ */
+ getActiveBootSlot() generates (Slot slot);
+};
+
diff --git a/boot/1.2/default/Android.bp b/boot/1.2/default/Android.bp
new file mode 100644
index 0000000..c097667
--- /dev/null
+++ b/boot/1.2/default/Android.bp
@@ -0,0 +1,50 @@
+cc_library_shared {
+ name: "android.hardware.boot@1.2-impl",
+ stem: "android.hardware.boot@1.0-impl-1.2",
+ defaults: [
+ "hidl_defaults",
+ "libboot_control_defaults",
+ ],
+ relative_install_path: "hw",
+ vendor: true,
+ recovery_available: true,
+ srcs: ["BootControl.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libhardware",
+ "libutils",
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ "android.hardware.boot@1.2",
+ ],
+ static_libs: [
+ "libboot_control",
+ "libfstab",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.boot@1.2-service",
+ defaults: ["hidl_defaults"],
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.boot@1.2-service.rc"],
+ srcs: ["service.cpp"],
+
+ vintf_fragments: [
+ "android.hardware.boot@1.2.xml",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libhardware",
+ "libhidlbase",
+ "libutils",
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ "android.hardware.boot@1.2",
+ ],
+
+}
diff --git a/boot/1.2/default/BootControl.cpp b/boot/1.2/default/BootControl.cpp
new file mode 100644
index 0000000..c0bf02f
--- /dev/null
+++ b/boot/1.2/default/BootControl.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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 "android.hardware.boot@1.2-impl"
+
+#include <memory>
+
+#include <log/log.h>
+
+#include "BootControl.h"
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_2 {
+namespace implementation {
+
+using ::android::hardware::boot::V1_0::CommandResult;
+
+bool BootControl::Init() {
+ return impl_.Init();
+}
+
+// Methods from ::android::hardware::boot::V1_0::IBootControl.
+Return<uint32_t> BootControl::getNumberSlots() {
+ return impl_.GetNumberSlots();
+}
+
+Return<uint32_t> BootControl::getCurrentSlot() {
+ return impl_.GetCurrentSlot();
+}
+
+Return<void> BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.MarkBootSuccessful()) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<void> BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.SetActiveBootSlot(slot)) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<void> BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.SetSlotAsUnbootable(slot)) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<BoolResult> BootControl::isSlotBootable(uint32_t slot) {
+ if (!impl_.IsValidSlot(slot)) {
+ return BoolResult::INVALID_SLOT;
+ }
+ return impl_.IsSlotBootable(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<BoolResult> BootControl::isSlotMarkedSuccessful(uint32_t slot) {
+ if (!impl_.IsValidSlot(slot)) {
+ return BoolResult::INVALID_SLOT;
+ }
+ return impl_.IsSlotMarkedSuccessful(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<void> BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) {
+ hidl_string ans;
+ const char* suffix = impl_.GetSuffix(slot);
+ if (suffix) {
+ ans = suffix;
+ }
+ _hidl_cb(ans);
+ return Void();
+}
+
+// Methods from ::android::hardware::boot::V1_1::IBootControl.
+Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus status) {
+ return impl_.SetSnapshotMergeStatus(status);
+}
+
+Return<MergeStatus> BootControl::getSnapshotMergeStatus() {
+ return impl_.GetSnapshotMergeStatus();
+}
+
+// Methods from ::android::hardware::boot::V1_2::IBootControl.
+Return<uint32_t> BootControl::getActiveBootSlot() {
+ return impl_.GetActiveBootSlot();
+}
+
+IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
+ auto module = std::make_unique<BootControl>();
+ if (!module->Init()) {
+ ALOGE("Could not initialize BootControl module");
+ return nullptr;
+ }
+ return module.release();
+}
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace boot
+} // namespace hardware
+} // namespace android
diff --git a/boot/1.2/default/BootControl.h b/boot/1.2/default/BootControl.h
new file mode 100644
index 0000000..5791699
--- /dev/null
+++ b/boot/1.2/default/BootControl.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/boot/1.2/IBootControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <libboot_control/libboot_control.h>
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_2 {
+namespace implementation {
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_0::BoolResult;
+using ::android::hardware::boot::V1_1::MergeStatus;
+using ::android::hardware::boot::V1_2::IBootControl;
+
+class BootControl : public IBootControl {
+ public:
+ bool Init();
+
+ // Methods from ::android::hardware::boot::V1_0::IBootControl.
+ Return<uint32_t> getNumberSlots() override;
+ Return<uint32_t> getCurrentSlot() override;
+ Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
+ Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
+ Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
+ Return<BoolResult> isSlotBootable(uint32_t slot) override;
+ Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
+ Return<void> getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override;
+
+ // Methods from ::android::hardware::boot::V1_1::IBootControl.
+ Return<bool> setSnapshotMergeStatus(MergeStatus status) override;
+ Return<MergeStatus> getSnapshotMergeStatus() override;
+
+ // Methods from ::android::hardware::boot::V1_2::IBootControl.
+ Return<uint32_t> getActiveBootSlot() override;
+
+ private:
+ android::bootable::BootControl impl_;
+};
+
+extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name);
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace boot
+} // namespace hardware
+} // namespace android
diff --git a/boot/1.2/default/android.hardware.boot@1.2-service.rc b/boot/1.2/default/android.hardware.boot@1.2-service.rc
new file mode 100644
index 0000000..14926c0
--- /dev/null
+++ b/boot/1.2/default/android.hardware.boot@1.2-service.rc
@@ -0,0 +1,7 @@
+service vendor.boot-hal-1-2 /vendor/bin/hw/android.hardware.boot@1.2-service
+ interface android.hardware.boot@1.0::IBootControl default
+ interface android.hardware.boot@1.1::IBootControl default
+ interface android.hardware.boot@1.2::IBootControl default
+ class early_hal
+ user root
+ group root
diff --git a/boot/1.2/default/android.hardware.boot@1.2.xml b/boot/1.2/default/android.hardware.boot@1.2.xml
new file mode 100644
index 0000000..ba91e8f
--- /dev/null
+++ b/boot/1.2/default/android.hardware.boot@1.2.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.boot</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.2::IBootControl/default</fqname>
+ </hal>
+</manifest>
diff --git a/boot/1.2/default/service.cpp b/boot/1.2/default/service.cpp
new file mode 100644
index 0000000..3053957
--- /dev/null
+++ b/boot/1.2/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "android.hardware.boot@1.2-service"
+
+#include <android/hardware/boot/1.2/IBootControl.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::defaultPassthroughServiceImplementation;
+using IBootControl_V1_0 = android::hardware::boot::V1_0::IBootControl;
+using IBootControl_V1_2 = android::hardware::boot::V1_2::IBootControl;
+
+int main(int /* argc */, char* /* argv */[]) {
+ return defaultPassthroughServiceImplementation<IBootControl_V1_0, IBootControl_V1_2>();
+}
diff --git a/boot/1.2/vts/functional/Android.bp b/boot/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..a7f5ccb
--- /dev/null
+++ b/boot/1.2/vts/functional/Android.bp
@@ -0,0 +1,31 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalBootV1_2TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalBootV1_2TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ "android.hardware.boot@1.2",
+ "libgmock",
+ ],
+ test_suites: [
+ "device-tests",
+ "vts",
+ ],
+}
diff --git a/boot/1.2/vts/functional/VtsHalBootV1_2TargetTest.cpp b/boot/1.2/vts/functional/VtsHalBootV1_2TargetTest.cpp
new file mode 100644
index 0000000..9df23c3
--- /dev/null
+++ b/boot/1.2/vts/functional/VtsHalBootV1_2TargetTest.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "boot_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/boot/1.2/IBootControl.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_0::CommandResult;
+using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::boot::V1_2::IBootControl;
+
+class BootHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ boot = IBootControl::getService(GetParam());
+ ASSERT_NE(boot, nullptr);
+
+ LOG(INFO) << "Test is remote " << boot->isRemote();
+ }
+
+ sp<IBootControl> boot;
+};
+
+auto generate_callback(CommandResult* dest) {
+ return [=](CommandResult cr) { *dest = cr; };
+}
+
+TEST_P(BootHidlTest, GetActiveBootSlot) {
+ Slot curSlot = boot->getCurrentSlot();
+ Slot otherSlot = curSlot ? 0 : 1;
+
+ // Set the active slot, then check if the getter returns the correct slot.
+ CommandResult cr;
+ Return<void> result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
+ EXPECT_TRUE(result.isOk());
+ Slot activeSlot = boot->getActiveBootSlot();
+ EXPECT_EQ(otherSlot, activeSlot);
+
+ result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
+ EXPECT_TRUE(result.isOk());
+ activeSlot = boot->getActiveBootSlot();
+ EXPECT_EQ(curSlot, activeSlot);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BootHidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, BootHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 86f26e4..27e74f1 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -529,24 +529,29 @@
}
void CameraModule::removeCamera(int cameraId) {
- std::unordered_set<std::string> physicalIds;
- camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
- mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
- common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
+ // Skip HAL1 devices which isn't cached in mCameraInfoMap and don't advertise
+ // static_camera_characteristics
+ if (getDeviceVersion(cameraId) >= CAMERA_DEVICE_API_VERSION_3_0) {
+ std::unordered_set<std::string> physicalIds;
+ camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
+ mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
+ common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
- if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
- for (const auto& id : physicalIds) {
- int idInt = std::stoi(id);
- if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
- free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
- mPhysicalCameraInfoMap.removeItem(idInt);
- } else {
- ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
- __FUNCTION__, id.c_str());
+ if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
+ for (const auto& id : physicalIds) {
+ int idInt = std::stoi(id);
+ if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
+ free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
+ mPhysicalCameraInfoMap.removeItem(idInt);
+ } else {
+ ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
+ __FUNCTION__, id.c_str());
+ }
}
}
+ free_camera_metadata(metadata);
}
- free_camera_metadata(metadata);
+
mCameraInfoMap.removeItem(cameraId);
mDeviceVersionMap.removeItem(cameraId);
}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9a5838b..72321e2 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -134,7 +134,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.boot</name>
- <version>1.1</version>
+ <version>1.2</version>
<interface>
<name>IBootControl</name>
<instance>default</instance>
@@ -430,6 +430,14 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.radio.config</name>
+ <version>1.3</version>
+ <interface>
+ <name>IRadioConfig</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.renderscript</name>
<version>1.0</version>
<interface>
diff --git a/current.txt b/current.txt
index 073beb7..7aa9593 100644
--- a/current.txt
+++ b/current.txt
@@ -771,6 +771,10 @@
6a271e493907e8ba20912e42771bd0d99ae45431a851d5675ef9496d02510a34 android.hardware.gnss@1.1::IGnssMeasurementCallback
2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient
3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types
+9679f27a42f75781c8993ef163ed92808a1928de186639834841d0b8e326e63d android.hardware.gatekeeper@1.0::IGatekeeper
+40456eb90ea88b62d18ad3fbf1da8917981cd55ac04ce69c8e058d49ff5beff4 android.hardware.keymaster@3.0::IKeymasterDevice
+6017b4f2481feb0fffceae81c62bc372c898998b2d8fe69fbd39859d3a315e5e android.hardware.keymaster@4.0::IKeymasterDevice
+dabe23dde7c9e3ad65c61def7392f186d7efe7f4216f9b6f9cf0863745b1a9f4 android.hardware.keymaster@4.1::IKeymasterDevice
cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index 28fd5b6..f5cb8e4 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -10,5 +10,5 @@
interfaces: [
"android.hidl.base@1.0",
],
- gen_java: true,
+ gen_java: false,
}
diff --git a/gatekeeper/1.0/IGatekeeper.hal b/gatekeeper/1.0/IGatekeeper.hal
index 59dd7d1..84e8e06 100644
--- a/gatekeeper/1.0/IGatekeeper.hal
+++ b/gatekeeper/1.0/IGatekeeper.hal
@@ -15,6 +15,7 @@
*/
package android.hardware.gatekeeper@1.0;
+@SensitiveData
interface IGatekeeper {
/**
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index e137afb..9e703d8 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -21,6 +21,7 @@
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
+ "libbase",
"libfmq",
"libsync",
"android.hardware.graphics.mapper@2.0",
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 4fee560..f0250c0 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "graphics_composer_hidl_hal_test"
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <composer-vts/2.1/ComposerVts.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
@@ -1102,3 +1103,15 @@
} // namespace graphics
} // namespace hardware
} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ using namespace std::chrono_literals;
+ if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
+ ALOGE("Failed to stop init.svc.surfaceflinger");
+ return -1;
+ }
+
+ return RUN_ALL_TESTS();
+}
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 16e9138..6aa836c 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -31,6 +31,7 @@
"libEGL",
"libGLESv1_CM",
"libGLESv2",
+ "libbase",
"libfmq",
"libgui",
"libhidlbase",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 4d7df1c..31ec885 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
@@ -700,3 +701,15 @@
} // namespace graphics
} // namespace hardware
} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ using namespace std::chrono_literals;
+ if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
+ ALOGE("Failed to stop init.svc.surfaceflinger");
+ return -1;
+ }
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 1ab6b3b..1cbb60e 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -21,6 +21,7 @@
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
+ "libbase",
"libfmq",
"libhidlbase",
"libsync",
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index a4c1b63..8b42654 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -19,6 +19,7 @@
#include <algorithm>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
@@ -630,3 +631,15 @@
} // namespace graphics
} // namespace hardware
} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ using namespace std::chrono_literals;
+ if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
+ ALOGE("Failed to stop init.svc.surfaceflinger");
+ return -1;
+ }
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index d0209b7..cab549c 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -21,6 +21,7 @@
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
+ "libbase",
"libfmq",
"libsync",
"android.hardware.graphics.mapper@2.0",
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index e6ecf93..d8312a2 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -21,6 +21,7 @@
#include <thread>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
#include <composer-vts/2.4/ComposerVts.h>
@@ -57,6 +58,25 @@
using ContentType = IComposerClient::ContentType;
using DisplayCapability = IComposerClient::DisplayCapability;
+class VtsDisplay {
+ public:
+ VtsDisplay(Display display, int32_t displayWidth, int32_t displayHeight)
+ : mDisplay(display), mDisplayWidth(displayWidth), mDisplayHeight(displayHeight) {}
+
+ Display get() const { return mDisplay; }
+
+ IComposerClient::FRect getCrop() const {
+ return {0, 0, static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)};
+ }
+
+ IComposerClient::Rect getFrameRect() const { return {0, 0, mDisplayWidth, mDisplayHeight}; }
+
+ private:
+ const Display mDisplay;
+ const int32_t mDisplayWidth;
+ const int32_t mDisplayHeight;
+};
+
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
void SetUp() override {
@@ -67,15 +87,19 @@
mComposerCallback = new GraphicsComposerCallback;
mComposerClient->registerCallback_2_4(mComposerCallback);
- // assume the first display is primary and is never removed
- mPrimaryDisplay = waitForFirstDisplay();
+ // assume the first displays are built-in and are never removed
+ mDisplays = waitForDisplays();
mInvalidDisplayId = GetInvalidDisplayId();
// explicitly disable vsync
- mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ for (const auto& display : mDisplays) {
+ mComposerClient->setVsyncEnabled(display.get(), false);
+ }
mComposerCallback->setVsyncAllowed(false);
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
}
@@ -83,6 +107,7 @@
void TearDown() override {
ASSERT_EQ(0, mReader->mErrors.size());
ASSERT_EQ(0, mReader->mCompositionChanges.size());
+
if (mComposerCallback != nullptr) {
EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
@@ -97,10 +122,10 @@
// display. Currently assuming that a device will never have close to
// std::numeric_limit<uint64_t>::max() displays registered while running tests
Display GetInvalidDisplayId() {
- std::vector<Display> validDisplays = mComposerCallback->getDisplays();
uint64_t id = std::numeric_limits<uint64_t>::max();
while (id > 0) {
- if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) {
+ if (std::none_of(mDisplays.begin(), mDisplays.end(),
+ [&](const VtsDisplay& display) { return id == display.get(); })) {
return id;
}
id--;
@@ -127,6 +152,30 @@
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+ const native_handle_t* allocate() {
+ return mGralloc->allocate(
+ /*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
+ static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
+ }
+
+ struct TestParameters {
+ nsecs_t delayForChange;
+ bool refreshMiss;
+ };
+
+ void Test_setActiveConfigWithConstraints(const TestParameters& params);
+
+ void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline*);
+
+ void waitForVsyncPeriodChange(Display display, const VsyncPeriodChangeTimeline& timeline,
+ int64_t desiredTimeNanos, int64_t oldPeriodNanos,
+ int64_t newPeriodNanos);
+
+ std::unique_ptr<ComposerClient> mComposerClient;
+ std::vector<VtsDisplay> mDisplays;
+ Display mInvalidDisplayId;
+
void forEachTwoConfigs(Display display, std::function<void(Config, Config)> func) {
const auto displayConfigs = mComposerClient->getDisplayConfigs(display);
for (const Config config1 : displayConfigs) {
@@ -138,88 +187,44 @@
}
}
- // use the slot count usually set by SF
- static constexpr uint32_t kBufferSlotCount = 64;
-
void Test_setContentType(const ContentType& contentType, const char* contentTypeStr);
void Test_setContentTypeForDisplay(const Display& display,
const std::vector<ContentType>& capabilities,
const ContentType& contentType, const char* contentTypeStr);
- std::unique_ptr<Composer> mComposer;
- std::unique_ptr<ComposerClient> mComposerClient;
- sp<GraphicsComposerCallback> mComposerCallback;
- // the first display and is assumed never to be removed
- Display mPrimaryDisplay;
- Display mInvalidDisplayId;
- std::unique_ptr<CommandWriterBase> mWriter;
- std::unique_ptr<TestCommandReader> mReader;
-
private:
- Display waitForFirstDisplay() {
+ // use the slot count usually set by SF
+ static constexpr uint32_t kBufferSlotCount = 64;
+
+ std::vector<VtsDisplay> waitForDisplays() {
while (true) {
+ // Sleep for a small period of time to allow all built-in displays
+ // to post hotplug events
+ std::this_thread::sleep_for(5ms);
std::vector<Display> displays = mComposerCallback->getDisplays();
if (displays.empty()) {
- usleep(5 * 1000);
continue;
}
- return displays[0];
+ std::vector<VtsDisplay> vtsDisplays;
+ vtsDisplays.reserve(displays.size());
+ for (Display display : displays) {
+ const Config activeConfig = mComposerClient->getActiveConfig(display);
+ const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
+ display, activeConfig, IComposerClient::Attribute::WIDTH);
+ const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
+ display, activeConfig, IComposerClient::Attribute::HEIGHT);
+ vtsDisplays.emplace_back(VtsDisplay{display, displayWidth, displayHeight});
+ }
+
+ return vtsDisplays;
}
}
-};
-// Tests for IComposerClient::Command.
-class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
- protected:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
-
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
- const Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
- mDisplayWidth = mComposerClient->getDisplayAttribute_2_4(mPrimaryDisplay, activeConfig,
- IComposerClient::Attribute::WIDTH);
- mDisplayHeight = mComposerClient->getDisplayAttribute_2_4(
- mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT);
-
- mWriter = std::make_unique<CommandWriterBase>(1024);
- mReader = std::make_unique<TestCommandReader>();
- }
-
- void TearDown() override {
- ASSERT_EQ(0, mReader->mErrors.size());
- ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
- }
-
- const native_handle_t* allocate() {
- return mGralloc->allocate(
- /*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
- static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
- static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
- }
-
- void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
-
- struct TestParameters {
- nsecs_t delayForChange;
- bool refreshMiss;
- };
-
- void Test_setActiveConfigWithConstraints(const TestParameters& params);
-
- void sendRefreshFrame(const VsyncPeriodChangeTimeline*);
-
- void waitForVsyncPeriodChange(Display display, const VsyncPeriodChangeTimeline& timeline,
- int64_t desiredTimeNanos, int64_t oldPeriodNanos,
- int64_t newPeriodNanos);
-
+ std::unique_ptr<Composer> mComposer;
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
- int32_t mDisplayWidth;
- int32_t mDisplayHeight;
-
- private:
+ sp<GraphicsComposerCallback> mComposerCallback;
std::unique_ptr<Gralloc> mGralloc;
};
@@ -230,9 +235,10 @@
}
TEST_P(GraphicsComposerHidlTest, getDisplayCapabilities) {
- for (Display display : mComposerCallback->getDisplays()) {
+ for (const auto& display : mDisplays) {
std::vector<IComposerClient::DisplayCapability> capabilities;
- EXPECT_EQ(Error::NONE, mComposerClient->getDisplayCapabilities(display, &capabilities));
+ EXPECT_EQ(Error::NONE,
+ mComposerClient->getDisplayCapabilities(display.get(), &capabilities));
}
}
@@ -241,38 +247,40 @@
EXPECT_EQ(Error::BAD_DISPLAY,
mComposerClient->getDisplayConnectionType(mInvalidDisplayId, &type));
- for (Display display : mComposerCallback->getDisplays()) {
- EXPECT_EQ(Error::NONE, mComposerClient->getDisplayConnectionType(display, &type));
+ for (const auto& display : mDisplays) {
+ EXPECT_EQ(Error::NONE, mComposerClient->getDisplayConnectionType(display.get(), &type));
}
}
TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4) {
- std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
- for (auto config : configs) {
- const std::array<IComposerClient::Attribute, 4> requiredAttributes = {{
- IComposerClient::Attribute::WIDTH,
- IComposerClient::Attribute::HEIGHT,
- IComposerClient::Attribute::VSYNC_PERIOD,
- IComposerClient::Attribute::CONFIG_GROUP,
- }};
- for (auto attribute : requiredAttributes) {
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- mPrimaryDisplay, config, attribute,
- [&](const auto& tmpError, const auto& value) {
- EXPECT_EQ(Error::NONE, tmpError);
- EXPECT_NE(-1, value);
- });
- }
+ for (const auto& display : mDisplays) {
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
+ for (auto config : configs) {
+ const std::array<IComposerClient::Attribute, 4> requiredAttributes = {{
+ IComposerClient::Attribute::WIDTH,
+ IComposerClient::Attribute::HEIGHT,
+ IComposerClient::Attribute::VSYNC_PERIOD,
+ IComposerClient::Attribute::CONFIG_GROUP,
+ }};
+ for (auto attribute : requiredAttributes) {
+ mComposerClient->getRaw()->getDisplayAttribute_2_4(
+ display.get(), config, attribute,
+ [&](const auto& tmpError, const auto& value) {
+ EXPECT_EQ(Error::NONE, tmpError);
+ EXPECT_NE(-1, value);
+ });
+ }
- const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
- IComposerClient::Attribute::DPI_X,
- IComposerClient::Attribute::DPI_Y,
- }};
- for (auto attribute : optionalAttributes) {
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) {
- EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
- });
+ const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
+ IComposerClient::Attribute::DPI_X,
+ IComposerClient::Attribute::DPI_Y,
+ }};
+ for (auto attribute : optionalAttributes) {
+ mComposerClient->getRaw()->getDisplayAttribute_2_4(
+ display.get(), config, attribute, [&](const auto& tmpError, const auto&) {
+ EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
+ });
+ }
}
}
}
@@ -283,11 +291,12 @@
mComposerClient->getDisplayVsyncPeriod(mInvalidDisplayId, &vsyncPeriodNanos));
}
-TEST_P(GraphicsComposerHidlCommandTest, getDisplayVsyncPeriod) {
- for (Display display : mComposerCallback->getDisplays()) {
- for (Config config : mComposerClient->getDisplayConfigs(display)) {
+TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod) {
+ for (const auto& display : mDisplays) {
+ for (Config config : mComposerClient->getDisplayConfigs(display.get())) {
VsyncPeriodNanos expectedVsyncPeriodNanos = mComposerClient->getDisplayAttribute_2_4(
- display, config, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+ display.get(), config,
+ IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
VsyncPeriodChangeTimeline timeline;
IComposerClient::VsyncPeriodChangeConstraints constraints;
@@ -295,12 +304,12 @@
constraints.desiredTimeNanos = systemTime();
constraints.seamlessRequired = false;
EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
- display, config, constraints, &timeline));
+ display.get(), config, constraints, &timeline));
if (timeline.refreshRequired) {
- sendRefreshFrame(&timeline);
+ sendRefreshFrame(display, &timeline);
}
- waitForVsyncPeriodChange(display, timeline, constraints.desiredTimeNanos, 0,
+ waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
expectedVsyncPeriodNanos);
VsyncPeriodNanos vsyncPeriodNanos;
@@ -309,7 +318,7 @@
std::this_thread::sleep_for(10ms);
vsyncPeriodNanos = 0;
EXPECT_EQ(Error::NONE,
- mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+ mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
--retryCount;
} while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
@@ -322,7 +331,7 @@
timeout *= 2;
vsyncPeriodNanos = 0;
EXPECT_EQ(Error::NONE,
- mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+ mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
}
}
@@ -347,31 +356,34 @@
constraints.seamlessRequired = false;
constraints.desiredTimeNanos = systemTime();
- for (Display display : mComposerCallback->getDisplays()) {
- Config invalidConfigId = GetInvalidConfigId(display);
- EXPECT_EQ(Error::BAD_CONFIG, mComposerClient->setActiveConfigWithConstraints(
- display, invalidConfigId, constraints, &timeline));
+ for (const auto& display : mDisplays) {
+ Config invalidConfigId = GetInvalidConfigId(display.get());
+ EXPECT_EQ(Error::BAD_CONFIG,
+ mComposerClient->setActiveConfigWithConstraints(display.get(), invalidConfigId,
+ constraints, &timeline));
}
}
-TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
VsyncPeriodChangeTimeline timeline;
IComposerClient::VsyncPeriodChangeConstraints constraints;
constraints.seamlessRequired = true;
constraints.desiredTimeNanos = systemTime();
- for (Display display : mComposerCallback->getDisplays()) {
- forEachTwoConfigs(display, [&](Config config1, Config config2) {
+ for (const auto& display : mDisplays) {
+ forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
- display, config1, IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
+ display.get(), config1,
+ IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
- display, config2, IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
+ display.get(), config2,
+ IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
if (configGroup1 != configGroup2) {
- mComposerClient->setActiveConfig(display, config1);
- sendRefreshFrame(nullptr);
+ mComposerClient->setActiveConfig(display.get(), config1);
+ sendRefreshFrame(display, nullptr);
EXPECT_EQ(Error::SEAMLESS_NOT_ALLOWED,
- mComposerClient->setActiveConfigWithConstraints(display, config2,
+ mComposerClient->setActiveConfigWithConstraints(display.get(), config2,
constraints, &timeline));
}
});
@@ -382,7 +394,8 @@
return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
}
-void GraphicsComposerHidlCommandTest::sendRefreshFrame(const VsyncPeriodChangeTimeline* timeline) {
+void GraphicsComposerHidlTest::sendRefreshFrame(const VtsDisplay& display,
+ const VsyncPeriodChangeTimeline* timeline) {
if (timeline != nullptr) {
// Refresh time should be before newVsyncAppliedTimeNanos
EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
@@ -390,29 +403,25 @@
std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
}
- mWriter->selectDisplay(mPrimaryDisplay);
- mComposerClient->setPowerMode(mPrimaryDisplay, V2_1::IComposerClient::PowerMode::ON);
- mComposerClient->setColorMode_2_3(mPrimaryDisplay, ColorMode::NATIVE,
- RenderIntent::COLORIMETRIC);
+ mWriter->selectDisplay(display.get());
+ mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON);
+ mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
auto handle = allocate();
ASSERT_NE(nullptr, handle);
- IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
-
Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount));
mWriter->selectLayer(layer);
mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
- mWriter->setLayerDisplayFrame(displayFrame);
+ mWriter->setLayerDisplayFrame(display.getFrameRect());
mWriter->setLayerPlaneAlpha(1);
- mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+ mWriter->setLayerSourceCrop(display.getCrop());
mWriter->setLayerTransform(static_cast<Transform>(0));
- mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, displayFrame));
+ mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
mWriter->setLayerZOrder(10);
mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
mWriter->setLayerBuffer(0, handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
@@ -440,9 +449,11 @@
execute();
}
-void GraphicsComposerHidlCommandTest::waitForVsyncPeriodChange(
- Display display, const VsyncPeriodChangeTimeline& timeline, int64_t desiredTimeNanos,
- int64_t oldPeriodNanos, int64_t newPeriodNanos) {
+void GraphicsComposerHidlTest::waitForVsyncPeriodChange(Display display,
+ const VsyncPeriodChangeTimeline& timeline,
+ int64_t desiredTimeNanos,
+ int64_t oldPeriodNanos,
+ int64_t newPeriodNanos) {
const auto CHANGE_DEADLINE = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
while (std::chrono::steady_clock::now() <= CHANGE_DEADLINE) {
VsyncPeriodNanos vsyncPeriodNanos;
@@ -456,17 +467,18 @@
}
}
-void GraphicsComposerHidlCommandTest::Test_setActiveConfigWithConstraints(
- const TestParameters& params) {
- for (Display display : mComposerCallback->getDisplays()) {
- forEachTwoConfigs(display, [&](Config config1, Config config2) {
- mComposerClient->setActiveConfig(display, config1);
- sendRefreshFrame(nullptr);
+void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(const TestParameters& params) {
+ for (const auto& display : mDisplays) {
+ forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
+ mComposerClient->setActiveConfig(display.get(), config1);
+ sendRefreshFrame(display, nullptr);
int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
- display, config1, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+ display.get(), config1,
+ IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
int32_t vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
- display, config2, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+ display.get(), config2,
+ IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
if (vsyncPeriod1 == vsyncPeriod2) {
return; // continue
@@ -477,7 +489,7 @@
.desiredTimeNanos = systemTime() + params.delayForChange,
.seamlessRequired = false};
EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
- display, config2, constraints, &timeline));
+ display.get(), config2, constraints, &timeline));
EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
// Refresh rate should change within a reasonable time
@@ -491,10 +503,10 @@
// callback
std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) + 100ms);
}
- sendRefreshFrame(&timeline);
+ sendRefreshFrame(display, &timeline);
}
- waitForVsyncPeriodChange(display, timeline, constraints.desiredTimeNanos, vsyncPeriod1,
- vsyncPeriod2);
+ waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
+ vsyncPeriod1, vsyncPeriod2);
// At this point the refresh rate should have changed already, however in rare
// cases the implementation might have missed the deadline. In this case a new
@@ -506,30 +518,30 @@
if (newTimeline.has_value()) {
if (newTimeline->refreshRequired) {
- sendRefreshFrame(&newTimeline.value());
+ sendRefreshFrame(display, &newTimeline.value());
}
- waitForVsyncPeriodChange(display, newTimeline.value(), constraints.desiredTimeNanos,
- vsyncPeriod1, vsyncPeriod2);
+ waitForVsyncPeriodChange(display.get(), newTimeline.value(),
+ constraints.desiredTimeNanos, vsyncPeriod1, vsyncPeriod2);
}
VsyncPeriodNanos vsyncPeriodNanos;
EXPECT_EQ(Error::NONE,
- mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+ mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
});
}
}
-TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints) {
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints) {
Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
}
-TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_Delayed) {
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_Delayed) {
Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000, // 300ms
.refreshMiss = false});
}
-TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_MissRefresh) {
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_MissRefresh) {
Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
}
@@ -539,9 +551,9 @@
}
TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) {
- for (Display display : mComposerCallback->getDisplays()) {
+ for (const auto& display : mDisplays) {
std::vector<DisplayCapability> capabilities;
- const auto error = mComposerClient->getDisplayCapabilities(display, &capabilities);
+ const auto error = mComposerClient->getDisplayCapabilities(display.get(), &capabilities);
EXPECT_EQ(Error::NONE, error);
const bool allmSupport =
@@ -550,16 +562,16 @@
if (!allmSupport) {
EXPECT_EQ(Error::UNSUPPORTED,
- mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
+ mComposerClient->setAutoLowLatencyMode(display.get(), true));
EXPECT_EQ(Error::UNSUPPORTED,
- mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
+ mComposerClient->setAutoLowLatencyMode(display.get(), false));
GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
- << std::to_string(display) << ", skipping test";
+ << std::to_string(display.get()) << ", skipping test";
return;
}
- EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
- EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
+ EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), true));
+ EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), false));
}
}
@@ -572,10 +584,10 @@
TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
std::vector<ContentType> supportedContentTypes;
- for (Display display : mComposerCallback->getDisplays()) {
+ for (const auto& display : mDisplays) {
supportedContentTypes.clear();
const auto error =
- mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
+ mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
const bool noneSupported =
std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
ContentType::NONE) != supportedContentTypes.end();
@@ -585,8 +597,8 @@
}
TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) {
- for (Display display : mComposerCallback->getDisplays()) {
- const auto error = mComposerClient->setContentType(display, ContentType::NONE);
+ for (const auto& display : mDisplays) {
+ const auto error = mComposerClient->setContentType(display.get(), ContentType::NONE);
EXPECT_NE(Error::UNSUPPORTED, error);
}
}
@@ -618,13 +630,14 @@
void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType,
const char* contentTypeStr) {
- for (Display display : mComposerCallback->getDisplays()) {
+ for (const auto& display : mDisplays) {
std::vector<ContentType> supportedContentTypes;
const auto error =
- mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
+ mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
EXPECT_EQ(Error::NONE, error);
- Test_setContentTypeForDisplay(display, supportedContentTypes, contentType, contentTypeStr);
+ Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
+ contentTypeStr);
}
}
@@ -650,13 +663,7 @@
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
android::hardware::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlCommandTest);
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, GraphicsComposerHidlCommandTest,
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
- android::hardware::PrintInstanceNameToString);
-
-TEST_P(GraphicsComposerHidlCommandTest, getLayerGenericMetadataKeys) {
+TEST_P(GraphicsComposerHidlTest, getLayerGenericMetadataKeys) {
std::vector<IComposerClient::LayerGenericMetadataKey> keys;
mComposerClient->getLayerGenericMetadataKeys(&keys);
@@ -685,3 +692,15 @@
} // namespace graphics
} // namespace hardware
} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ using namespace std::chrono_literals;
+ if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
+ ALOGE("Failed to stop init.svc.surfaceflinger");
+ return -1;
+ }
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index fbf3ab1..77b795b 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -55,6 +55,7 @@
#include <keymaster/contexts/soft_attestation_cert.h>
#include <keymaster/keymaster_tags.h>
#include <keymaster/km_openssl/attestation_utils.h>
+#include <keymaster/km_openssl/certificate_utils.h>
namespace android {
namespace hardware {
@@ -962,6 +963,18 @@
return {};
}
+ ::keymaster::X509_NAME_Ptr subjectName;
+ if (KM_ERROR_OK !=
+ ::keymaster::make_name_from_str("Android Identity Credential Key", &subjectName)) {
+ LOG(ERROR) << "Cannot create attestation subject";
+ return {};
+ }
+
+ vector<uint8_t> subject(i2d_X509_NAME(subjectName.get(), NULL));
+ unsigned char* subjectPtr = subject.data();
+
+ i2d_X509_NAME(subjectName.get(), &subjectPtr);
+
::keymaster::AuthorizationSet auth_set(
::keymaster::AuthorizationSetBuilder()
.Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
@@ -976,6 +989,8 @@
// includes app id.
.Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
applicationId.data(), applicationId.size())
+ .Authorization(::keymaster::TAG_CERTIFICATE_SUBJECT, subject.data(),
+ subject.size())
.Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
// Unique id and device id is not applicable for identity credential attestation,
@@ -1008,12 +1023,12 @@
// relying party is ever going to trust our batch key and those keys above
// it.
//
- ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+ ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
+ KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
- error = generate_attestation_from_EVP_with_subject_name(
- key, swEnforced, hwEnforced, auth_set, context, ::keymaster::kCurrentKeymasterVersion,
- *attestation_chain, *attestation_signing_key, "Android Identity Credential Key",
- &cert_chain_out);
+ error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
+ *attestation_chain, *attestation_signing_key,
+ &cert_chain_out);
if (KM_ERROR_OK != error || !cert_chain_out) {
LOG(ERROR) << "Error generate attestation from EVP key" << error;
@@ -2388,7 +2403,6 @@
return ret;
}
-
vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const vector<uint8_t>& getTestHardwareBoundKey() {
diff --git a/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
index 2664765..9bd8602 100644
--- a/keymaster/3.0/IKeymasterDevice.hal
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -20,6 +20,7 @@
* Keymaster device definition. For thorough documentation see the implementer's reference, at
* https://source.android.com/security/keystore/implementer-ref.html
*/
+@SensitiveData
interface IKeymasterDevice {
/**
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index 3475f79..dfde060 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -195,7 +195,7 @@
* Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
* IKeymasterDevice key, as described in the Key Access Control section above.
*/
-
+@SensitiveData
interface IKeymasterDevice {
/**
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
index bbeccaa..ccb9f2e 100644
--- a/keymaster/4.1/IKeymasterDevice.hal
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -37,6 +37,7 @@
* versions will be numbered as major_version * 10 + minor version. The addition of new attestable
* tags changes the attestation format again, slightly, so the attestationVersion must be 4.
*/
+@SensitiveData
interface IKeymasterDevice extends @4.0::IKeymasterDevice {
/**
* Called by client to notify the IKeymasterDevice that the device is now locked, and keys with
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
index fba58af..33a95fe 100644
--- a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
@@ -41,7 +41,7 @@
MIN_SECONDS_BETWEEN_OPS = 805306771,
MAX_USES_PER_BOOT = 805306772,
USER_ID = 805306869,
- USER_SECURE_ID = 1073742326,
+ USER_SECURE_ID = -1610612234,
NO_AUTH_REQUIRED = 1879048695,
USER_AUTH_TYPE = 268435960,
AUTH_TIMEOUT = 805306873,
diff --git a/keymint/aidl/android/hardware/keymint/Tag.aidl b/keymint/aidl/android/hardware/keymint/Tag.aidl
index e85a8f5..46da096 100644
--- a/keymint/aidl/android/hardware/keymint/Tag.aidl
+++ b/keymint/aidl/android/hardware/keymint/Tag.aidl
@@ -355,7 +355,7 @@
*
* Must be hardware-enforced.
*/
- USER_SECURE_ID = (4 << 28) | 502, /* TagType:UINT_REP */
+ USER_SECURE_ID = (10 << 28) | 502, /* TagType:ULONG_REP */
/**
* Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key. This tag
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index bbd5343..a68830d 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -37,7 +37,6 @@
nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device);
nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device);
nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device);
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device);
nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
V1_2::IDevice* device);
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 517d61f..a9e5377 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -42,6 +42,30 @@
#include <vector>
namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
+ } else {
+ result = validatedConvertToCanonical(capabilities);
+ }
+ };
+
+ const auto ret = device->getCapabilities_1_2(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+} // namespace
nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device) {
CHECK(device != nullptr);
@@ -106,27 +130,6 @@
return result;
}
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
- CHECK(device != nullptr);
-
- nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical =
- validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
- } else {
- result = validatedConvertToCanonical(capabilities);
- }
- };
-
- const auto ret = device->getCapabilities_1_2(cb);
- NN_TRY(hal::utils::handleTransportError(ret));
-
- return result;
-}
-
nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
V1_2::IDevice* device) {
CHECK(device != nullptr);
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 5e3d5c2..0fa244d 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -71,6 +71,27 @@
return NN_TRY(std::move(result));
}
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_3::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](ErrorStatus status, const Capabilities& capabilities) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getCapabilities_1_3 failed with " << toString(status);
+ } else {
+ result = validatedConvertToCanonical(capabilities);
+ }
+ };
+
+ const auto ret = device->getCapabilities_1_3(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
} // namespace
nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
@@ -87,7 +108,7 @@
auto versionString = NN_TRY(V1_2::utils::initVersionString(device.get()));
const auto deviceType = NN_TRY(V1_2::utils::initDeviceType(device.get()));
auto extensions = NN_TRY(V1_2::utils::initExtensions(device.get()));
- auto capabilities = NN_TRY(V1_2::utils::initCapabilities(device.get()));
+ auto capabilities = NN_TRY(initCapabilities(device.get()));
const auto numberOfCacheFilesNeeded =
NN_TRY(V1_2::utils::initNumberOfCacheFilesNeeded(device.get()));
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
new file mode 100644
index 0000000..8c04b88
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidBuffer final : public nn::IBuffer {
+ public:
+ nn::Request::MemoryDomainToken getToken() const override;
+
+ nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
+
+ nn::GeneralResult<void> copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const override;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
new file mode 100644
index 0000000..5e62b9a
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidDevice final : public nn::IDevice {
+ public:
+ InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString;
+ const nn::Version kFeatureLevel;
+ const nn::DeviceType kType;
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
new file mode 100644
index 0000000..4b32b4e
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidPreparedModel final : public nn::IPreparedModel {
+ public:
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 4a84e4d..4bfed6c 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -45,8 +45,9 @@
std::string versionString, std::vector<nn::Extension> extensions,
nn::Capabilities capabilities, nn::SharedDevice device);
- nn::SharedDevice getDevice() const;
- nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const;
+ nn::SharedDevice getDevice() const EXCLUDES(mMutex);
+ nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const
+ EXCLUDES(mMutex);
const std::string& getName() const override;
const std::string& getVersionString() const override;
@@ -78,6 +79,7 @@
const std::vector<nn::BufferRole>& outputRoles) const override;
private:
+ bool isValidInternal() const EXCLUDES(mMutex);
nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
nn::Priority priority, nn::OptionalTimePoint deadline,
@@ -100,6 +102,7 @@
const nn::Capabilities kCapabilities;
mutable std::mutex mMutex;
mutable nn::SharedDevice mDevice GUARDED_BY(mMutex);
+ mutable bool mIsValid GUARDED_BY(mMutex) = true;
};
} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidBuffer.cpp b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
new file mode 100644
index 0000000..c6f75d7
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidBuffer.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::Request::MemoryDomainToken InvalidBuffer::getToken() const {
+ return nn::Request::MemoryDomainToken{};
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyTo(const nn::Memory& /*dst*/) const {
+ return NN_ERROR() << "InvalidBuffer";
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyFrom(const nn::Memory& /*src*/,
+ const nn::Dimensions& /*dimensions*/) const {
+ return NN_ERROR() << "InvalidBuffer";
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
new file mode 100644
index 0000000..535ccb4
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidDevice.h"
+
+#include "InvalidBuffer.h"
+#include "InvalidPreparedModel.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+InvalidDevice::InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded)
+ : kName(std::move(name)),
+ kVersionString(std::move(versionString)),
+ kFeatureLevel(featureLevel),
+ kType(type),
+ kExtensions(std::move(extensions)),
+ kCapabilities(std::move(capabilities)),
+ kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded) {}
+
+const std::string& InvalidDevice::getName() const {
+ return kName;
+}
+
+const std::string& InvalidDevice::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version InvalidDevice::getFeatureLevel() const {
+ return kFeatureLevel;
+}
+
+nn::DeviceType InvalidDevice::getType() const {
+ return kType;
+}
+
+const std::vector<nn::Extension>& InvalidDevice::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& InvalidDevice::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> InvalidDevice::getNumberOfCacheFilesNeeded() const {
+ return kNumberOfCacheFilesNeeded;
+}
+
+nn::GeneralResult<void> InvalidDevice::wait() const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<std::vector<bool>> InvalidDevice::getSupportedOperations(
+ const nn::Model& /*model*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModel(
+ const nn::Model& /*model*/, nn::ExecutionPreference /*preference*/,
+ nn::Priority /*priority*/, nn::OptionalTimePoint /*deadline*/,
+ const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModelFromCache(
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedBuffer> InvalidDevice::allocate(
+ const nn::BufferDesc& /*desc*/,
+ const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+ const std::vector<nn::BufferRole>& /*inputRoles*/,
+ const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
new file mode 100644
index 0000000..9ae7a63
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidPreparedModel.h"
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+InvalidPreparedModel::execute(const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
+ const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+ return NN_ERROR() << "InvalidPreparedModel";
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+InvalidPreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+ return NN_ERROR() << "InvalidPreparedModel";
+}
+
+std::any InvalidPreparedModel::getUnderlyingResource() const {
+ return {};
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 26025a5..2f83c5c 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -16,6 +16,9 @@
#include "ResilientDevice.h"
+#include "InvalidBuffer.h"
+#include "InvalidDevice.h"
+#include "InvalidPreparedModel.h"
#include "ResilientBuffer.h"
#include "ResilientPreparedModel.h"
@@ -107,12 +110,21 @@
}
auto device = std::move(maybeDevice).value();
- // TODO(b/173081926): Instead of CHECKing to ensure the cache has not been changed, return an
- // invalid/"null" IDevice object that always fails.
- CHECK_EQ(kName, device->getName());
- CHECK_EQ(kVersionString, device->getVersionString());
- CHECK(kExtensions == device->getSupportedExtensions());
- CHECK_EQ(kCapabilities, device->getCapabilities());
+ // If recovered device has different metadata than what is cached (i.e., because it was
+ // updated), mark the device as invalid and preserve the cached data.
+ auto compare = [this, &device](auto fn) REQUIRES(mMutex) {
+ return std::invoke(fn, mDevice) != std::invoke(fn, device);
+ };
+ if (compare(&IDevice::getName) || compare(&IDevice::getVersionString) ||
+ compare(&IDevice::getFeatureLevel) || compare(&IDevice::getType) ||
+ compare(&IDevice::getSupportedExtensions) || compare(&IDevice::getCapabilities)) {
+ LOG(ERROR) << "Recovered device has different metadata than what is cached. Marking "
+ "IDevice object as invalid.";
+ device = std::make_shared<const InvalidDevice>(
+ kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(), kExtensions,
+ kCapabilities, mDevice->getNumberOfCacheFilesNeeded());
+ mIsValid = false;
+ }
mDevice = std::move(device);
return mDevice;
@@ -199,11 +211,19 @@
return ResilientBuffer::create(std::move(makeBuffer));
}
+bool ResilientDevice::isValidInternal() const {
+ std::lock_guard hold(mMutex);
+ return mIsValid;
+}
+
nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
nn::Priority priority, nn::OptionalTimePoint deadline,
const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidPreparedModel>();
+ }
const auto fn = [&model, preference, priority, deadline, &modelCache, &dataCache,
token](const nn::IDevice& device) {
return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
@@ -216,6 +236,9 @@
bool blocking, nn::OptionalTimePoint deadline,
const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidPreparedModel>();
+ }
const auto fn = [deadline, &modelCache, &dataCache, token](const nn::IDevice& device) {
return device.prepareModelFromCache(deadline, modelCache, dataCache, token);
};
@@ -227,6 +250,9 @@
const std::vector<nn::SharedPreparedModel>& preparedModels,
const std::vector<nn::BufferRole>& inputRoles,
const std::vector<nn::BufferRole>& outputRoles) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidBuffer>();
+ }
const auto fn = [&desc, &preparedModels, &inputRoles, &outputRoles](const nn::IDevice& device) {
return device.allocate(desc, preparedModels, inputRoles, outputRoles);
};
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index 8afbf22..0e7354d 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -217,6 +217,13 @@
* Each subsequent request to this method is processed only after the
* completion of the previous one.
*
+ * When the SIM is in POWER_DOWN, the modem should send an empty vector of
+ * AppStatus in CardStatus.applications. If a SIM in the POWER_DOWN state
+ * is removed and a new SIM is inserted, the new SIM should be in POWER_UP
+ * mode by default. If the device is turned off or restarted while the SIM
+ * is in POWER_DOWN, then the SIM should turn on normally in POWER_UP mode
+ * when the device turns back on.
+ *
* Response callback is IRadioResponse.setSimCardPowerResponse_1_6().
* Note that this differs from setSimCardPower_1_1 in that the response
* callback should only be sent once the device has finished executing
@@ -340,13 +347,54 @@
*
* @param serial Serial number of request.
* @param dataThrottlingAction DataThrottlingAction as defined in types.hal
- * @param completionWindowSecs window, in seconds, in which the requested
- * throttling action has to be achieved. This must be 0 when
+ * @param completionDurationMillis window, in milliseconds, in which the
+ * requested throttling action has to be achieved. This must be 0 when
* dataThrottlingAction is DataThrottlingAction:HOLD.
*
* Response function is IRadioResponse.setDataThrottlingResponse()
*/
oneway setDataThrottling(int32_t serial,
DataThrottlingAction dataThrottlingAction,
- int32_t completionWindowSecs);
+ int64_t completionDurationMillis);
+
+ /**
+ * Get which bands the modem's background scan is acting on.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response callback is IRadioResponse.getSystemSelectionChannelsResponse()
+ */
+ oneway getSystemSelectionChannels(int32_t serial);
+
+ /**
+ * Request all of the current cell information known to the radio. The radio
+ * must return list of all current cells, including the neighboring cells. If for a particular
+ * cell information isn't known then the appropriate unknown value will be returned.
+ * This does not cause or change the rate of unsolicited cellInfoList().
+ *
+ * This is identitcal to getCellInfoList in V1.0, but it requests updated version of CellInfo.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response callback is IRadioResponse.getCellInfoListResponse()
+ */
+ oneway getCellInfoList_1_6(int32_t serial);
+
+ /**
+ * Request current voice registration state.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioResponse.getVoiceRegistrationStateResponse_1_6()
+ */
+ oneway getVoiceRegistrationState_1_6(int32_t serial);
+
+ /**
+ * Request current data registration state.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioResponse.getDataRegistrationStateResponse_1_6()
+ */
+ oneway getDataRegistrationState_1_6(int32_t serial);
};
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index f195c0e..bc6e397 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -18,8 +18,10 @@
import @1.0::RadioIndicationType;
import @1.5::IRadioIndication;
-import @1.6::SetupDataCallResult;
+import @1.6::CellInfo;
import @1.6::LinkCapacityEstimate;
+import @1.6::NetworkScanResult;
+import @1.6::SetupDataCallResult;
/**
* Interface declaring unsolicited radio indications.
@@ -67,4 +69,23 @@
* @param lce LinkCapacityEstimate
*/
oneway currentLinkCapacityEstimate_1_6(RadioIndicationType type, LinkCapacityEstimate lce);
+
+ /**
+ * Report all of the current cell information known to the radio.
+ *
+ * This indication is updated from IRadioIndication@1.5 to report the @1.6 version of
+ * CellInfo.
+ *
+ * @param type Type of radio indication
+ * @param records Current cell information
+ */
+ oneway cellInfoList_1_6(RadioIndicationType type, vec<CellInfo> records);
+
+ /**
+ * Incremental network scan results.
+ *
+ * This indication is updated from IRadioIndication@1.5 to report the @1.6 version of
+ * CellInfo.
+ */
+ oneway networkScanResult_1_6(RadioIndicationType type, NetworkScanResult result);
};
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index 5a71c1f..0f08a46 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -17,8 +17,10 @@
package android.hardware.radio@1.6;
import @1.0::SendSmsResult;
-import @1.6::RadioResponseInfo;
import @1.5::IRadioResponse;
+import @1.6::CellInfo;
+import @1.6::RegStateResult;
+import @1.6::RadioResponseInfo;
import @1.6::SetupDataCallResult;
/**
@@ -207,7 +209,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
* RadioError:SIM_ERR (indicates a timeout or other issue making the SIM unresponsive)
*
@@ -317,4 +318,55 @@
* RadioError:INVALID_ARGUMENTS
*/
oneway setDataThrottlingResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ */
+ oneway getSystemSelectionChannelsResponse(RadioResponseInfo info);
+
+ /**
+ * This is identical to getCellInfoListResponse_1_5 but uses an updated version of CellInfo.
+ *
+ * @param info Response info struct containing response type, serial no. and error
+ * @param cellInfo List of current cell information known to radio
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway getCellInfoListResponse_1_6(RadioResponseInfo info, vec<CellInfo> cellInfo);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param voiceRegResponse Current Voice registration response as defined by RegStateResult
+ * in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway getVoiceRegistrationStateResponse_1_6(RadioResponseInfo info,
+ RegStateResult voiceRegResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dataRegResponse Current Data registration response as defined by RegStateResult in
+ * types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NOT_PROVISIONED
+ */
+ oneway getDataRegistrationStateResponse_1_6(RadioResponseInfo info,
+ RegStateResult dataRegResponse);
};
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 2cba915..20dc612 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -16,12 +16,35 @@
package android.hardware.radio@1.6;
+import @1.0::CdmaSignalStrength;
+import @1.0::EvdoSignalStrength;
+import @1.0::GsmSignalStrength;
+import @1.0::LteSignalStrength;
import @1.0::RadioError;
import @1.0::RadioResponseType;
+import @1.0::RegState;
+import @1.1::ScanStatus;
+import @1.2::CellInfoCdma;
+import @1.2::CellConnectionStatus;
+import @1.2::TdscdmaSignalStrength;
+import @1.2::WcdmaSignalStrength;
import @1.4::DataCallFailCause;
import @1.4::DataConnActiveStatus;
+import @1.4::NrSignalStrength;
import @1.4::PdpProtocolType;
+import @1.4::RadioTechnology;
+import @1.5::CellIdentity;
+import @1.5::CellIdentityLte;
+import @1.5::CellIdentityNr;
+import @1.5::CellInfoGsm;
+import @1.5::CellInfoWcdma;
+import @1.5::CellInfoTdscdma;
import @1.5::LinkAddress;
+import @1.5::RegStateResult.AccessTechnologySpecificInfo.Cdma2000RegistrationInfo;
+import @1.5::RegStateResult.AccessTechnologySpecificInfo.EutranRegistrationInfo;
+import @1.5::RegistrationFailCause;
+import @1.5::SetupDataCallResult;
+
import android.hidl.safe_union@1.0::Monostate;
struct QosBandwidth {
@@ -416,3 +439,287 @@
*/
HOLD = 3
};
+
+/**
+ * Defines the values for VoPS indicator of NR as per 3gpp spec 24.501 sec 9.10.3.5
+ */
+enum VopsIndicator : uint8_t {
+ /** IMS voice over PS session not supported */
+ VOPS_NOT_SUPPORTED = 0,
+ /** IMS voice over PS session supported over 3GPP access */
+ VOPS_OVER_3GPP = 1,
+ /** IMS voice over PS session supported over non-3GPP access */
+ VOPS_OVER_NON_3GPP = 2,
+};
+
+/**
+ * Defines the values for emergency service indicator of NR
+ * as per 3gpp spec 24.501 sec 9.10.3.5
+ */
+enum EmcIndicator : uint8_t {
+ /** Emergency services not supported */
+ EMC_NOT_SUPPORTED = 0,
+ /** Emergency services supported in NR connected to 5GCN only */
+ EMC_NR_CONNECTED_TO_5GCN = 1,
+ /** Emergency services supported in E-UTRA connected to 5GCN only */
+ EMC_EUTRA_CONNECTED_TO_5GCN = 2,
+ /** Emergency services supported in NR connected to 5GCN and E-UTRA connected to 5GCN */
+ EMC_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3
+};
+
+/**
+ * Defines the values for emergency service fallback indicator of NR
+ * as per 3gpp spec 24.501 sec 9.10.3.5
+ */
+enum EmfIndicator : uint8_t {
+ /** Emergency services fallback not supported */
+ EMF_NOT_SUPPORTED = 0,
+ /** Emergency services fallback supported in NR connected to 5GCN only */
+ EMF_NR_CONNECTED_TO_5GCN = 1,
+ /** Emergency services fallback supported in E-UTRA connected to 5GCN only */
+ EMF_EUTRA_CONNECTED_TO_5GCN = 2,
+ /**
+ * Emergency services fallback supported in NR connected to 5GCN and E-UTRA
+ * connected to 5GCN.
+ */
+ EMF_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3
+};
+
+/**
+ * Type to define the NR specific network capabilities for voice over PS including
+ * emergency and normal voice calls.
+ */
+struct NrVopsInfo {
+ /**
+ * This indicates if the camped network supports VoNR services, and what kind of services
+ * it supports. This information is received from NR network during NR NAS registration
+ * procedure through NR REGISTRATION ACCEPT.
+ * Refer 3GPP 24.501 EPS 5GS network feature support -> IMS VoPS
+ */
+ VopsIndicator vopsSupported;
+
+ /**
+ * This indicates if the camped network supports VoNR emergency service. This information
+ * is received from NR network through two sources:
+ * a. During NR NAS registration procedure through NR REGISTRATION ACCEPT.
+ * Refer 3GPP 24.501 EPS 5GS network feature support -> EMC
+ * b. In case the device is not registered on the network.
+ * Refer 3GPP 38.331 SIB1 : ims-EmergencySupport
+ * If device is registered on NR, then this field indicates whether the cell
+ * supports IMS emergency bearer services for UEs in limited service mode.
+ */
+ EmcIndicator emcSupported;
+
+ /**
+ * This indicates if the camped network supports VoNR emergency service fallback. This
+ * information is received from NR network during NR NAS registration procedure through
+ * NR REGISTRATION ACCEPT.
+ * Refer 3GPP 24.501 EPS 5GS network feature support -> EMF
+ */
+ EmfIndicator emfSupported;
+};
+
+struct LteSignalStrength {
+ @1.0::LteSignalStrength base;
+
+ /**
+ * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
+ * The definition of CQI in each table is different.
+ *
+ * Reference: 3GPP TS 136.213 section 7.2.3.
+ *
+ * Range [1, 6], INT_MAX means invalid/unreported.
+ */
+ uint32_t cqiTableIndex;
+};
+
+struct NrSignalStrength {
+ @1.4::NrSignalStrength base;
+
+ /**
+ * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
+ * The definition of CQI in each table is different.
+ *
+ * Reference: 3GPP TS 138.214 section 5.2.2.1.
+ *
+ * Range [1, 3], INT_MAX means invalid/unreported.
+ */
+ uint32_t csiCqiTableIndex;
+
+ /**
+ * CSI channel quality indicator (CQI) for all subbands.
+ *
+ * If the CQI report is for the entire wideband, a single CQI index is provided.
+ * If the CQI report is for all subbands, one CQI index is provided for each subband,
+ * in ascending order of subband index.
+ * If CQI is not available, the CQI report is empty.
+ *
+ * Reference: 3GPP TS 138.214 section 5.2.2.1.
+ *
+ * Range [0, 15], INT_MAX means invalid/unreported.
+ */
+ vec<uint32_t> csiCqiReport;
+};
+
+/**
+ * Overwritten from @1.4::SignalStrength in order to update LteSignalStrength and NrSignalStrength.
+ */
+struct SignalStrength {
+ /**
+ * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ GsmSignalStrength gsm;
+
+ /**
+ * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ CdmaSignalStrength cdma;
+
+ /**
+ * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ EvdoSignalStrength evdo;
+
+ /**
+ * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ LteSignalStrength lte;
+
+ /**
+ * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+ * otherwise all fields should be set to INT_MAX to mark them as invalid.
+ */
+ TdscdmaSignalStrength tdscdma;
+
+ /**
+ * If WCDMA measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ WcdmaSignalStrength wcdma;
+
+ /**
+ * If NR 5G measurements are provided, this structure must contain valid measurements; otherwise
+ * all fields should be set to INT_MAX to mark them as invalid.
+ */
+ NrSignalStrength nr;
+};
+
+/** Overwritten from @1.5::CellInfoLte in order to update LteSignalStrength. */
+struct CellInfoLte {
+ CellIdentityLte cellIdentityLte;
+ LteSignalStrength signalStrengthLte;
+};
+
+/** Overwritten from @1.5::CellInfoNr in order to update NrSignalStrength. */
+struct CellInfoNr {
+ CellIdentityNr cellIdentityNr;
+ NrSignalStrength signalStrengthNr;
+};
+
+/** Overwritten from @1.5::CellInfo in order to update LteSignalStrength and NrSignalStrength. */
+struct CellInfo {
+ /**
+ * True if this cell is registered false if not registered.
+ */
+ bool registered;
+ /**
+ * Connection status for the cell.
+ */
+ CellConnectionStatus connectionStatus;
+
+ safe_union CellInfoRatSpecificInfo {
+ /**
+ * 3gpp CellInfo types.
+ */
+ CellInfoGsm gsm;
+ CellInfoWcdma wcdma;
+ CellInfoTdscdma tdscdma;
+ CellInfoLte lte;
+ CellInfoNr nr;
+
+ /**
+ * 3gpp2 CellInfo types;
+ */
+ CellInfoCdma cdma;
+ } ratSpecificInfo;
+};
+
+/** Overwritten from @1.5::NetworkScanResult in order to update the CellInfo to 1.6 version. */
+struct NetworkScanResult {
+ /**
+ * The status of the scan.
+ */
+ ScanStatus status;
+
+ /**
+ * The error code of the incremental result.
+ */
+ RadioError error;
+
+ /**
+ * List of network information as CellInfo.
+ */
+ vec<CellInfo> networkInfos;
+};
+
+/**
+ * Overwritten from @1.5::RegStateResult to 1.6 to support NrRegistrationInfo
+ * version.
+ */
+struct RegStateResult {
+ /**
+ * Registration state
+ *
+ * If the RAT is indicated as a GERAN, UTRAN, or CDMA2000 technology, this value reports
+ * registration in the Circuit-switched domain.
+ * If the RAT is indicated as an EUTRAN, NGRAN, or another technology that does not support
+ * circuit-switched services, this value reports registration in the Packet-switched domain.
+ */
+ RegState regState;
+
+ /**
+ * Indicates the available voice radio technology, valid values as
+ * defined by RadioTechnology.
+ */
+ RadioTechnology rat;
+
+ /**
+ * Cause code reported by the network in case registration fails. This will be a mobility
+ * management cause code defined for MM, GMM, MME or equivalent as appropriate for the RAT.
+ */
+ RegistrationFailCause reasonForDenial;
+
+ /** CellIdentity */
+ CellIdentity cellIdentity;
+
+ /**
+ * The most-recent PLMN-ID upon which the UE registered (or attempted to register if a failure
+ * is reported in the reasonForDenial field). This PLMN shall be in standard format consisting
+ * of a 3 digit MCC concatenated with a 2 or 3 digit MNC.
+ */
+ string registeredPlmn;
+
+ /**
+ * Access-technology-specific registration information, such as for CDMA2000.
+ */
+ safe_union AccessTechnologySpecificInfo {
+ Monostate noinit;
+
+ Cdma2000RegistrationInfo cdmaInfo;
+
+ EutranRegistrationInfo eutranInfo;
+
+ struct NgranRegistrationInfo {
+ /**
+ * Network capabilities for voice over PS services. This info is valid only on NR
+ * network and must be present when the device is camped on NR. VopsInfo must be
+ * empty when the device is not camped on NR.
+ */
+ NrVopsInfo nrVopsInfo;
+ } ngranInfo;
+ } accessTechnologySpecificInfo;
+};
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 d3ffba9..75772cd 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -303,7 +303,7 @@
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_6->setDataThrottling(
- serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60);
+ serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60000);
ASSERT_OK(res);
EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -318,7 +318,22 @@
serial = GetRandomSerialNumber();
- res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER, 60);
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
+ 60000);
+ ASSERT_OK(res);
+ 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}));
+
+ serial = GetRandomSerialNumber();
+
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
ASSERT_OK(res);
EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -333,9 +348,8 @@
serial = GetRandomSerialNumber();
- res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::HOLD, 60);
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
ASSERT_OK(res);
-
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);
@@ -345,19 +359,50 @@
::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
::android::hardware::radio::V1_6::RadioError::NONE,
::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+}
+/*
+ * Test IRadio.setSimCardPower_1_6() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setSimCardPower_1_6) {
+ /* Test setSimCardPower power down */
serial = GetRandomSerialNumber();
-
- res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60);
- ASSERT_OK(res);
-
+ radio_v1_6->setSimCardPower_1_6(serial, CardPowerState::POWER_DOWN);
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}));
-}
\ No newline at end of file
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+
+ // setSimCardPower_1_6 does not return until the request is handled, and should not trigger
+ // CardState::ABSENT when turning off power
+ if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+ /* Wait some time for setting sim power down and then verify it */
+ updateSimCardStatus();
+ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+ // applications should be an empty vector of AppStatus
+ EXPECT_EQ(0, cardStatus.applications.size());
+ }
+
+ /* Test setSimCardPower power up */
+ serial = GetRandomSerialNumber();
+ radio_v1_6->setSimCardPower_1_6(serial, CardPowerState::POWER_UP);
+ 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::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+
+ // setSimCardPower_1_6 does not return until the request is handled. Just verify that we still
+ // have CardState::PRESENT after turning the power back on
+ if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+ updateSimCardStatus();
+ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+ }
+}
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 fcf679c..964259d 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
@@ -795,6 +795,22 @@
Return<void> setDataThrottlingResponse(
const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> getSystemSelectionChannelsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> getCellInfoListResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_6::CellInfo>&
+ cellInfo);
+
+ Return<void> getVoiceRegistrationStateResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::RegStateResult& regResponse);
+
+ Return<void> getDataRegistrationStateResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::RegStateResult& regResponse);
};
/* Callback class for radio indication */
@@ -814,6 +830,15 @@
Return<void> unthrottleApn(RadioIndicationType type,
const ::android::hardware::hidl_string& apn);
+ Return<void> networkScanResult_1_6(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_6::NetworkScanResult& result);
+
+ Return<void> cellInfoList_1_6(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_6::CellInfo>&
+ records);
+
/* 1.5 Api */
Return<void> uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
index afde291..4dffe63 100644
--- a/radio/1.6/vts/functional/radio_indication.cpp
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -386,3 +386,16 @@
const ::android::hardware::hidl_string& /*reason*/) {
return Void();
}
+
+Return<void> RadioIndication_v1_6::networkScanResult_1_6(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_6::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_6(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_6::CellInfo>& /*records*/) {
+ return Void();
+}
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index 788038a..cd3b2cf 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -1163,3 +1163,33 @@
parent_v1_6.notify(info.serial);
return Void();
}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_6::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSystemSelectionChannelsResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::RegStateResult& /*regResponse*/) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_6::RegStateResult& /*regResponse*/) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
new file mode 100644
index 0000000..ace0de9
--- /dev/null
+++ b/radio/config/1.3/Android.bp
@@ -0,0 +1,21 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.radio.config@1.3",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IRadioConfig.hal",
+ "IRadioConfigResponse.hal",
+ ],
+ interfaces: [
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
+ "android.hardware.radio.config@1.2",
+ "android.hardware.radio@1.0",
+ "android.hardware.radio@1.6",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+ system_ext_specific: true,
+}
diff --git a/radio/config/1.3/IRadioConfig.hal b/radio/config/1.3/IRadioConfig.hal
new file mode 100644
index 0000000..83bcf92
--- /dev/null
+++ b/radio/config/1.3/IRadioConfig.hal
@@ -0,0 +1,42 @@
+/*
+ * 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 interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+
+package android.hardware.radio.config@1.3;
+
+import @1.1::IRadioConfig;
+import IRadioConfigResponse;
+
+interface IRadioConfig extends @1.1::IRadioConfig {
+ /**
+ * Gets the available Radio Hal capabilities on the current device.
+ *
+ * This is called once per device boot up.
+ *
+ * @param serial Serial number of request
+ *
+ * Response callback is
+ * IRadioConfigResponse.getHalDeviceCapabilitiesResponse()
+ */
+ oneway getHalDeviceCapabilities(int32_t serial);
+};
diff --git a/radio/config/1.3/IRadioConfigResponse.hal b/radio/config/1.3/IRadioConfigResponse.hal
new file mode 100644
index 0000000..863754f
--- /dev/null
+++ b/radio/config/1.3/IRadioConfigResponse.hal
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config@1.3;
+
+import android.hardware.radio@1.6::RadioResponseInfo;
+import @1.2::IRadioConfigResponse;
+import HalDeviceCapabilities;
+
+/**
+ * Interface declaring response functions to solicited radio config requests.
+ */
+interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param capabilities Capabilities struct containing the capabilities of the
+ * device related to the Radio HAL
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway getHalDeviceCapabilitiesResponse(RadioResponseInfo info,
+ HalDeviceCapabilities capabilities);
+};
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
new file mode 100644
index 0000000..bedb709
--- /dev/null
+++ b/radio/config/1.3/types.hal
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config@1.3;
+
+/**
+ * Contains the device capabilities with respect to the Radio HAL.
+ */
+struct HalDeviceCapabilities {};
diff --git a/radio/config/1.3/vts/functional/Android.bp b/radio/config/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..abd081f
--- /dev/null
+++ b/radio/config/1.3/vts/functional/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+ name: "VtsHalRadioConfigV1_3TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "radio_config_hidl_hal_api.cpp",
+ "radio_config_hidl_hal_test.cpp",
+ "radio_config_response.cpp",
+ "radio_config_indication.cpp",
+ "VtsHalRadioConfigV1_3TargetTest.cpp",
+ ],
+ static_libs: [
+ "RadioVtsTestUtilBase",
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
+ "android.hardware.radio.config@1.2",
+ "android.hardware.radio.config@1.3",
+ ],
+ header_libs: ["radio.util.header@1.0"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp b/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
new file mode 100644
index 0000000..5772d08
--- /dev/null
+++ b/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigHidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioConfigHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IRadioConfig::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
new file mode 100644
index 0000000..8df02dd
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getHalDeviceCapabilities()
+ */
+TEST_P(RadioConfigHidlTest, getHalDeviceCapabilities) {
+ const int serial = GetRandomSerialNumber();
+ Return<void> res = radioConfig->getHalDeviceCapabilities(serial);
+ ASSERT_OK(res);
+ ALOGI("getHalDeviceCapabilities, rspInfo.error = %s\n",
+ toString(radioConfigRsp->rspInfo.error).c_str());
+}
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..de8365a
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+ radioConfig = IRadioConfig::getService(GetParam());
+ if (radioConfig == NULL) {
+ sleep(60);
+ radioConfig = IRadioConfig::getService(GetParam());
+ }
+ ASSERT_NE(nullptr, radioConfig.get());
+
+ radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+ ASSERT_NE(nullptr, radioConfigRsp.get());
+
+ count_ = 0;
+
+ radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify(int receivedSerial) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ if (serial == receivedSerial) {
+ count_++;
+ cv_.notify_one();
+ }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+ std::unique_lock<std::mutex> lock(mtx_);
+
+ std::cv_status status = std::cv_status::no_timeout;
+ auto now = std::chrono::system_clock::now();
+ while (count_ == 0) {
+ status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) {
+ return status;
+ }
+ }
+ count_--;
+ return status;
+}
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
new file mode 100644
index 0000000..439eb70
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+#include <android/hardware/radio/config/1.1/types.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.2/types.h>
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.3/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <log/log.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_2;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::radio::config::V1_1::ModemsConfig;
+using ::android::hardware::radio::config::V1_1::PhoneCapability;
+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::V1_0::RadioResponseInfo;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public IRadioConfigResponse {
+ protected:
+ RadioConfigHidlTest& parent;
+
+ public:
+ RadioResponseInfo rspInfo;
+ PhoneCapability phoneCap;
+
+ RadioConfigResponse(RadioConfigHidlTest& parent);
+ virtual ~RadioConfigResponse() = default;
+
+ Return<void> getSimSlotsStatusResponse(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus);
+
+ Return<void> getSimSlotsStatusResponse_1_2(
+ const RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+
+ Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+
+ Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+ const PhoneCapability& phoneCapability);
+
+ Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
+
+ Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+ const ModemsConfig& mConfig);
+
+ Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
+
+ Return<void> getHalDeviceCapabilitiesResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const HalDeviceCapabilities& halDeviceCapabilities);
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public IRadioConfigIndication {
+ protected:
+ RadioConfigHidlTest& parent;
+
+ public:
+ RadioConfigIndication(RadioConfigHidlTest& parent);
+ virtual ~RadioConfigIndication() = default;
+
+ Return<void> simSlotsStatusChanged_1_2(
+ ::android::hardware::radio::V1_0::RadioIndicationType type,
+ const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::TestWithParam<std::string> {
+ protected:
+ std::mutex mtx_;
+ std::condition_variable cv_;
+ int count_;
+
+ public:
+ virtual void SetUp() override;
+
+ /* Used as a mechanism to inform the test about data/event callback */
+ void notify(int receivedSerial);
+
+ /* Test code calls this function to wait for response */
+ std::cv_status wait();
+
+ void updateSimCardStatus();
+
+ /* Serial number for radio request */
+ int serial;
+
+ /* radio config service handle */
+ sp<IRadioConfig> radioConfig;
+
+ /* radio config response handle */
+ sp<RadioConfigResponse> radioConfigRsp;
+};
diff --git a/radio/config/1.3/vts/functional/radio_config_indication.cpp b/radio/config/1.3/vts/functional/radio_config_indication.cpp
new file mode 100644
index 0000000..6fa443c
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_indication.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+RadioConfigIndication::RadioConfigIndication(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
+ ::android::hardware::radio::V1_0::RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<SimSlotStatus>& /*slotStatus*/) {
+ return Void();
+}
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..2a8b28b
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+// SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::config::V1_0::SimSlotStatus>& /* slotStatus */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+ const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const PhoneCapability& phoneCapability) {
+ rspInfo = info;
+ phoneCap = phoneCapability;
+ parent.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+ const ModemsConfig& /* mConfig */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+ return Void();
+}
+
+Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& /* info */,
+ const ::android::hardware::radio::config::V1_3::HalDeviceCapabilities& /* capabilities */) {
+ return Void();
+}
\ No newline at end of file
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 870980f..4701579 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -26,6 +26,7 @@
namespace V2_X {
namespace implementation {
+using ::android::hardware::sensors::V1_0::EventPayload;
using ::android::hardware::sensors::V1_0::MetaDataEventType;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
@@ -133,20 +134,13 @@
}
std::vector<Event> Sensor::readEvents() {
- // For an accelerometer sensor type, default the z-direction
- // value to -9.8
- float zValue = (mSensorInfo.type == SensorType::ACCELEROMETER)
- ? -9.8 : 0.0;
-
std::vector<Event> events;
Event event;
event.sensorHandle = mSensorInfo.sensorHandle;
event.sensorType = mSensorInfo.type;
event.timestamp = ::android::elapsedRealtimeNano();
- event.u.vec3.x = 0;
- event.u.vec3.y = 0;
- event.u.vec3.z = zValue;
- event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
+ memset(&event.u, 0, sizeof(event.u));
+ readEventPayload(event.u);
events.push_back(event);
return events;
}
@@ -194,7 +188,7 @@
for (auto iter = events.begin(); iter != events.end(); ++iter) {
Event ev = *iter;
- if (ev.u.vec3 != mPreviousEvent.u.vec3 || !mPreviousEventSet) {
+ if (!mPreviousEventSet || memcmp(&mPreviousEvent.u, &ev.u, sizeof(ev.u)) != 0) {
outputEvents.push_back(ev);
mPreviousEvent = ev;
mPreviousEventSet = true;
@@ -221,6 +215,13 @@
mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION);
};
+void AccelSensor::readEventPayload(EventPayload& payload) {
+ payload.vec3.x = 0;
+ payload.vec3.y = 0;
+ payload.vec3.z = -9.8;
+ payload.vec3.status = SensorStatus::ACCURACY_HIGH;
+}
+
PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
: Sensor(callback) {
mSensorInfo.sensorHandle = sensorHandle;
@@ -240,6 +241,10 @@
mSensorInfo.flags = 0;
};
+void PressureSensor::readEventPayload(EventPayload& payload) {
+ payload.scalar = 1013.25f;
+}
+
MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
: Sensor(callback) {
mSensorInfo.sensorHandle = sensorHandle;
diff --git a/sensors/common/default/2.X/Sensor.h b/sensors/common/default/2.X/Sensor.h
index a792797..8ef11be 100644
--- a/sensors/common/default/2.X/Sensor.h
+++ b/sensors/common/default/2.X/Sensor.h
@@ -47,6 +47,7 @@
using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
using Result = ::android::hardware::sensors::V1_0::Result;
using Event = ::android::hardware::sensors::V2_1::Event;
+ using EventPayload = ::android::hardware::sensors::V1_0::EventPayload;
using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
using SensorType = ::android::hardware::sensors::V2_1::SensorType;
@@ -65,6 +66,7 @@
protected:
void run();
virtual std::vector<Event> readEvents();
+ virtual void readEventPayload(EventPayload&) {}
static void startThread(Sensor* sensor);
bool isWakeUpSensor();
@@ -101,6 +103,9 @@
class AccelSensor : public Sensor {
public:
AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
};
class GyroSensor : public Sensor {
@@ -116,6 +121,9 @@
class PressureSensor : public Sensor {
public:
PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
};
class MagnetometerSensor : public Sensor {
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4c54427..e242616 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -21,6 +21,7 @@
import ISimple;
import ITheirTypes.FloatArray;
+@SensitiveData // for test
interface IFoo {
enum SomeBaseEnum : uint8_t {
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 1765915..7b130ea 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -41,6 +41,9 @@
shared_libs: [
"libbinder",
],
+ data: [
+ ":tuner_frontend_input_ts",
+ ],
test_suites: [
"general-tests",
"vts",
diff --git a/tv/tuner/1.0/vts/functional/AndroidTest.xml b/tv/tuner/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3a2db27
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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 VtsHalTvTunerV1_0TargetTest.">
+ <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="VtsHalTvTunerV1_0TargetTest->/data/local/tmp/VtsHalTvTunerV1_0TargetTest" />
+ <option name="push" value="test.es->/data/local/tmp/test.es" />
+ <option name="push" value="segment000000.ts->/data/local/tmp/segment000000.ts" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalTvTunerV1_0TargetTest" />
+ </test>
+</configuration>
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index 4fa1746..6b2413c 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -165,8 +165,9 @@
Return<Result> Filter::releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) {
ALOGV("%s", __FUNCTION__);
- if ((avMemory.getNativeHandle()->numFds > 0) &&
+ if (mSharedAvMemHandle != NULL && avMemory != NULL &&
(mSharedAvMemHandle.getNativeHandle()->numFds > 0) &&
+ (avMemory.getNativeHandle()->numFds > 0) &&
(sameFile(avMemory.getNativeHandle()->data[0],
mSharedAvMemHandle.getNativeHandle()->data[0]))) {
freeSharedAvHandle();
diff --git a/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp
index 1fc36f1..73cd057 100644
--- a/tv/tuner/1.1/vts/functional/Android.bp
+++ b/tv/tuner/1.1/vts/functional/Android.bp
@@ -40,6 +40,9 @@
shared_libs: [
"libbinder",
],
+ data: [
+ ":tuner_frontend_input_es",
+ ],
test_suites: [
"general-tests",
"vts",
diff --git a/tv/tuner/1.1/vts/functional/AndroidTest.xml b/tv/tuner/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..28f95db
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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 VtsHalTvTunerV1_1TargetTest.">
+ <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="VtsHalTvTunerV1_1TargetTest->/data/local/tmp/VtsHalTvTunerV1_1TargetTest" />
+ <option name="push" value="test.es->/data/local/tmp/test.es" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalTvTunerV1_1TargetTest" />
+ </test>
+</configuration>
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index e872762..2dcb9a1 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -179,7 +179,7 @@
configSingleFilterInDemuxTest(filterArray[IP_IP0], frontendArray[DVBT]);
}
-TEST_P(TunerFilterHidlTest, ReonfigFilterToReceiveStartId) {
+TEST_P(TunerFilterHidlTest, ReconfigFilterToReceiveStartId) {
description("Recofigure and restart a filter to test start id.");
// TODO use parameterized tests
reconfigSingleFilterInDemuxTest(filterArray[TS_VIDEO0], filterArray[TS_VIDEO1],
diff --git a/tv/tuner/assets/Android.bp b/tv/tuner/assets/Android.bp
new file mode 100644
index 0000000..b58b645
--- /dev/null
+++ b/tv/tuner/assets/Android.bp
@@ -0,0 +1,17 @@
+genrule {
+ name: "tuner_frontend_input_es",
+ srcs: ["tuner_frontend_input.es"],
+ out: [
+ "test.es",
+ ],
+ cmd: "cp -f $(in) $(genDir)/test.es",
+}
+
+genrule {
+ name: "tuner_frontend_input_ts",
+ srcs: ["tuner_frontend_input.ts"],
+ out: [
+ "segment000000.ts",
+ ],
+ cmd: "cp -f $(in) $(genDir)/segment000000.ts",
+}
diff --git a/tv/tuner/assets/tuner_frontend_input.es b/tv/tuner/assets/tuner_frontend_input.es
new file mode 100644
index 0000000..b53c957
--- /dev/null
+++ b/tv/tuner/assets/tuner_frontend_input.es
Binary files differ
diff --git a/tv/tuner/assets/tuner_frontend_input.ts b/tv/tuner/assets/tuner_frontend_input.ts
new file mode 100644
index 0000000..8992c7b
--- /dev/null
+++ b/tv/tuner/assets/tuner_frontend_input.ts
Binary files differ
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 0b21248..cd7b603 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -206,7 +206,10 @@
* device/board configuration files ensuring that no ID is assigned to
* multiple clients. No client should use this API unless explicitly
* assigned an always-on source ID. Clients must develop their own way to
- * get IDs from vendor in a stable way.
+ * get IDs from vendor in a stable way. For instance, a client may expose
+ * a stable API (via HAL, sysprops, or xml overlays) to allow vendor to
+ * associate a hardware ID with a specific usecase. When that usecase is
+ * triggered, a client would use that hardware ID here.
*
* @param id The device-specific always-on source ID to enable.
* @param effect The type of haptic event to trigger.
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index dfd2524..adbb0cf 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -116,7 +116,7 @@
}
TEST_P(VibratorAidl, OnWithCallback) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
@@ -130,7 +130,7 @@
}
TEST_P(VibratorAidl, OnCallbackNotSupported) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) {
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
}
diff --git a/wifi/1.5/Android.bp b/wifi/1.5/Android.bp
index 5a62a3a..e2c38ce 100644
--- a/wifi/1.5/Android.bp
+++ b/wifi/1.5/Android.bp
@@ -7,6 +7,7 @@
"types.hal",
"IWifi.hal",
"IWifiChip.hal",
+ "IWifiApIface.hal",
"IWifiNanIface.hal",
"IWifiNanIfaceEventCallback.hal",
"IWifiStaIface.hal",
diff --git a/wifi/1.5/IWifiApIface.hal b/wifi/1.5/IWifiApIface.hal
new file mode 100644
index 0000000..9625a6b
--- /dev/null
+++ b/wifi/1.5/IWifiApIface.hal
@@ -0,0 +1,40 @@
+/*
+ * Copyright 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.wifi@1.5;
+
+import @1.4::IWifiApIface;
+import @1.0::MacAddress;
+import @1.0::WifiStatus;
+
+/**
+ * Represents a network interface in AP mode.
+ *
+ * This can be obtained through @1.0::IWifiChip.getApIface() and casting
+ * IWifiApIface up to 1.5.
+ */
+interface IWifiApIface extends @1.4::IWifiApIface {
+ /**
+ * Reset all of the AP interfaces MAC address to the factory MAC address.
+ *
+ * @return status WifiStatus of the operation
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ resetToFactoryMacAddress() generates (WifiStatus status);
+};
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index dcc9279..2702759 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -17,6 +17,7 @@
package android.hardware.wifi@1.5;
import @1.0::WifiStatus;
+import @1.5::IWifiApIface;
import @1.0::IWifiIface;
import @1.3::IWifiChip;
import @1.4::IWifiChip;
@@ -127,4 +128,43 @@
* |WifiStatusCode.ERROR_INVALID_ARGS|
*/
setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);
+
+
+ /**
+ * Create bridged IWifiApIface.
+ *
+ * Depending on the mode the chip is configured in, the interface creation
+ * may fail (code: |ERROR_NOT_AVAILABLE|) if we've already reached the maximum
+ * allowed (specified in |ChipIfaceCombination|) number of ifaces of the AP
+ * type.
+ *
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|
+ * @return iface HIDL interface object representing the iface if
+ * successful, null otherwise.
+ */
+ createBridgedApIface() generates (WifiStatus status, IWifiApIface iface);
+
+ /**
+ * Removes one of the instance on the AP Iface with the provided ifaceName and
+ * ifaceInstanceName.
+ *
+ * Use the API: removeApIface with brIfaceName in the V1_0::WifiChip.hal to remove bridge Iface.
+ *
+ * @param brIfaceName Name of the bridged AP iface.
+ * @param ifaceInstanceName Name of the instance. The empty instance is
+ * invalid.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+ * |WifiStatusCode.ERROR_INVALID_ARGS|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|
+ */
+ removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName)
+ generates (WifiStatus status);
};
diff --git a/wifi/1.5/default/service.cpp b/wifi/1.5/default/service.cpp
index 8539a37..23e2b47 100644
--- a/wifi/1.5/default/service.cpp
+++ b/wifi/1.5/default/service.cpp
@@ -17,6 +17,7 @@
#include <android-base/logging.h>
#include <hidl/HidlLazyUtils.h>
#include <hidl/HidlTransportSupport.h>
+#include <signal.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
@@ -45,6 +46,7 @@
#endif
int main(int /*argc*/, char** argv) {
+ signal(SIGPIPE, SIG_IGN);
android::base::InitLogging(
argv, android::base::LogdLogger(android::base::SYSTEM));
LOG(INFO) << "Wifi Hal is booting up...";
diff --git a/wifi/1.5/default/wifi_ap_iface.cpp b/wifi/1.5/default/wifi_ap_iface.cpp
index 04e382a..d98aa45 100644
--- a/wifi/1.5/default/wifi_ap_iface.cpp
+++ b/wifi/1.5/default/wifi_ap_iface.cpp
@@ -29,10 +29,11 @@
using hidl_return_util::validateAndCall;
WifiApIface::WifiApIface(
- const std::string& ifname,
+ const std::string& ifname, const std::vector<std::string>& instances,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
: ifname_(ifname),
+ instances_(instances),
legacy_hal_(legacy_hal),
iface_util_(iface_util),
is_valid_(true) {}
@@ -81,6 +82,14 @@
getFactoryMacAddress_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
&WifiApIface::getFactoryMacAddressInternal,
+ hidl_status_cb,
+ instances_.size() > 0 ? instances_[0] : ifname_);
+}
+
+Return<void> WifiApIface::resetToFactoryMacAddress(
+ resetToFactoryMacAddress_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::resetToFactoryMacAddressInternal,
hidl_status_cb);
}
@@ -94,8 +103,8 @@
WifiStatus WifiApIface::setCountryCodeInternal(
const std::array<int8_t, 2>& code) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->setCountryCode(ifname_, code);
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
+ instances_.size() > 0 ? instances_[0] : ifname_, code);
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -107,13 +116,30 @@
std::vector<uint32_t> valid_frequencies;
std::tie(legacy_status, valid_frequencies) =
legacy_hal_.lock()->getValidFrequenciesForBand(
- ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
+ instances_.size() > 0 ? instances_[0] : ifname_,
+ hidl_struct_util::convertHidlWifiBandToLegacy(band));
return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
}
WifiStatus WifiApIface::setMacAddressInternal(
const std::array<uint8_t, 6>& mac) {
- bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+ bool status;
+ // Support random MAC up to 2 interfaces
+ if (instances_.size() == 2) {
+ int rbyte = 1;
+ for (auto const& intf : instances_) {
+ std::array<uint8_t, 6> rmac = mac;
+ // reverse the bits to avoid clision
+ rmac[rbyte] = 0xff - rmac[rbyte];
+ status = iface_util_.lock()->setMacAddress(intf, rmac);
+ if (!status) {
+ LOG(INFO) << "Failed to set random mac address on " << intf;
+ }
+ rbyte++;
+ }
+ } else {
+ status = iface_util_.lock()->setMacAddress(ifname_, mac);
+ }
if (!status) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
@@ -121,15 +147,37 @@
}
std::pair<WifiStatus, std::array<uint8_t, 6>>
-WifiApIface::getFactoryMacAddressInternal() {
+WifiApIface::getFactoryMacAddressInternal(const std::string& ifaceName) {
std::array<uint8_t, 6> mac =
- iface_util_.lock()->getFactoryMacAddress(ifname_);
+ iface_util_.lock()->getFactoryMacAddress(ifaceName);
if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 &&
mac[4] == 0 && mac[5] == 0) {
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
}
return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
}
+
+WifiStatus WifiApIface::resetToFactoryMacAddressInternal() {
+ std::pair<WifiStatus, std::array<uint8_t, 6>> getMacResult;
+ if (instances_.size() == 2) {
+ for (auto const& intf : instances_) {
+ getMacResult = getFactoryMacAddressInternal(intf);
+ LOG(DEBUG) << "Reset MAC to factory MAC on " << intf;
+ if (getMacResult.first.code != WifiStatusCode::SUCCESS ||
+ !iface_util_.lock()->setMacAddress(intf, getMacResult.second)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ } else {
+ getMacResult = getFactoryMacAddressInternal(ifname_);
+ LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_;
+ if (getMacResult.first.code != WifiStatusCode::SUCCESS ||
+ !iface_util_.lock()->setMacAddress(ifname_, getMacResult.second)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ return createWifiStatus(WifiStatusCode::SUCCESS);
+}
} // namespace implementation
} // namespace V1_5
} // namespace wifi
diff --git a/wifi/1.5/default/wifi_ap_iface.h b/wifi/1.5/default/wifi_ap_iface.h
index 48b444a..02fb2d8 100644
--- a/wifi/1.5/default/wifi_ap_iface.h
+++ b/wifi/1.5/default/wifi_ap_iface.h
@@ -18,7 +18,7 @@
#define WIFI_AP_IFACE_H_
#include <android-base/macros.h>
-#include <android/hardware/wifi/1.4/IWifiApIface.h>
+#include <android/hardware/wifi/1.5/IWifiApIface.h>
#include "wifi_iface_util.h"
#include "wifi_legacy_hal.h"
@@ -33,9 +33,10 @@
/**
* HIDL interface object used to control a AP Iface instance.
*/
-class WifiApIface : public V1_4::IWifiApIface {
+class WifiApIface : public V1_5::IWifiApIface {
public:
WifiApIface(const std::string& ifname,
+ const std::vector<std::string>& instances,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
// Refer to |WifiChip::invalidate()|.
@@ -55,6 +56,8 @@
setMacAddress_cb hidl_status_cb) override;
Return<void> getFactoryMacAddress(
getFactoryMacAddress_cb hidl_status_cb) override;
+ Return<void> resetToFactoryMacAddress(
+ resetToFactoryMacAddress_cb hidl_status_cb) override;
private:
// Corresponding worker functions for the HIDL methods.
@@ -64,10 +67,12 @@
std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
getValidFrequenciesForBandInternal(V1_0::WifiBand band);
WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
- std::pair<WifiStatus, std::array<uint8_t, 6>>
- getFactoryMacAddressInternal();
+ std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal(
+ const std::string& ifaceName);
+ WifiStatus resetToFactoryMacAddressInternal();
std::string ifname_;
+ std::vector<std::string> instances_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
bool is_valid_;
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 1c238c8..dd39551 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
+#include <net/if.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@@ -44,6 +45,7 @@
constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
constexpr unsigned kMaxWlanIfaces = 5;
+constexpr char kApBridgeIfacePrefix[] = "ap_br_";
template <typename Iface>
void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -101,24 +103,36 @@
return "wlan" + std::to_string(idx);
}
-// Returns the dedicated iface name if one is defined.
-std::string getApIfaceName() {
+// Returns the dedicated iface name if defined.
+// Returns two ifaces in bridged mode.
+std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
+ std::vector<std::string> ifnames;
std::array<char, PROPERTY_VALUE_MAX> buffer;
+ buffer.fill(0);
if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) ==
0) {
- return {};
+ return ifnames;
}
- return buffer.data();
+ ifnames.push_back(buffer.data());
+ if (is_bridged) {
+ buffer.fill(0);
+ if (property_get("ro.vendor.wifi.sap.concurrent.interface",
+ buffer.data(), nullptr) == 0) {
+ return ifnames;
+ }
+ ifnames.push_back(buffer.data());
+ }
+ return ifnames;
}
-std::string getP2pIfaceName() {
+std::string getPredefinedP2pIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.direct.interface", buffer.data(), "p2p0");
return buffer.data();
}
// Returns the dedicated iface name if one is defined.
-std::string getNanIfaceName() {
+std::string getPredefinedNanIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
return {};
@@ -434,6 +448,13 @@
&WifiChip::createApIfaceInternal, hidl_status_cb);
}
+Return<void> WifiChip::createBridgedApIface(
+ createBridgedApIface_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createBridgedApIfaceInternal,
+ hidl_status_cb);
+}
+
Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getApIfaceNamesInternal, hidl_status_cb);
@@ -453,6 +474,15 @@
ifname);
}
+Return<void> WifiChip::removeIfaceInstanceFromBridgedApIface(
+ const hidl_string& ifname, const hidl_string& ifInstanceName,
+ removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
+ return validateAndCall(
+ this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal,
+ hidl_status_cb, ifname, ifInstanceName);
+}
+
Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createNanIfaceInternal, hidl_status_cb);
@@ -693,6 +723,7 @@
}
void WifiChip::invalidateAndRemoveAllIfaces() {
+ invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
invalidateAndClearAll(nan_ifaces_);
invalidateAndClearAll(p2p_ifaces_);
@@ -861,21 +892,28 @@
return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
}
-std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
- if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::string ifname = allocateApIfaceName();
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->createVirtualInterface(
- ifname,
- hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
+ legacy_hal::wifi_error legacy_status;
+ legacy_status = legacy_hal_.lock()->createVirtualInterface(
+ apVirtIf,
+ hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to add interface: " << ifname << " "
+ LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
<< legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
+ return createWifiStatusFromLegacyError(legacy_status);
}
- sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_, iface_util_);
+ return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+sp<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
+ std::vector<std::string> ap_instances;
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == ifname) {
+ ap_instances = it.second;
+ }
+ }
+ sp<WifiApIface> iface =
+ new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_);
ap_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
@@ -883,6 +921,61 @@
}
}
setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+ return iface;
+}
+
+std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
+WifiChip::createApIfaceInternal() {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
+ std::string ifname = allocateApIfaceName();
+ WifiStatus status = createVirtualApInterface(ifname);
+ if (status.code != WifiStatusCode::SUCCESS) {
+ return {status, {}};
+ }
+ sp<WifiApIface> iface = newWifiApIface(ifname);
+ return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
+WifiChip::createBridgedApIfaceInternal() {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
+ std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
+ if (ap_instances.size() < 2) {
+ LOG(ERROR) << "Fail to allocate two instances";
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
+ std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
+ for (int i = 0; i < 2; i++) {
+ WifiStatus status = createVirtualApInterface(ap_instances[i]);
+ if (status.code != WifiStatusCode::SUCCESS) {
+ if (i != 0) { // The failure happened when creating second virtual
+ // iface.
+ legacy_hal_.lock()->deleteVirtualInterface(
+ ap_instances.front()); // Remove the first virtual iface.
+ }
+ return {status, {}};
+ }
+ }
+ br_ifaces_ap_instances_[br_ifname] = ap_instances;
+ if (!iface_util_.lock()->createBridge(br_ifname)) {
+ LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
+ invalidateAndClearBridgedAp(br_ifname);
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
+ for (auto const& instance : ap_instances) {
+ // Bind ap instance interface to AP bridge
+ if (!iface_util_.lock()->addIfaceToBridge(br_ifname, instance)) {
+ LOG(ERROR) << "Failed add if to Bridge - if_name="
+ << instance.c_str();
+ invalidateAndClearBridgedAp(br_ifname);
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+ }
+ }
+ sp<WifiApIface> iface = newWifiApIface(br_ifname);
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
@@ -894,7 +987,7 @@
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
}
-std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
+std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::getApIfaceInternal(
const std::string& ifname) {
const auto iface = findUsingName(ap_ifaces_, ifname);
if (!iface.get()) {
@@ -913,12 +1006,8 @@
// nan/rtt objects over AP iface. But, there is no harm to do it
// here and not make that assumption all over the place.
invalidateAndRemoveDependencies(ifname);
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->deleteVirtualInterface(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to remove interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
- }
+ // Clear the bridge interface and the iface instance.
+ invalidateAndClearBridgedAp(ifname);
invalidateAndClear(ap_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@@ -929,13 +1018,49 @@
return createWifiStatus(WifiStatusCode::SUCCESS);
}
+WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
+ const std::string& ifname, const std::string& ifInstanceName) {
+ legacy_hal::wifi_error legacy_status;
+ const auto iface = findUsingName(ap_ifaces_, ifname);
+ if (!iface.get() || !ifInstanceName.empty()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ // Requires to remove one of the instance in bridge mode
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == ifname) {
+ for (auto const& iface : it.second) {
+ if (iface == ifInstanceName) {
+ if (!iface_util_.lock()->removeIfaceFromBridge(it.first,
+ iface)) {
+ LOG(ERROR) << "Failed to remove interface: " << iface
+ << " from " << ifname << ", error: "
+ << legacyErrorToString(legacy_status);
+ return createWifiStatus(
+ WifiStatusCode::ERROR_NOT_AVAILABLE);
+ }
+ legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to del interface: " << iface
+ << " " << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ }
+ }
+ break;
+ }
+ }
+ br_ifaces_ap_instances_.erase(ifInstanceName);
+ return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>>
WifiChip::createNanIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
bool is_dedicated_iface = true;
- std::string ifname = getNanIfaceName();
+ std::string ifname = getPredefinedNanIfaceName();
if (ifname.empty() || !iface_util_.lock()->ifNameToIndex(ifname)) {
// Use the first shared STA iface (wlan0) if a dedicated aware iface is
// not defined.
@@ -988,7 +1113,7 @@
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
- std::string ifname = getP2pIfaceName();
+ std::string ifname = getPredefinedP2pIfaceName();
sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
p2p_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -1607,7 +1732,7 @@
// ChipIfaceCombination.
// b) Check if the requested iface type can be added to the current mode.
bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) {
- // Check if we can support atleast 1 iface of type.
+ // Check if we can support at least 1 iface of type.
std::map<IfaceType, size_t> req_iface_combo;
req_iface_combo[requested_type] = 1;
return canCurrentModeSupportIfaceCombo(req_iface_combo);
@@ -1623,17 +1748,17 @@
}
bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
- // Check if we can support atleast 1 STA & 1 AP concurrently.
+ // Check if we can support at least 1 STA & 1 AP concurrently.
std::map<IfaceType, size_t> req_iface_combo;
req_iface_combo[IfaceType::AP] = 1;
req_iface_combo[IfaceType::STA] = 1;
return canCurrentModeSupportIfaceCombo(req_iface_combo);
}
-bool WifiChip::isDualApAllowedInCurrentMode() {
- // Check if we can support atleast 1 STA & 1 AP concurrently.
+bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
+ // Check if we can support at least 2 STA concurrently.
std::map<IfaceType, size_t> req_iface_combo;
- req_iface_combo[IfaceType::AP] = 2;
+ req_iface_combo[IfaceType::STA] = 2;
return canCurrentModeSupportIfaceCombo(req_iface_combo);
}
@@ -1653,6 +1778,7 @@
uint32_t start_idx) {
for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
const auto ifname = getWlanIfaceNameWithType(type, idx);
+ if (findUsingNameFromBridgedApInstances(ifname)) continue;
if (findUsingName(ap_ifaces_, ifname)) continue;
if (findUsingName(sta_ifaces_, ifname)) continue;
return ifname;
@@ -1662,19 +1788,46 @@
return {};
}
+uint32_t WifiChip::startIdxOfApIface() {
+ if (isDualStaConcurrencyAllowedInCurrentMode()) {
+ // When the HAL support dual STAs, AP should start with idx 2.
+ return 2;
+ } else if (isStaApConcurrencyAllowedInCurrentMode()) {
+ // When the HAL support STA + AP but it doesn't support dual STAs.
+ // AP should start with idx 1.
+ return 1;
+ }
+ // No concurrency support.
+ return 0;
+}
+
// AP iface names start with idx 1 for modes supporting
// concurrent STA and not dual AP, else start with idx 0.
std::string WifiChip::allocateApIfaceName() {
// Check if we have a dedicated iface for AP.
- std::string ifname = getApIfaceName();
- if (!ifname.empty()) {
- return ifname;
+ std::vector<std::string> ifnames = getPredefinedApIfaceNames(false);
+ if (!ifnames.empty()) {
+ return ifnames[0];
}
- return allocateApOrStaIfaceName(IfaceType::AP,
- (isStaApConcurrencyAllowedInCurrentMode() &&
- !isDualApAllowedInCurrentMode())
- ? 1
- : 0);
+ return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+}
+
+std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
+ // Check if we have a dedicated iface for AP.
+ std::vector<std::string> instances = getPredefinedApIfaceNames(true);
+ if (instances.size() == 2) {
+ return instances;
+ } else {
+ int num_ifaces_need_to_allocate = 2 - instances.size();
+ for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
+ std::string instance_name =
+ allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+ if (!instance_name.empty()) {
+ instances.push_back(instance_name);
+ }
+ }
+ }
+ return instances;
}
// STA iface names start with idx 0.
@@ -1727,6 +1880,48 @@
return getWlanIfaceName(idx);
}
+void WifiChip::invalidateAndClearBridgedApAll() {
+ for (auto const& it : br_ifaces_ap_instances_) {
+ for (auto const& iface : it.second) {
+ iface_util_.lock()->removeIfaceFromBridge(it.first, iface);
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ }
+ iface_util_.lock()->deleteBridge(it.first);
+ }
+ br_ifaces_ap_instances_.clear();
+}
+
+void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
+ if (br_name.empty()) return;
+ // delete managed interfaces
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == br_name) {
+ for (auto const& iface : it.second) {
+ iface_util_.lock()->removeIfaceFromBridge(br_name, iface);
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ }
+ iface_util_.lock()->deleteBridge(br_name);
+ br_ifaces_ap_instances_.erase(br_name);
+ break;
+ }
+ }
+ return;
+}
+
+bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == name) {
+ return true;
+ }
+ for (auto const& iface : it.second) {
+ if (iface == name) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
} // namespace implementation
} // namespace V1_5
} // namespace wifi
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 693d480..bff8d68 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -94,11 +94,16 @@
Return<void> requestFirmwareDebugDump(
requestFirmwareDebugDump_cb hidl_status_cb) override;
Return<void> createApIface(createApIface_cb hidl_status_cb) override;
+ Return<void> createBridgedApIface(
+ createBridgedApIface_cb hidl_status_cb) override;
Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
Return<void> getApIface(const hidl_string& ifname,
getApIface_cb hidl_status_cb) override;
Return<void> removeApIface(const hidl_string& ifname,
removeApIface_cb hidl_status_cb) override;
+ Return<void> removeIfaceInstanceFromBridgedApIface(
+ const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
+ removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
Return<void> getNanIface(const hidl_string& ifname,
@@ -192,11 +197,17 @@
requestDriverDebugDumpInternal();
std::pair<WifiStatus, std::vector<uint8_t>>
requestFirmwareDebugDumpInternal();
- std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal();
+ sp<WifiApIface> newWifiApIface(std::string& ifname);
+ WifiStatus createVirtualApInterface(const std::string& apVirtIf);
+ std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createApIfaceInternal();
+ std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
+ createBridgedApIfaceInternal();
std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
- std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
+ std::pair<WifiStatus, sp<V1_5::IWifiApIface>> getApIfaceInternal(
const std::string& ifname);
WifiStatus removeApIfaceInternal(const std::string& ifname);
+ WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(
+ const std::string& brIfaceName, const std::string& ifInstanceName);
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(
@@ -265,13 +276,18 @@
bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
bool isValidModeId(ChipModeId mode_id);
bool isStaApConcurrencyAllowedInCurrentMode();
- bool isDualApAllowedInCurrentMode();
+ bool isDualStaConcurrencyAllowedInCurrentMode();
+ uint32_t startIdxOfApIface();
std::string getFirstActiveWlanIfaceName();
std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
std::string allocateApIfaceName();
+ std::vector<std::string> allocateBridgedApInstanceNames();
std::string allocateStaIfaceName();
bool writeRingbufferFilesInternal();
std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
+ void invalidateAndClearBridgedApAll();
+ void invalidateAndClearBridgedAp(const std::string& br_name);
+ bool findUsingNameFromBridgedApInstances(const std::string& name);
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@@ -296,7 +312,7 @@
event_cb_handler_;
const std::function<void(const std::string&)> subsystemCallbackHandler_;
-
+ std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
DISALLOW_COPY_AND_ASSIGN(WifiChip);
};
diff --git a/wifi/1.5/default/wifi_sta_iface.cpp b/wifi/1.5/default/wifi_sta_iface.cpp
index f3dcfc5..82bfcf1 100644
--- a/wifi/1.5/default/wifi_sta_iface.cpp
+++ b/wifi/1.5/default/wifi_sta_iface.cpp
@@ -648,6 +648,10 @@
WifiStaIface::getFactoryMacAddressInternal() {
std::array<uint8_t, 6> mac =
iface_util_.lock()->getFactoryMacAddress(ifname_);
+ if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 &&
+ mac[4] == 0 && mac[5] == 0) {
+ return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
+ }
return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
}
diff --git a/wifi/1.5/vts/functional/Android.bp b/wifi/1.5/vts/functional/Android.bp
index eb595c9..2d8b412 100644
--- a/wifi/1.5/vts/functional/Android.bp
+++ b/wifi/1.5/vts/functional/Android.bp
@@ -60,3 +60,26 @@
"vts",
],
}
+
+// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
+cc_test {
+ name: "VtsHalWifiApV1_5TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "wifi_chip_hidl_ap_test.cpp",
+ ],
+ static_libs: [
+ "VtsHalWifiV1_0TargetTestUtil",
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
new file mode 100644
index 0000000..395d317
--- /dev/null
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+
+#undef NAN // NAN is defined in bionic/libc/include/math.h:38
+
+#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
+#include <android/hardware/wifi/1.5/IWifi.h>
+#include <android/hardware/wifi/1.5/IWifiApIface.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifiIface;
+using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
+using ::android::hardware::wifi::V1_0::WifiStatus;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_4::IWifiChipEventCallback;
+using ::android::hardware::wifi::V1_5::IWifiApIface;
+using ::android::hardware::wifi::V1_5::IWifiChip;
+
+/**
+ * Fixture for IWifiChip tests that are conditioned on SoftAP support.
+ */
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ // Make sure to start with a clean state
+ stopWifi(GetInstanceName());
+
+ wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
+ ASSERT_NE(nullptr, wifi_chip_.get());
+ }
+
+ virtual void TearDown() override { stopWifi(GetInstanceName()); }
+
+ protected:
+ // Helper function to configure the Chip in one of the supported modes.
+ // Most of the non-mode-configuration-related methods require chip
+ // to be first configured.
+ ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) {
+ ChipModeId mode_id;
+ EXPECT_EQ(expectSuccess,
+ configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
+ return mode_id;
+ }
+
+ WifiStatusCode createApIface(sp<IWifiApIface>* ap_iface) {
+ configureChipForIfaceType(IfaceType::AP, true);
+ const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createApIface);
+ *ap_iface = IWifiApIface::castFrom(status_and_iface.second);
+ return status_and_iface.first.code;
+ }
+
+ WifiStatusCode createBridgedApIface(sp<IWifiApIface>* ap_iface) {
+ configureChipForIfaceType(IfaceType::AP, true);
+ const auto& status_and_iface =
+ HIDL_INVOKE(wifi_chip_, createBridgedApIface);
+ *ap_iface = status_and_iface.second;
+ return status_and_iface.first.code;
+ }
+
+ sp<IWifiChip> wifi_chip_;
+
+ private:
+ std::string GetInstanceName() { return GetParam(); }
+};
+
+// TODO: b/173999527. Add test for bridged API.
+
+/*
+ * resetToFactoryMacAddress
+ */
+TEST_P(WifiChipHidlTest, resetToFactoryMacAddressTest) {
+ sp<IWifiApIface> wifi_ap_iface;
+ const auto& status_code = createApIface(&wifi_ap_iface);
+ if (status_code != WifiStatusCode::SUCCESS) {
+ EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status_code);
+ }
+ const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, WifiChipHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ ::android::hardware::wifi::V1_5::IWifi::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 1c3141e..b9c7b30 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -22,7 +22,7 @@
#include <VtsCoreUtil.h>
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIface.h>
-#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
#include "supplicant_hidl_call_util.h"
#include "supplicant_hidl_test_utils.h"
@@ -74,7 +74,7 @@
sta_iface_ = getSupplicantStaIface(supplicant_);
ASSERT_NE(sta_iface_.get(), nullptr);
- v1_1 = ::android::hardware::wifi::supplicant::V1_1::
+ v1_4 = ::android::hardware::wifi::supplicant::V1_4::
ISupplicantStaIface::castFrom(sta_iface_);
memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size());
@@ -82,7 +82,7 @@
protected:
bool isP2pOn_ = false;
- sp<::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface> v1_1 =
+ sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4 =
nullptr;
// ISupplicantStaIface object used for all tests in this fixture.
sp<ISupplicantStaIface> sta_iface_;
@@ -181,8 +181,9 @@
* RegisterCallback
*/
TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback) {
+ // This API is deprecated from v1.4 HAL.
SupplicantStatusCode expectedCode =
- (nullptr != v1_1) ? SupplicantStatusCode::FAILURE_UNKNOWN
+ (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN
: SupplicantStatusCode::SUCCESS;
sta_iface_->registerCallback(new IfaceCallback(),
[&](const SupplicantStatus& status) {
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index ee80628..d9ae3e0 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -48,6 +48,8 @@
"android.hardware.wifi.supplicant@1.0",
"android.hardware.wifi.supplicant@1.1",
"android.hardware.wifi.supplicant@1.2",
+ "android.hardware.wifi.supplicant@1.3",
+ "android.hardware.wifi.supplicant@1.4",
"android.hardware.wifi@1.0",
"android.hardware.wifi@1.1",
"libgmock",
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 418def2..7e6e3e4 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -20,7 +20,7 @@
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/1.1/IWifi.h>
#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
-#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -47,14 +47,14 @@
sta_iface_ = getSupplicantStaIface_1_1(supplicant_);
ASSERT_NE(sta_iface_.get(), nullptr);
- v1_2 = ::android::hardware::wifi::supplicant::V1_2::
+ v1_4 = ::android::hardware::wifi::supplicant::V1_4::
ISupplicantStaIface::castFrom(sta_iface_);
}
protected:
// ISupplicantStaIface object used for all tests in this fixture.
sp<ISupplicantStaIface> sta_iface_;
- sp<::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface> v1_2 =
+ sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4 =
nullptr;
};
@@ -139,8 +139,9 @@
* RegisterCallback_1_1
*/
TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_1) {
+ // This API is deprecated from v1.4 HAL.
SupplicantStatusCode expectedCode =
- (nullptr != v1_2) ? SupplicantStatusCode::FAILURE_UNKNOWN
+ (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN
: SupplicantStatusCode::SUCCESS;
sta_iface_->registerCallback_1_1(new IfaceCallback(),
[&](const SupplicantStatus& status) {
diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp
index c23585a..2592a2b 100644
--- a/wifi/supplicant/1.2/vts/functional/Android.bp
+++ b/wifi/supplicant/1.2/vts/functional/Android.bp
@@ -51,6 +51,7 @@
"android.hardware.wifi.supplicant@1.1",
"android.hardware.wifi.supplicant@1.2",
"android.hardware.wifi.supplicant@1.3",
+ "android.hardware.wifi.supplicant@1.4",
"android.hardware.wifi@1.0",
"android.hardware.wifi@1.1",
"libgmock",
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 7799390..7f81206 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -25,6 +25,7 @@
#include <android/hardware/wifi/supplicant/1.2/types.h>
#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaIface.h>
#include <android/hardware/wifi/supplicant/1.3/types.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
#include <hidl/GtestPrinter.h>
#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
@@ -63,6 +64,8 @@
v1_3 = ::android::hardware::wifi::supplicant::V1_3::
ISupplicantStaIface::castFrom(sta_iface_);
+ v1_4 = ::android::hardware::wifi::supplicant::V1_4::
+ ISupplicantStaIface::castFrom(sta_iface_);
}
enum DppCallbackType {
@@ -106,6 +109,7 @@
// ISupplicantStaIface object used for all tests in this fixture.
sp<ISupplicantStaIface> sta_iface_;
sp<::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface> v1_3;
+ sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4;
bool isDppSupported() {
uint32_t keyMgmtMask = 0;
@@ -266,8 +270,9 @@
* RegisterCallback_1_2
*/
TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_2) {
+ // This API is deprecated from v1.4 HAL.
SupplicantStatusCode expectedCode =
- (nullptr != v1_3) ? SupplicantStatusCode::FAILURE_UNKNOWN
+ (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN
: SupplicantStatusCode::SUCCESS;
sta_iface_->registerCallback_1_2(new IfaceCallback(),
[&](const SupplicantStatus& status) {
diff --git a/wifi/supplicant/1.4/ISupplicantStaIface.hal b/wifi/supplicant/1.4/ISupplicantStaIface.hal
index f9e4c9b..7441ba5 100644
--- a/wifi/supplicant/1.4/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaIface.hal
@@ -71,8 +71,7 @@
* |SupplicantStatusCode.FAILURE_UNKNOWN|,
* |SupplicantStatusCode.FAILURE_IFACE_INVALID|
*/
- initiateVenueUrlAnqpQuery(MacAddress macAddress)
- generates (SupplicantStatus status);
+ initiateVenueUrlAnqpQuery(MacAddress macAddress) generates (SupplicantStatus status);
/**
* Get wpa driver capabilities.
@@ -84,4 +83,55 @@
*/
getWpaDriverCapabilities_1_4() generates (SupplicantStatus status,
bitfield<WpaDriverCapabilitiesMask> driverCapabilitiesMask);
+
+ /**
+ * Generates DPP bootstrap information: Bootstrap ID, DPP URI and listen
+ * channel for responder mode.
+ *
+ * @param MacAddress MAC address of the interface for the DPP operation.
+ * @param deviceInfo Device specific information.
+ * As per DPP Specification V1.0 section 5.2,
+ * allowed Range of ASCII characters in deviceInfo - %x20-7E
+ * semicolon is not allowed.
+ * @param DppCurve Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ * @return status of operation and bootstrap info.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ generateDppBootstrapInfoForResponder(MacAddress macAddress, string deviceInfo, DppCurve curve)
+ generates (SupplicantStatus status, DppResponderBootstrapInfo bootstrapInfo);
+
+ /**
+ * Start DPP in Enrollee-Responder mode.
+ * Framework must first call |generateDppBootstrapInfoForResponder| to generate
+ * the bootstrapping information: Bootstrap ID, DPP URI and the listen channel.
+ * Then call this API with derived listen channel to start listening for
+ * authentication request from Peer initiator.
+ *
+ * @param listenChannel DPP listen channel.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ startDppEnrolleeResponder(uint32_t listenChannel) generates (SupplicantStatus status);
+
+ /**
+ * Stop DPP Responder operation - Remove the bootstrap code and stop listening.
+ *
+ * @param ownBootstrapId Local device's URI ID obtained through
+ * |generateDppBootstrapInfoForResponder| call.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ stopDppResponder(uint32_t ownBootstrapId) generates (SupplicantStatus status);
};
diff --git a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
index 852696d..efcebda 100644
--- a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
@@ -40,8 +40,12 @@
/**
* Baseline information as defined in HAL 1.0.
*/
- @1.0::ISupplicantStaIfaceCallback.AnqpData V1_0; /* Container for v1.0 of this struct */
- vec<uint8_t> venueUrl; /* Venue URL ANQP-element */
+ @1.0::ISupplicantStaIfaceCallback.AnqpData V1_0;
+
+ /*
+ * Container for v1.0 of this struct
+ */
+ vec<uint8_t> venueUrl;
};
/**
diff --git a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
index 80beedf..6bed5ab 100644
--- a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
@@ -17,7 +17,7 @@
package android.hardware.wifi.supplicant@1.4;
import @1.3::ISupplicantStaNetwork;
-import @1.4::ISupplicantStaNetworkCallback;
+import ISupplicantStaNetworkCallback;
/**
* Interface exposed by the supplicant for each station mode network
diff --git a/wifi/supplicant/1.4/types.hal b/wifi/supplicant/1.4/types.hal
index 18af8fe..aec61c4 100644
--- a/wifi/supplicant/1.4/types.hal
+++ b/wifi/supplicant/1.4/types.hal
@@ -18,6 +18,7 @@
import @1.0::SupplicantStatusCode;
import @1.3::ConnectionCapabilities;
+import @1.3::DppFailureCode;
import @1.3::WpaDriverCapabilitiesMask;
/**
@@ -40,6 +41,29 @@
};
/**
+ * DppFailureCode: Error codes for DPP (Easy Connect)
+ */
+enum DppFailureCode : @1.3::DppFailureCode {
+ /**
+ * Failure to generate a DPP URI.
+ */
+ URI_GENERATION,
+};
+
+/**
+ * DppCurve: Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ */
+enum DppCurve : uint32_t {
+ PRIME256V1,
+ SECP384R1,
+ SECP521R1,
+ BRAINPOOLP256R1,
+ BRAINPOOLP384R1,
+ BRAINPOOLP512R1,
+};
+
+/**
* Connection Capabilities supported by current network and device
*/
struct ConnectionCapabilities {
@@ -47,6 +71,7 @@
* Baseline information as defined in HAL 1.3.
*/
@1.3::ConnectionCapabilities V1_3;
+
/**
* detailed network mode for legacy network
*/
@@ -64,13 +89,14 @@
* Generic structure to return the status of any supplicant operation.
*/
struct SupplicantStatus {
- SupplicantStatusCode code;
- /**
- * A vendor specific error message to provide more information beyond the
- * status code.
- * This will be used for debbuging purposes only.
- */
- string debugMessage;
+ SupplicantStatusCode code;
+
+ /**
+ * A vendor specific error message to provide more information beyond the
+ * status code.
+ * This will be used for debbuging purposes only.
+ */
+ string debugMessage;
};
/**
@@ -78,7 +104,27 @@
*/
enum WpaDriverCapabilitiesMask : @1.3::WpaDriverCapabilitiesMask {
/**
- *
*/
SAE_PK = 1 << 2,
};
+
+/**
+ * DPP bootstrap info generated for responder mode operation
+ */
+struct DppResponderBootstrapInfo {
+ /**
+ * Generated bootstrap identifier
+ */
+ uint32_t bootstrapId;
+
+ /**
+ * The Wi-Fi channel that the DPP responder is listening on.
+ */
+ uint32_t listenChannel;
+
+ /**
+ * Bootstrapping URI per DPP specification, "section 5.2 Bootstrapping
+ * information", may contain listen channel, MAC address, public key, or other information.
+ */
+ string uri;
+};
diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
index c0b5a70..ccd469d 100644
--- a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -19,6 +19,7 @@
#include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
#include <android/hardware/wifi/supplicant/1.2/types.h>
#include <android/hardware/wifi/supplicant/1.3/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaNetwork.h>
#include <android/hardware/wifi/supplicant/1.3/types.h>
#include <android/hardware/wifi/supplicant/1.4/ISupplicant.h>
#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
@@ -45,7 +46,10 @@
using ::android::hardware::wifi::supplicant::V1_2::DppNetRole;
using ::android::hardware::wifi::supplicant::V1_2::DppProgressCode;
using ::android::hardware::wifi::supplicant::V1_3::DppSuccessCode;
+using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
using ::android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities;
+using ::android::hardware::wifi::supplicant::V1_4::DppCurve;
+using ::android::hardware::wifi::supplicant::V1_4::DppResponderBootstrapInfo;
using ::android::hardware::wifi::supplicant::V1_4::ISupplicant;
using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface;
using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIfaceCallback;
@@ -74,6 +78,24 @@
sp<ISupplicantStaIface> sta_iface_;
// MAC address to use for various tests.
std::array<uint8_t, 6> mac_addr_;
+
+ bool isDppSupported() {
+ uint32_t keyMgmtMask = 0;
+
+ // We need to first get the key management capabilities from the device.
+ // If DPP is not supported, we just pass the test.
+ sta_iface_->getKeyMgmtCapabilities_1_3(
+ [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ keyMgmtMask = keyMgmtMaskInternal;
+ });
+
+ if (!(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::DPP)) {
+ // DPP not supported
+ return false;
+ }
+ return true;
+ }
};
class IfaceCallback : public ISupplicantStaIfaceCallback {
@@ -255,6 +277,48 @@
});
}
+/*
+ * StartDppEnrolleeResponder
+ */
+TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeResponder) {
+ // We need to first get the key management capabilities from the device.
+ // If DPP is not supported, we just pass the test.
+ if (!isDppSupported()) {
+ // DPP not supported
+ return;
+ }
+
+ hidl_string deviceInfo = "DPP_Responder_Mode_VTS_Test";
+ uint32_t bootstrap_id = 0;
+ uint32_t listen_channel = 0;
+ uint8_t mac_address[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+
+ // Generate DPP bootstrap information
+ sta_iface_->generateDppBootstrapInfoForResponder(
+ mac_address, deviceInfo, DppCurve::PRIME256V1,
+ [&](const SupplicantStatusV1_4& status,
+ DppResponderBootstrapInfo bootstrapInfo) {
+ EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+ EXPECT_NE(-1, bootstrapInfo.bootstrapId);
+ EXPECT_NE(0, bootstrapInfo.bootstrapId);
+ bootstrap_id = bootstrapInfo.bootstrapId;
+ listen_channel = bootstrapInfo.listenChannel;
+ EXPECT_NE(0, bootstrapInfo.listenChannel);
+ });
+
+ // Start DPP as Enrollee-Responder.
+ sta_iface_->startDppEnrolleeResponder(
+ listen_channel, [&](const SupplicantStatusV1_4& status) {
+ EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+ });
+
+ // Stop DPP Enrollee-Responder mode, ie remove the URI and stop listen.
+ sta_iface_->stopDppResponder(
+ bootstrap_id, [&](const SupplicantStatusV1_4& status) {
+ EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+ });
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,