Merge "Add AM/FM/HD unit test for bcradio utils lib" into main
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 81c99f7..2b6207e 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -51,5 +51,10 @@
{
"name": "VtsHalNSTargetTest"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "VtsHalSpatializerTargetTest"
+ }
]
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index e14e9c0..07a85f8 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -74,6 +74,7 @@
boolean supportsVariableLatency();
int getAAudioMixerBurstCount();
int getAAudioHardwareBurstMinUsec();
+ void prepareToDisconnectExternalDevice(int portId);
const int DEFAULT_AAUDIO_MIXER_BURST_COUNT = 2;
const int DEFAULT_AAUDIO_HARDWARE_BURST_MIN_DURATION_US = 1000;
@VintfStability
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index e736c32..3c5f7f6 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -206,8 +206,10 @@
* after successful connection of an external device.
*
* Handling of a disconnect is done in a reverse order:
- * 1. Reset port configuration using the 'resetAudioPortConfig' method.
- * 2. Release the connected device port by calling the 'disconnectExternalDevice'
+ * 1. Notify the HAL module to prepare for device disconnection using
+ * 'prepareToDisconnectExternalDevice' method.
+ * 2. Reset port configuration using the 'resetAudioPortConfig' method.
+ * 3. Release the connected device port by calling the 'disconnectExternalDevice'
* method. This also removes the audio routes associated with this
* device port.
*
@@ -234,11 +236,15 @@
* instance previously instantiated using the 'connectExternalDevice'
* method.
*
- * The framework will call this method before closing streams and resetting
- * patches. This call can be used by the HAL module to prepare itself to
- * device disconnection. If the HAL module indicates an error after the first
- * call, the framework will call this method once again after closing associated
- * streams and patches.
+ * On AIDL HAL v1, the framework will call this method before closing streams
+ * and resetting patches. This call can be used by the HAL module to prepare
+ * itself to device disconnection. If the HAL module indicates an error after
+ * the first call, the framework will call this method once again after closing
+ * associated streams and patches.
+ *
+ * On AIDL HAL v2 and later, the framework will call 'prepareToDisconnectExternalDevice'
+ * method to notify the HAL module to prepare itself for device disconnection. The
+ * framework will only call this method after closing associated streams and patches.
*
* @throws EX_ILLEGAL_ARGUMENT In the following cases:
* - If the port can not be found by the ID.
@@ -912,4 +918,23 @@
* @throw EX_UNSUPPORTED_OPERATION If the module does not support aaudio MMAP.
*/
int getAAudioHardwareBurstMinUsec();
+
+ /**
+ * Notify the HAL module to prepare for disconnecting an external device.
+ *
+ * This method is used to inform the HAL module that 'disconnectExternalDevice' will be
+ * called soon. The HAL module can rely on this method to abort active data operations
+ * early. The 'portId' must be of a connected device Port instance previously instantiated
+ * using 'connectExternalDevice' method. 'disconnectExternalDevice' method will be called
+ * soon after this method with the same 'portId'.
+ *
+ * Note: This method is called after the external device is disconnected. The system does
+ * not try to predict the disconnection event.
+ *
+ * @param portId The ID of the audio port corresponding to the disconnected device
+ * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+ * - If the port can not be found by the ID.
+ * - If this is not a connected device port.
+ */
+ void prepareToDisconnectExternalDevice(int portId);
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 7cd0545..7e06c2c 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -204,6 +204,7 @@
vendor: true,
shared_libs: [
"libaudioaidlcommon",
+ "libaudioutils",
"libbase",
"libbinder_ndk",
"libcutils",
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index d63e353..2a8e58f 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -321,9 +321,9 @@
//
// Mix ports:
// * "r_submix output", maximum 10 opened streams, maximum 10 active streams
-// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
// * "r_submix input", maximum 10 opened streams, maximum 10 active streams
-// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//
// Routes:
// "r_submix output" -> "Remote Submix Out"
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 66c2169..94aa4dc 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -93,32 +93,6 @@
return std::all_of(profiles.begin(), profiles.end(), isDynamicProfile);
}
-// Note: does not assign an ID to the config.
-bool generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
- const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
- *config = {};
- config->portId = port.id;
- for (const auto& profile : port.profiles) {
- if (isDynamicProfile(profile)) continue;
- config->format = profile.format;
- config->channelMask = *profile.channelMasks.begin();
- config->sampleRate = Int{.value = *profile.sampleRates.begin()};
- config->flags = port.flags;
- config->ext = port.ext;
- return true;
- }
- if (allowDynamicConfig) {
- config->format = AudioFormatDescription{};
- config->channelMask = AudioChannelLayout{};
- config->sampleRate = Int{.value = 0};
- config->flags = port.flags;
- config->ext = port.ext;
- return true;
- }
- LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
- return false;
-}
-
bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& format,
AudioProfile* profile) {
if (auto profilesIt =
@@ -204,10 +178,11 @@
}
auto& configs = getConfig().portConfigs;
auto portConfigIt = findById<AudioPortConfig>(configs, in_portConfigId);
+ const int32_t nominalLatencyMs = getNominalLatencyMs(*portConfigIt);
// Since this is a private method, it is assumed that
// validity of the portConfigId has already been checked.
- const int32_t minimumStreamBufferSizeFrames = calculateBufferSizeFrames(
- getNominalLatencyMs(*portConfigIt), portConfigIt->sampleRate.value().value);
+ const int32_t minimumStreamBufferSizeFrames =
+ calculateBufferSizeFrames(nominalLatencyMs, portConfigIt->sampleRate.value().value);
if (in_bufferSizeFrames < minimumStreamBufferSizeFrames) {
LOG(ERROR) << __func__ << ": insufficient buffer size " << in_bufferSizeFrames
<< ", must be at least " << minimumStreamBufferSizeFrames;
@@ -246,7 +221,7 @@
std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
portConfigIt->format.value(), portConfigIt->channelMask.value(),
- portConfigIt->sampleRate.value().value, flags, getNominalLatencyMs(*portConfigIt),
+ portConfigIt->sampleRate.value().value, flags, nominalLatencyMs,
portConfigIt->ext.get<AudioPortExt::mix>().handle,
std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
asyncCallback, outEventCallback, mSoundDose.getInstance(), params);
@@ -332,6 +307,29 @@
return ndk::ScopedAStatus::ok();
}
+bool Module::generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
+ const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
+ for (const auto& profile : port.profiles) {
+ if (isDynamicProfile(profile)) continue;
+ config->format = profile.format;
+ config->channelMask = *profile.channelMasks.begin();
+ config->sampleRate = Int{.value = *profile.sampleRates.begin()};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ if (allowDynamicConfig) {
+ config->format = AudioFormatDescription{};
+ config->channelMask = AudioChannelLayout{};
+ config->sampleRate = Int{.value = 0};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
+ return false;
+}
+
void Module::populateConnectedProfiles() {
Configuration& config = getConfig();
for (const AudioPort& port : config.ports) {
@@ -621,10 +619,11 @@
std::vector<AudioRoute*> routesToMixPorts = getAudioRoutesForAudioPortImpl(templateId);
std::set<int32_t> routableMixPortIds = getRoutableAudioPortIds(templateId, &routesToMixPorts);
+ const int32_t nextPortId = getConfig().nextPortId++;
if (!mDebug.simulateDeviceConnections) {
// Even if the device port has static profiles, the HAL module might need to update
// them, or abort the connection process.
- RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
+ RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort, nextPortId));
} else if (hasDynamicProfilesOnly(connectedPort.profiles)) {
auto& connectedProfiles = getConfig().connectedProfiles;
if (auto connectedProfilesIt = connectedProfiles.find(templateId);
@@ -648,7 +647,7 @@
}
}
- connectedPort.id = getConfig().nextPortId++;
+ connectedPort.id = nextPortId;
auto [connectedPortsIt, _] =
mConnectedDevicePorts.insert(std::pair(connectedPort.id, std::set<int32_t>()));
LOG(DEBUG) << __func__ << ": template port " << templateId << " external device connected, "
@@ -762,6 +761,28 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::prepareToDisconnectExternalDevice(int32_t in_portId) {
+ auto& ports = getConfig().ports;
+ auto portIt = findById<AudioPort>(ports, in_portId);
+ if (portIt == ports.end()) {
+ LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (portIt->ext.getTag() != AudioPortExt::Tag::device) {
+ LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a device port";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ auto connectedPortsIt = mConnectedDevicePorts.find(in_portId);
+ if (connectedPortsIt == mConnectedDevicePorts.end()) {
+ LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a connected device port";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ onPrepareToDisconnectExternalDevice(*portIt);
+
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Module::getAudioPatches(std::vector<AudioPatch>* _aidl_return) {
*_aidl_return = getConfig().patches;
LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " patches";
@@ -1017,6 +1038,18 @@
ndk::ScopedAStatus Module::setAudioPortConfig(const AudioPortConfig& in_requested,
AudioPortConfig* out_suggested, bool* _aidl_return) {
+ auto generate = [this](const AudioPort& port, AudioPortConfig* config) {
+ return generateDefaultPortConfig(port, config);
+ };
+ return setAudioPortConfigImpl(in_requested, generate, out_suggested, _aidl_return);
+}
+
+ndk::ScopedAStatus Module::setAudioPortConfigImpl(
+ const AudioPortConfig& in_requested,
+ const std::function<bool(const ::aidl::android::media::audio::common::AudioPort& port,
+ ::aidl::android::media::audio::common::AudioPortConfig* config)>&
+ fillPortConfig,
+ AudioPortConfig* out_suggested, bool* applied) {
LOG(DEBUG) << __func__ << ": requested " << in_requested.toString();
auto& configs = getConfig().portConfigs;
auto existing = configs.end();
@@ -1045,7 +1078,8 @@
*out_suggested = *existing;
} else {
AudioPortConfig newConfig;
- if (generateDefaultPortConfig(*portIt, &newConfig)) {
+ newConfig.portId = portIt->id;
+ if (fillPortConfig(*portIt, &newConfig)) {
*out_suggested = newConfig;
} else {
LOG(ERROR) << __func__ << ": unable generate a default config for port " << portId;
@@ -1150,17 +1184,17 @@
if (existing == configs.end() && requestedIsValid && requestedIsFullySpecified) {
out_suggested->id = getConfig().nextPortId++;
configs.push_back(*out_suggested);
- *_aidl_return = true;
+ *applied = true;
LOG(DEBUG) << __func__ << ": created new port config " << out_suggested->toString();
} else if (existing != configs.end() && requestedIsValid) {
*existing = *out_suggested;
- *_aidl_return = true;
+ *applied = true;
LOG(DEBUG) << __func__ << ": updated port config " << out_suggested->toString();
} else {
LOG(DEBUG) << __func__ << ": not applied; existing config ? " << (existing != configs.end())
<< "; requested is valid? " << requestedIsValid << ", fully specified? "
<< requestedIsFullySpecified;
- *_aidl_return = false;
+ *applied = false;
}
return ndk::ScopedAStatus::ok();
}
@@ -1512,7 +1546,7 @@
return mIsMmapSupported.value();
}
-ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort) {
+ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
if (audioPort->ext.getTag() != AudioPortExt::device) {
LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -1541,6 +1575,11 @@
LOG(DEBUG) << __func__ << ": do nothing and return";
}
+void Module::onPrepareToDisconnectExternalDevice(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort __unused) {
+ LOG(DEBUG) << __func__ << ": do nothing and return";
+}
+
ndk::ScopedAStatus Module::onMasterMuteChanged(bool mute __unused) {
LOG(VERBOSE) << __func__ << ": do nothing and return ok";
return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/acousticEchoCanceler/Android.bp b/audio/aidl/default/acousticEchoCanceler/Android.bp
index bfb7212..35d4a56 100644
--- a/audio/aidl/default/acousticEchoCanceler/Android.bp
+++ b/audio/aidl/default/acousticEchoCanceler/Android.bp
@@ -27,8 +27,6 @@
name: "libaecsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"AcousticEchoCancelerSw.cpp",
diff --git a/audio/aidl/default/alsa/ModuleAlsa.cpp b/audio/aidl/default/alsa/ModuleAlsa.cpp
index 8512631..9a2cce7 100644
--- a/audio/aidl/default/alsa/ModuleAlsa.cpp
+++ b/audio/aidl/default/alsa/ModuleAlsa.cpp
@@ -34,7 +34,7 @@
namespace aidl::android::hardware::audio::core {
-ndk::ScopedAStatus ModuleAlsa::populateConnectedDevicePort(AudioPort* audioPort) {
+ndk::ScopedAStatus ModuleAlsa::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
auto deviceProfile = alsa::getDeviceProfile(*audioPort);
if (!deviceProfile.has_value()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 00de797..827ff80 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -47,6 +47,7 @@
<library name="visualizer" path="libvisualizeraidl.so"/>
<library name="volumesw" path="libvolumesw.so"/>
<library name="extensioneffect" path="libextensioneffect.so"/>
+ <library name="spatializersw" path="libspatializersw.so"/>
</libraries>
<!-- list of effects to load.
@@ -96,8 +97,9 @@
<libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
</effectProxy>
<effect name="extension_effect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002" type="fa81de0e-588b-11ed-9b6a-0242ac120002"/>
- <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
- <effect name="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
+ <effect name="acoustic_echo_canceler" library="pre_processing" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+ <effect name="noise_suppression" library="pre_processing" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
+ <effect name="spatializer" library="spatializersw" uuid="fa81a880-588b-11ed-9b6a-0242ac120002"/>
</effects>
<preprocess>
diff --git a/audio/aidl/default/automaticGainControlV1/Android.bp b/audio/aidl/default/automaticGainControlV1/Android.bp
index 4ae8e63..05c2c54 100644
--- a/audio/aidl/default/automaticGainControlV1/Android.bp
+++ b/audio/aidl/default/automaticGainControlV1/Android.bp
@@ -27,8 +27,6 @@
name: "libagc1sw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"AutomaticGainControlV1Sw.cpp",
diff --git a/audio/aidl/default/automaticGainControlV2/Android.bp b/audio/aidl/default/automaticGainControlV2/Android.bp
index 631cf58..dedc555 100644
--- a/audio/aidl/default/automaticGainControlV2/Android.bp
+++ b/audio/aidl/default/automaticGainControlV2/Android.bp
@@ -27,8 +27,6 @@
name: "libagc2sw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"AutomaticGainControlV2Sw.cpp",
diff --git a/audio/aidl/default/bassboost/Android.bp b/audio/aidl/default/bassboost/Android.bp
index 82b2f20..9f47770 100644
--- a/audio/aidl/default/bassboost/Android.bp
+++ b/audio/aidl/default/bassboost/Android.bp
@@ -27,8 +27,6 @@
name: "libbassboostsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"BassBoostSw.cpp",
diff --git a/audio/aidl/default/bluetooth/DevicePortProxy.cpp b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
index 1be0875..d772c20 100644
--- a/audio/aidl/default/bluetooth/DevicePortProxy.cpp
+++ b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AHAL_BluetoothPortProxy"
+#define LOG_TAG "AHAL_BluetoothAudioPort"
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
@@ -254,12 +254,7 @@
return (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
}
-bool BluetoothAudioPortAidl::getPreferredDataIntervalUs(size_t* interval_us) const {
- if (!interval_us) {
- LOG(ERROR) << __func__ << ": bad input arg";
- return false;
- }
-
+bool BluetoothAudioPortAidl::getPreferredDataIntervalUs(size_t& interval_us) const {
if (!inUse()) {
LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
return false;
@@ -272,16 +267,11 @@
return false;
}
- *interval_us = hal_audio_cfg.get<AudioConfiguration::pcmConfig>().dataIntervalUs;
+ interval_us = hal_audio_cfg.get<AudioConfiguration::pcmConfig>().dataIntervalUs;
return true;
}
-bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration* audio_cfg) const {
- if (!audio_cfg) {
- LOG(ERROR) << __func__ << ": bad input arg";
- return false;
- }
-
+bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration& audio_cfg) {
if (!inUse()) {
LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
return false;
@@ -293,15 +283,26 @@
LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
return false;
}
- *audio_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
+ audio_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
LOG(VERBOSE) << __func__ << debugMessage() << ", state*=" << getState() << ", PcmConfig=["
- << audio_cfg->toString() << "]";
- if (audio_cfg->channelMode == ChannelMode::UNKNOWN) {
+ << audio_cfg.toString() << "]";
+ if (audio_cfg.channelMode == ChannelMode::UNKNOWN) {
return false;
}
return true;
}
+bool BluetoothAudioPortAidlOut::loadAudioConfig(PcmConfiguration& audio_cfg) {
+ if (!BluetoothAudioPortAidl::loadAudioConfig(audio_cfg)) return false;
+ // WAR to support Mono / 16 bits per sample as the Bluetooth stack requires
+ if (audio_cfg.channelMode == ChannelMode::MONO && audio_cfg.bitsPerSample == 16) {
+ mIsStereoToMono = true;
+ audio_cfg.channelMode = ChannelMode::STEREO;
+ LOG(INFO) << __func__ << ": force channels = to be AUDIO_CHANNEL_OUT_STEREO";
+ }
+ return true;
+}
+
bool BluetoothAudioPortAidl::standby() {
if (!inUse()) {
LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
@@ -435,7 +436,7 @@
retval = condWaitState(BluetoothStreamState::SUSPENDING);
} else {
LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
- << " Hal fails";
+ << " failure to suspend stream";
}
}
}
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
index 8a1cbbf..9084b30 100644
--- a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -24,13 +24,25 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::bluetooth::audio::ChannelMode;
+using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioConfigBase;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::media::audio::common::PcmType;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
+using android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
using android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
// TODO(b/312265159) bluetooth audio should be in its own process
@@ -39,6 +51,35 @@
namespace aidl::android::hardware::audio::core {
+namespace {
+
+PcmType pcmTypeFromBitsPerSample(int8_t bitsPerSample) {
+ if (bitsPerSample == 8)
+ return PcmType::UINT_8_BIT;
+ else if (bitsPerSample == 16)
+ return PcmType::INT_16_BIT;
+ else if (bitsPerSample == 24)
+ return PcmType::INT_24_BIT;
+ else if (bitsPerSample == 32)
+ return PcmType::INT_32_BIT;
+ ALOGE("Unsupported bitsPerSample: %d", bitsPerSample);
+ return PcmType::DEFAULT;
+}
+
+AudioChannelLayout channelLayoutFromChannelMode(ChannelMode mode) {
+ if (mode == ChannelMode::MONO) {
+ return AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_MONO);
+ } else if (mode == ChannelMode::STEREO || mode == ChannelMode::DUALMONO) {
+ return AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO);
+ }
+ ALOGE("Unsupported channel mode: %s", toString(mode).c_str());
+ return AudioChannelLayout{};
+}
+
+} // namespace
+
ModuleBluetooth::ModuleBluetooth(std::unique_ptr<Module::Configuration>&& config)
: Module(Type::BLUETOOTH, std::move(config)) {
// TODO(b/312265159) bluetooth audio should be in its own process
@@ -95,66 +136,130 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus ModuleBluetooth::setAudioPortConfig(const AudioPortConfig& in_requested,
+ AudioPortConfig* out_suggested,
+ bool* _aidl_return) {
+ auto fillConfig = [this](const AudioPort& port, AudioPortConfig* config) {
+ if (port.ext.getTag() == AudioPortExt::device) {
+ CachedProxy proxy;
+ auto status = findOrCreateProxy(port, proxy);
+ if (status.isOk()) {
+ const auto& pcmConfig = proxy.pcmConfig;
+ LOG(DEBUG) << "setAudioPortConfig: suggesting port config from "
+ << pcmConfig.toString();
+ const auto pcmType = pcmTypeFromBitsPerSample(pcmConfig.bitsPerSample);
+ const auto channelMask = channelLayoutFromChannelMode(pcmConfig.channelMode);
+ if (pcmType != PcmType::DEFAULT && channelMask != AudioChannelLayout{}) {
+ config->format =
+ AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
+ config->channelMask = channelMask;
+ config->sampleRate = Int{.value = pcmConfig.sampleRateHz};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ }
+ }
+ return generateDefaultPortConfig(port, config);
+ };
+ return Module::setAudioPortConfigImpl(in_requested, fillConfig, out_suggested, _aidl_return);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::checkAudioPatchEndpointsMatch(
+ const std::vector<AudioPortConfig*>& sources, const std::vector<AudioPortConfig*>& sinks) {
+ // Both sources and sinks must be non-empty, this is guaranteed by 'setAudioPatch'.
+ const bool isInput = sources[0]->ext.getTag() == AudioPortExt::device;
+ const int32_t devicePortId = isInput ? sources[0]->portId : sinks[0]->portId;
+ const auto proxyIt = mProxies.find(devicePortId);
+ if (proxyIt == mProxies.end()) return ndk::ScopedAStatus::ok();
+ const auto& pcmConfig = proxyIt->second.pcmConfig;
+ const AudioPortConfig* mixPortConfig = isInput ? sinks[0] : sources[0];
+ if (!StreamBluetooth::checkConfigParams(
+ pcmConfig, AudioConfigBase{.sampleRate = mixPortConfig->sampleRate->value,
+ .channelMask = *(mixPortConfig->channelMask),
+ .format = *(mixPortConfig->format)})) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ if (int32_t handle = mixPortConfig->ext.get<AudioPortExt::mix>().handle; handle > 0) {
+ mConnections.insert(std::pair(handle, devicePortId));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+void ModuleBluetooth::onExternalDeviceConnectionChanged(const AudioPort& audioPort,
+ bool connected) {
+ if (!connected) mProxies.erase(audioPort.id);
+}
+
ndk::ScopedAStatus ModuleBluetooth::createInputStream(
StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+ CachedProxy proxy;
+ RETURN_STATUS_IF_ERROR(fetchAndCheckProxy(context, proxy));
return createStreamInstance<StreamInBluetooth>(result, std::move(context), sinkMetadata,
- microphones, getBtProfileManagerHandles());
+ microphones, getBtProfileManagerHandles(),
+ proxy.ptr, proxy.pcmConfig);
}
ndk::ScopedAStatus ModuleBluetooth::createOutputStream(
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+ CachedProxy proxy;
+ RETURN_STATUS_IF_ERROR(fetchAndCheckProxy(context, proxy));
return createStreamInstance<StreamOutBluetooth>(result, std::move(context), sourceMetadata,
- offloadInfo, getBtProfileManagerHandles());
+ offloadInfo, getBtProfileManagerHandles(),
+ proxy.ptr, proxy.pcmConfig);
}
-ndk::ScopedAStatus ModuleBluetooth::populateConnectedDevicePort(AudioPort* audioPort) {
+ndk::ScopedAStatus ModuleBluetooth::populateConnectedDevicePort(AudioPort* audioPort,
+ int32_t nextPortId) {
if (audioPort->ext.getTag() != AudioPortExt::device) {
LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+ if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::IsAidlAvailable()) {
+ LOG(ERROR) << __func__ << ": IBluetoothAudioProviderFactory AIDL service not available";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
const auto& devicePort = audioPort->ext.get<AudioPortExt::device>();
const auto& description = devicePort.device.type;
- // Since the configuration of the BT module is static, there is nothing to populate here.
- // However, this method must return an error when the device can not be connected,
- // this is determined by the status of BT profiles.
+ // This method must return an error when the device can not be connected.
if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP) {
bool isA2dpEnabled = false;
if (!!mBluetoothA2dp) {
RETURN_STATUS_IF_ERROR((*mBluetoothA2dp).isEnabled(&isA2dpEnabled));
}
LOG(DEBUG) << __func__ << ": isA2dpEnabled: " << isA2dpEnabled;
- return isA2dpEnabled ? ndk::ScopedAStatus::ok()
- : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ if (!isA2dpEnabled) return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
} else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE) {
bool isLeEnabled = false;
if (!!mBluetoothLe) {
RETURN_STATUS_IF_ERROR((*mBluetoothLe).isEnabled(&isLeEnabled));
}
LOG(DEBUG) << __func__ << ": isLeEnabled: " << isLeEnabled;
- return isLeEnabled ? ndk::ScopedAStatus::ok()
- : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ if (!isLeEnabled) return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
} else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
description.type == AudioDeviceType::OUT_HEARING_AID) {
- // Hearing aids can use a number of profiles, thus the only way to check
- // connectivity is to try to talk to the BT HAL.
- if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::
- IsAidlAvailable()) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- std::shared_ptr<BluetoothAudioPortAidl> proxy = std::shared_ptr<BluetoothAudioPortAidl>(
- std::make_shared<BluetoothAudioPortAidlOut>());
- if (proxy->registerPort(description)) {
- LOG(DEBUG) << __func__ << ": registered hearing aid port";
- proxy->unregisterPort();
- return ndk::ScopedAStatus::ok();
- }
- LOG(DEBUG) << __func__ << ": failed to register hearing aid port";
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ // Hearing aids can use a number of profiles, no single switch exists.
+ } else {
+ LOG(ERROR) << __func__ << ": unsupported device type: " << audioPort->toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- LOG(ERROR) << __func__ << ": unsupported device type: " << audioPort->toString();
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ CachedProxy proxy;
+ RETURN_STATUS_IF_ERROR(createProxy(*audioPort, nextPortId, proxy));
+ // Since the device is already connected and configured by the BT stack, provide
+ // the current configuration instead of all possible profiles.
+ const auto& pcmConfig = proxy.pcmConfig;
+ audioPort->profiles.clear();
+ audioPort->profiles.push_back(
+ AudioProfile{.format = AudioFormatDescription{.type = AudioFormatType::PCM,
+ .pcm = pcmTypeFromBitsPerSample(
+ pcmConfig.bitsPerSample)},
+ .channelMasks = std::vector<AudioChannelLayout>(
+ {channelLayoutFromChannelMode(pcmConfig.channelMode)}),
+ .sampleRates = std::vector<int>({pcmConfig.sampleRateHz})});
+ LOG(DEBUG) << __func__ << ": " << audioPort->toString();
+ return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
@@ -167,4 +272,77 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+int32_t ModuleBluetooth::getNominalLatencyMs(const AudioPortConfig& portConfig) {
+ const auto connectionsIt = mConnections.find(portConfig.ext.get<AudioPortExt::mix>().handle);
+ if (connectionsIt != mConnections.end()) {
+ const auto proxyIt = mProxies.find(connectionsIt->second);
+ if (proxyIt != mProxies.end()) {
+ auto proxy = proxyIt->second.ptr;
+ size_t dataIntervalUs = 0;
+ if (!proxy->getPreferredDataIntervalUs(dataIntervalUs)) {
+ LOG(WARNING) << __func__ << ": could not fetch preferred data interval";
+ }
+ const bool isInput = portConfig.flags->getTag() == AudioIoFlags::input;
+ return isInput ? StreamInBluetooth::getNominalLatencyMs(dataIntervalUs)
+ : StreamOutBluetooth::getNominalLatencyMs(dataIntervalUs);
+ }
+ }
+ LOG(ERROR) << __func__ << ": no connection or proxy found for " << portConfig.toString();
+ return Module::getNominalLatencyMs(portConfig);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::createProxy(const AudioPort& audioPort, int32_t instancePortId,
+ CachedProxy& proxy) {
+ const bool isInput = audioPort.flags.getTag() == AudioIoFlags::input;
+ proxy.ptr = isInput ? std::shared_ptr<BluetoothAudioPortAidl>(
+ std::make_shared<BluetoothAudioPortAidlIn>())
+ : std::shared_ptr<BluetoothAudioPortAidl>(
+ std::make_shared<BluetoothAudioPortAidlOut>());
+ const auto& devicePort = audioPort.ext.get<AudioPortExt::device>();
+ if (const auto device = devicePort.device.type; !proxy.ptr->registerPort(device)) {
+ LOG(ERROR) << __func__ << ": failed to register BT port for " << device.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (!proxy.ptr->loadAudioConfig(proxy.pcmConfig)) {
+ LOG(ERROR) << __func__ << ": state=" << proxy.ptr->getState()
+ << ", failed to load audio config";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ mProxies.insert(std::pair(instancePortId, proxy));
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleBluetooth::fetchAndCheckProxy(const StreamContext& context,
+ CachedProxy& proxy) {
+ const auto connectionsIt = mConnections.find(context.getMixPortHandle());
+ if (connectionsIt != mConnections.end()) {
+ const auto proxyIt = mProxies.find(connectionsIt->second);
+ if (proxyIt != mProxies.end()) {
+ proxy = proxyIt->second;
+ mProxies.erase(proxyIt);
+ }
+ mConnections.erase(connectionsIt);
+ }
+ if (proxy.ptr != nullptr) {
+ if (!StreamBluetooth::checkConfigParams(
+ proxy.pcmConfig, AudioConfigBase{.sampleRate = context.getSampleRate(),
+ .channelMask = context.getChannelLayout(),
+ .format = context.getFormat()})) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+ // Not having a proxy is OK, it may happen in VTS tests when streams are opened on unconnected
+ // mix ports.
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleBluetooth::findOrCreateProxy(const AudioPort& audioPort,
+ CachedProxy& proxy) {
+ if (auto proxyIt = mProxies.find(audioPort.id); proxyIt != mProxies.end()) {
+ proxy = proxyIt->second;
+ return ndk::ScopedAStatus::ok();
+ }
+ return createProxy(audioPort, audioPort.id, proxy);
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
index 0cee7f4..a73af1b 100644
--- a/audio/aidl/default/bluetooth/StreamBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#define LOG_TAG "AHAL_StreamBluetooth"
+#include <algorithm>
+#define LOG_TAG "AHAL_StreamBluetooth"
#include <Utils.h>
#include <android-base/logging.h>
#include <audio_utils/clock.h>
@@ -31,6 +32,7 @@
using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using aidl::android::hardware::bluetooth::audio::PresentationPosition;
using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioConfigBase;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioFormatDescription;
@@ -48,51 +50,33 @@
constexpr int kBluetoothDefaultInputBufferMs = 20;
constexpr int kBluetoothDefaultOutputBufferMs = 10;
// constexpr int kBluetoothSpatializerOutputBufferMs = 10;
+constexpr int kBluetoothDefaultRemoteDelayMs = 200;
-// pcm configuration params are not really used by the module
StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
- ModuleBluetooth::BtProfileHandles&& btHandles)
+ ModuleBluetooth::BtProfileHandles&& btHandles,
+ const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
+ const PcmConfiguration& pcmConfig)
: StreamCommonImpl(context, metadata),
- mSampleRate(getContext().getSampleRate()),
- mChannelLayout(getContext().getChannelLayout()),
- mFormat(getContext().getFormat()),
mFrameSizeBytes(getContext().getFrameSize()),
mIsInput(isInput(metadata)),
mBluetoothA2dp(std::move(std::get<ModuleBluetooth::BtInterface::BTA2DP>(btHandles))),
- mBluetoothLe(std::move(std::get<ModuleBluetooth::BtInterface::BTLE>(btHandles))) {
- mPreferredDataIntervalUs =
- (mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs) * 1000;
- mPreferredFrameCount = frameCountFromDurationUs(mPreferredDataIntervalUs, mSampleRate);
- mIsInitialized = false;
- mIsReadyToClose = false;
-}
+ mBluetoothLe(std::move(std::get<ModuleBluetooth::BtInterface::BTLE>(btHandles))),
+ mPreferredDataIntervalUs(pcmConfig.dataIntervalUs != 0
+ ? pcmConfig.dataIntervalUs
+ : (mIsInput ? kBluetoothDefaultInputBufferMs
+ : kBluetoothDefaultOutputBufferMs) *
+ 1000),
+ mPreferredFrameCount(
+ frameCountFromDurationUs(mPreferredDataIntervalUs, pcmConfig.sampleRateHz)),
+ mBtDeviceProxy(btDeviceProxy) {}
::android::status_t StreamBluetooth::init() {
- return ::android::OK; // defering this till we get AudioDeviceDescription
-}
-
-const StreamCommonInterface::ConnectedDevices& StreamBluetooth::getConnectedDevices() const {
std::lock_guard guard(mLock);
- return StreamCommonImpl::getConnectedDevices();
-}
-
-ndk::ScopedAStatus StreamBluetooth::setConnectedDevices(
- const std::vector<AudioDevice>& connectedDevices) {
- if (mIsInput && connectedDevices.size() > 1) {
- LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
- << ") for input stream";
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ if (mBtDeviceProxy == nullptr) {
+ // This is a normal situation in VTS tests.
+ LOG(INFO) << __func__ << ": no BT HAL proxy, stream is non-functional";
}
- for (const auto& connectedDevice : connectedDevices) {
- if (connectedDevice.address.getTag() != AudioDeviceAddress::mac) {
- LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- }
- }
- std::lock_guard guard(mLock);
- RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
- mIsInitialized = false; // updated connected device list, need initialization
- return ndk::ScopedAStatus::ok();
+ return ::android::OK;
}
::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
@@ -112,167 +96,111 @@
::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
std::lock_guard guard(mLock);
- if (!mIsInitialized || mIsReadyToClose) {
- // 'setConnectedDevices' has been called or stream is ready to close, so no transfers
+ if (mBtDeviceProxy == nullptr || mBtDeviceProxy->getState() == BluetoothStreamState::DISABLED) {
*actualFrameCount = 0;
*latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
return ::android::OK;
}
*actualFrameCount = 0;
*latencyMs = 0;
- for (auto proxy : mBtDeviceProxies) {
- if (!proxy->start()) {
- LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to start ";
- return -EIO;
- }
- const size_t fc = std::min(frameCount, mPreferredFrameCount);
- const size_t bytesToTransfer = fc * mFrameSizeBytes;
- if (mIsInput) {
- const size_t totalRead = proxy->readData(buffer, bytesToTransfer);
- *actualFrameCount = std::max(*actualFrameCount, totalRead / mFrameSizeBytes);
- } else {
- const size_t totalWrite = proxy->writeData(buffer, bytesToTransfer);
- *actualFrameCount = std::max(*actualFrameCount, totalWrite / mFrameSizeBytes);
- }
- PresentationPosition presentation_position;
- if (!proxy->getPresentationPosition(presentation_position)) {
- LOG(ERROR) << __func__ << ": getPresentationPosition returned error ";
- return ::android::UNKNOWN_ERROR;
- }
- *latencyMs =
- std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
- NANOS_PER_MILLISECOND));
+ if (!mBtDeviceProxy->start()) {
+ LOG(ERROR) << __func__ << ": state= " << mBtDeviceProxy->getState() << " failed to start";
+ return -EIO;
}
+ const size_t fc = std::min(frameCount, mPreferredFrameCount);
+ const size_t bytesToTransfer = fc * mFrameSizeBytes;
+ if (mIsInput) {
+ const size_t totalRead = mBtDeviceProxy->readData(buffer, bytesToTransfer);
+ *actualFrameCount = std::max(*actualFrameCount, totalRead / mFrameSizeBytes);
+ } else {
+ const size_t totalWrite = mBtDeviceProxy->writeData(buffer, bytesToTransfer);
+ *actualFrameCount = std::max(*actualFrameCount, totalWrite / mFrameSizeBytes);
+ }
+ PresentationPosition presentation_position;
+ if (!mBtDeviceProxy->getPresentationPosition(presentation_position)) {
+ presentation_position.remoteDeviceAudioDelayNanos =
+ kBluetoothDefaultRemoteDelayMs * NANOS_PER_MILLISECOND;
+ LOG(WARNING) << __func__ << ": getPresentationPosition failed, latency info is unavailable";
+ }
+ // TODO(b/317117580): incorporate logic from
+ // packages/modules/Bluetooth/system/audio_bluetooth_hw/stream_apis.cc
+ // out_calculate_feeding_delay_ms / in_calculate_starving_delay_ms
+ *latencyMs = std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
+ NANOS_PER_MILLISECOND));
return ::android::OK;
}
-::android::status_t StreamBluetooth::initialize() {
- if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::IsAidlAvailable()) {
- LOG(ERROR) << __func__ << ": IBluetoothAudioProviderFactory service not available";
- return ::android::UNKNOWN_ERROR;
- }
- if (StreamCommonImpl::getConnectedDevices().empty()) {
- LOG(ERROR) << __func__ << ", has no connected devices";
- return ::android::NO_INIT;
- }
- // unregister older proxies (if any)
- for (auto proxy : mBtDeviceProxies) {
- proxy->stop();
- proxy->unregisterPort();
- }
- mBtDeviceProxies.clear();
- for (auto it = StreamCommonImpl::getConnectedDevices().begin();
- it != StreamCommonImpl::getConnectedDevices().end(); ++it) {
- std::shared_ptr<BluetoothAudioPortAidl> proxy =
- mIsInput ? std::shared_ptr<BluetoothAudioPortAidl>(
- std::make_shared<BluetoothAudioPortAidlIn>())
- : std::shared_ptr<BluetoothAudioPortAidl>(
- std::make_shared<BluetoothAudioPortAidlOut>());
- if (proxy->registerPort(it->type)) {
- LOG(ERROR) << __func__ << ": cannot init HAL";
- return ::android::UNKNOWN_ERROR;
- }
- PcmConfiguration config;
- if (!proxy->loadAudioConfig(&config)) {
- LOG(ERROR) << __func__ << ": state=" << proxy->getState()
- << " failed to get audio config";
- return ::android::UNKNOWN_ERROR;
- }
- // TODO: Ensure minimum duration for spatialized output?
- // WAR to support Mono / 16 bits per sample as the Bluetooth stack required
- if (!mIsInput && config.channelMode == ChannelMode::MONO && config.bitsPerSample == 16) {
- proxy->forcePcmStereoToMono(true);
- config.channelMode = ChannelMode::STEREO;
- LOG(INFO) << __func__ << ": force channels = to be AUDIO_CHANNEL_OUT_STEREO";
- }
- if (!checkConfigParams(config)) {
- LOG(ERROR) << __func__ << " checkConfigParams failed";
- return ::android::UNKNOWN_ERROR;
- }
- mBtDeviceProxies.push_back(std::move(proxy));
- }
- mIsInitialized = true;
- return ::android::OK;
-}
-
-bool StreamBluetooth::checkConfigParams(
- ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config) {
- if ((int)mSampleRate != config.sampleRateHz) {
- LOG(ERROR) << __func__ << ": Sample Rate mismatch, stream val = " << mSampleRate
- << " hal val = " << config.sampleRateHz;
+// static
+bool StreamBluetooth::checkConfigParams(const PcmConfiguration& pcmConfig,
+ const AudioConfigBase& config) {
+ if ((int)config.sampleRate != pcmConfig.sampleRateHz) {
+ LOG(ERROR) << __func__ << ": sample rate mismatch, stream value=" << config.sampleRate
+ << ", BT HAL value=" << pcmConfig.sampleRateHz;
return false;
}
- auto channelCount = aidl::android::hardware::audio::common::getChannelCount(mChannelLayout);
- if ((config.channelMode == ChannelMode::MONO && channelCount != 1) ||
- (config.channelMode == ChannelMode::STEREO && channelCount != 2)) {
- LOG(ERROR) << __func__ << ": Channel count mismatch, stream val = " << channelCount
- << " hal val = " << toString(config.channelMode);
+ const auto channelCount =
+ aidl::android::hardware::audio::common::getChannelCount(config.channelMask);
+ if ((pcmConfig.channelMode == ChannelMode::MONO && channelCount != 1) ||
+ (pcmConfig.channelMode == ChannelMode::STEREO && channelCount != 2)) {
+ LOG(ERROR) << __func__ << ": Channel count mismatch, stream value=" << channelCount
+ << ", BT HAL value=" << toString(pcmConfig.channelMode);
return false;
}
- if (mFormat.type != AudioFormatType::PCM) {
- LOG(ERROR) << __func__ << ": unexpected format type "
- << aidl::android::media::audio::common::toString(mFormat.type);
+ if (config.format.type != AudioFormatType::PCM) {
+ LOG(ERROR) << __func__
+ << ": unexpected stream format type: " << toString(config.format.type);
return false;
}
- int8_t bps = aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(mFormat.pcm) * 8;
- if (bps != config.bitsPerSample) {
- LOG(ERROR) << __func__ << ": bits per sample mismatch, stream val = " << bps
- << " hal val = " << config.bitsPerSample;
+ const int8_t bitsPerSample =
+ aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(config.format.pcm) * 8;
+ if (bitsPerSample != pcmConfig.bitsPerSample) {
+ LOG(ERROR) << __func__ << ": bits per sample mismatch, stream value=" << bitsPerSample
+ << ", BT HAL value=" << pcmConfig.bitsPerSample;
return false;
}
- if (config.dataIntervalUs > 0) {
- mPreferredDataIntervalUs =
- std::min((int32_t)mPreferredDataIntervalUs, config.dataIntervalUs);
- mPreferredFrameCount = frameCountFromDurationUs(mPreferredDataIntervalUs, mSampleRate);
- }
return true;
}
ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
std::lock_guard guard(mLock);
- mIsReadyToClose = true;
+ if (mBtDeviceProxy != nullptr) {
+ if (mBtDeviceProxy->getState() != BluetoothStreamState::DISABLED) {
+ mBtDeviceProxy->stop();
+ }
+ }
return ndk::ScopedAStatus::ok();
}
::android::status_t StreamBluetooth::standby() {
std::lock_guard guard(mLock);
- if (!mIsInitialized) {
- if (auto status = initialize(); status != ::android::OK) return status;
- }
- for (auto proxy : mBtDeviceProxies) {
- if (!proxy->suspend()) {
- LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to stand by ";
- return -EIO;
- }
- }
+ if (mBtDeviceProxy != nullptr) mBtDeviceProxy->suspend();
return ::android::OK;
}
::android::status_t StreamBluetooth::start() {
std::lock_guard guard(mLock);
- if (!mIsInitialized) return initialize();
+ if (mBtDeviceProxy != nullptr) mBtDeviceProxy->start();
return ::android::OK;
}
void StreamBluetooth::shutdown() {
std::lock_guard guard(mLock);
- for (auto proxy : mBtDeviceProxies) {
- proxy->stop();
- proxy->unregisterPort();
+ if (mBtDeviceProxy != nullptr) {
+ mBtDeviceProxy->stop();
+ mBtDeviceProxy = nullptr;
}
- mBtDeviceProxies.clear();
}
ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
std::lock_guard guard(mLock);
- if (!mIsInitialized) return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ if (mBtDeviceProxy == nullptr) {
+ return ndk::ScopedAStatus::ok();
+ }
bool isOk = true;
if (isInput(metadata)) {
- isOk = mBtDeviceProxies[0]->updateSinkMetadata(std::get<SinkMetadata>(metadata));
+ isOk = mBtDeviceProxy->updateSinkMetadata(std::get<SinkMetadata>(metadata));
} else {
- for (auto proxy : mBtDeviceProxies) {
- if (!proxy->updateSourceMetadata(std::get<SourceMetadata>(metadata))) isOk = false;
- }
+ isOk = mBtDeviceProxy->updateSourceMetadata(std::get<SourceMetadata>(metadata));
}
return isOk ? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -280,7 +208,6 @@
ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
if (mIsInput) {
- LOG(WARNING) << __func__ << ": not handled";
return ndk::ScopedAStatus::ok();
}
auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
@@ -297,15 +224,10 @@
bool hasLeParam, enableLe;
auto btLe = mBluetoothLe.lock();
hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
- std::unique_lock lock(mLock);
- ::android::base::ScopedLockAssertion lock_assertion(mLock);
- if (!mIsInitialized) {
- LOG(WARNING) << __func__ << ": init not done";
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- for (auto proxy : mBtDeviceProxies) {
- if ((hasA2dpParam && proxy->isA2dp() && !applyParam(proxy, enableA2dp)) ||
- (hasLeParam && proxy->isLeAudio() && !applyParam(proxy, enableLe))) {
+ std::lock_guard guard(mLock);
+ if (mBtDeviceProxy != nullptr) {
+ if ((hasA2dpParam && mBtDeviceProxy->isA2dp() && !applyParam(mBtDeviceProxy, enableA2dp)) ||
+ (hasLeParam && mBtDeviceProxy->isLeAudio() && !applyParam(mBtDeviceProxy, enableLe))) {
LOG(DEBUG) << __func__ << ": applyParam failed";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
@@ -313,11 +235,20 @@
return ndk::ScopedAStatus::ok();
}
+// static
+int32_t StreamInBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
+ if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultInputBufferMs * 1000LL;
+ return dataIntervalUs / 1000LL;
+}
+
StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
- ModuleBluetooth::BtProfileHandles&& btProfileHandles)
+ ModuleBluetooth::BtProfileHandles&& btProfileHandles,
+ const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
+ const PcmConfiguration& pcmConfig)
: StreamIn(std::move(context), microphones),
- StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles)) {}
+ StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles), btDeviceProxy,
+ pcmConfig) {}
ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -325,11 +256,20 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+// static
+int32_t StreamOutBluetooth::getNominalLatencyMs(size_t dataIntervalUs) {
+ if (dataIntervalUs == 0) dataIntervalUs = kBluetoothDefaultOutputBufferMs * 1000LL;
+ return dataIntervalUs / 1000LL;
+}
+
StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo,
- ModuleBluetooth::BtProfileHandles&& btProfileHandles)
+ ModuleBluetooth::BtProfileHandles&& btProfileHandles,
+ const std::shared_ptr<BluetoothAudioPortAidl>& btDeviceProxy,
+ const PcmConfiguration& pcmConfig)
: StreamOut(std::move(context), offloadInfo),
- StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles)) {}
+ StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles), btDeviceProxy,
+ pcmConfig) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/downmix/Android.bp b/audio/aidl/default/downmix/Android.bp
index 6d15cdb..8657283 100644
--- a/audio/aidl/default/downmix/Android.bp
+++ b/audio/aidl/default/downmix/Android.bp
@@ -27,8 +27,6 @@
name: "libdownmixsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"DownmixSw.cpp",
diff --git a/audio/aidl/default/dynamicProcessing/Android.bp b/audio/aidl/default/dynamicProcessing/Android.bp
index 1c0312d..c0a648d 100644
--- a/audio/aidl/default/dynamicProcessing/Android.bp
+++ b/audio/aidl/default/dynamicProcessing/Android.bp
@@ -27,8 +27,6 @@
name: "libdynamicsprocessingsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"DynamicsProcessingSw.cpp",
diff --git a/audio/aidl/default/envReverb/Android.bp b/audio/aidl/default/envReverb/Android.bp
index dd4219a..2443c2a 100644
--- a/audio/aidl/default/envReverb/Android.bp
+++ b/audio/aidl/default/envReverb/Android.bp
@@ -27,8 +27,6 @@
name: "libenvreverbsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"EnvReverbSw.cpp",
diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
index 3610563..42708d1 100644
--- a/audio/aidl/default/equalizer/Android.bp
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -27,8 +27,6 @@
name: "libequalizersw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"EqualizerSw.cpp",
diff --git a/audio/aidl/default/extension/Android.bp b/audio/aidl/default/extension/Android.bp
index 4e5d352..5fee479 100644
--- a/audio/aidl/default/extension/Android.bp
+++ b/audio/aidl/default/extension/Android.bp
@@ -27,8 +27,6 @@
name: "libextensioneffect",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"ExtensionEffect.cpp",
diff --git a/audio/aidl/default/hapticGenerator/Android.bp b/audio/aidl/default/hapticGenerator/Android.bp
index 0df9a94..8fb9a3d 100644
--- a/audio/aidl/default/hapticGenerator/Android.bp
+++ b/audio/aidl/default/hapticGenerator/Android.bp
@@ -27,8 +27,6 @@
name: "libhapticgeneratorsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"HapticGeneratorSw.cpp",
diff --git a/audio/aidl/default/include/core-impl/DevicePortProxy.h b/audio/aidl/default/include/core-impl/DevicePortProxy.h
index 17a8cf3..ccb23bb 100644
--- a/audio/aidl/default/include/core-impl/DevicePortProxy.h
+++ b/audio/aidl/default/include/core-impl/DevicePortProxy.h
@@ -73,12 +73,7 @@
* Bluetooth stack
*/
virtual bool loadAudioConfig(
- ::aidl::android::hardware::bluetooth::audio::PcmConfiguration*) const = 0;
-
- /**
- * WAR to support Mono mode / 16 bits per sample
- */
- virtual void forcePcmStereoToMono(bool) = 0;
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration&) = 0;
/**
* When the Audio framework / HAL wants to change the stream state, it invokes
@@ -145,7 +140,7 @@
virtual bool isLeAudio() const = 0;
- virtual bool getPreferredDataIntervalUs(size_t*) const = 0;
+ virtual bool getPreferredDataIntervalUs(size_t&) const = 0;
virtual size_t writeData(const void*, size_t) const { return 0; }
@@ -162,10 +157,8 @@
void unregisterPort() override;
- bool loadAudioConfig(::aidl::android::hardware::bluetooth::audio::PcmConfiguration* audio_cfg)
- const override;
-
- void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; }
+ bool loadAudioConfig(
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& audio_cfg) override;
bool standby() override;
bool start() override;
@@ -193,7 +186,7 @@
bool isLeAudio() const override;
- bool getPreferredDataIntervalUs(size_t* interval_us) const override;
+ bool getPreferredDataIntervalUs(size_t& interval_us) const override;
protected:
uint16_t mCookie;
@@ -228,6 +221,9 @@
class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl {
public:
+ bool loadAudioConfig(
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& audio_cfg) override;
+
// The audio data path to the Bluetooth stack (Software encoding)
size_t writeData(const void* buffer, size_t bytes) const override;
};
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index caf43f1..ce71d70 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -16,6 +16,7 @@
#pragma once
+#include <functional>
#include <iostream>
#include <map>
#include <memory>
@@ -70,6 +71,7 @@
const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
+ ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t in_portId) override;
ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
ndk::ScopedAStatus getAudioPort(
int32_t in_portId,
@@ -187,7 +189,7 @@
// If the module is unable to populate the connected device port correctly, the returned error
// code must correspond to the errors of `IModule.connectedExternalDevice` method.
virtual ndk::ScopedAStatus populateConnectedDevicePort(
- ::aidl::android::media::audio::common::AudioPort* audioPort);
+ ::aidl::android::media::audio::common::AudioPort* audioPort, int32_t nextPortId);
// If the module finds that the patch endpoints configurations are not matched, the returned
// error code must correspond to the errors of `IModule.setAudioPatch` method.
virtual ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
@@ -195,6 +197,8 @@
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
virtual void onExternalDeviceConnectionChanged(
const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
+ virtual void onPrepareToDisconnectExternalDevice(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort);
virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();
@@ -207,6 +211,7 @@
const int32_t rawSizeFrames =
aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
sampleRateHz);
+ if (latencyMs >= 5) return rawSizeFrames;
int32_t powerOf2 = 1;
while (powerOf2 < rawSizeFrames) powerOf2 <<= 1;
return powerOf2;
@@ -224,12 +229,16 @@
std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+ // Note: does not assign an ID to the config.
+ bool generateDefaultPortConfig(const ::aidl::android::media::audio::common::AudioPort& port,
+ ::aidl::android::media::audio::common::AudioPortConfig* config);
std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
Configuration& getConfig();
const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
bool getMasterMute() const { return mMasterMute; }
bool getMasterVolume() const { return mMasterVolume; }
bool getMicMute() const { return mMicMute; }
+ const ModuleDebug& getModuleDebug() const { return mDebug; }
const Patches& getPatches() const { return mPatches; }
std::set<int32_t> getRoutableAudioPortIds(int32_t portId,
std::vector<AudioRoute*>* routes = nullptr);
@@ -240,6 +249,12 @@
template <typename C>
std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
void registerPatch(const AudioPatch& patch);
+ ndk::ScopedAStatus setAudioPortConfigImpl(
+ const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
+ const std::function<bool(const ::aidl::android::media::audio::common::AudioPort& port,
+ ::aidl::android::media::audio::common::AudioPortConfig*
+ config)>& fillPortConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* out_suggested, bool* applied);
ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
const AudioPatch& newPatch);
};
diff --git a/audio/aidl/default/include/core-impl/ModuleAlsa.h b/audio/aidl/default/include/core-impl/ModuleAlsa.h
index 2774fe5..3392b41 100644
--- a/audio/aidl/default/include/core-impl/ModuleAlsa.h
+++ b/audio/aidl/default/include/core-impl/ModuleAlsa.h
@@ -33,7 +33,8 @@
protected:
// Extension methods of 'Module'.
ndk::ScopedAStatus populateConnectedDevicePort(
- ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+ ::aidl::android::media::audio::common::AudioPort* audioPort,
+ int32_t nextPortId) override;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
index 631b088..9451411 100644
--- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -16,7 +16,10 @@
#pragma once
+#include <map>
+
#include "core-impl/Bluetooth.h"
+#include "core-impl/DevicePortProxy.h"
#include "core-impl/Module.h"
namespace aidl::android::hardware::audio::core {
@@ -31,6 +34,11 @@
ModuleBluetooth(std::unique_ptr<Configuration>&& config);
private:
+ struct CachedProxy {
+ std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl> ptr;
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration pcmConfig;
+ };
+
ChildInterface<BluetoothA2dp>& getBtA2dp();
ChildInterface<BluetoothLe>& getBtLe();
BtProfileHandles getBtProfileManagerHandles();
@@ -40,6 +48,17 @@
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
+ ndk::ScopedAStatus setAudioPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
+ ::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
+ bool* _aidl_return) override;
+
+ ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
+ const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
+ const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
+ override;
+ void onExternalDeviceConnectionChanged(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
ndk::ScopedAStatus createInputStream(
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
@@ -52,12 +71,24 @@
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus populateConnectedDevicePort(
- ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+ ::aidl::android::media::audio::common::AudioPort* audioPort,
+ int32_t nextPortId) override;
ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+ int32_t getNominalLatencyMs(
+ const ::aidl::android::media::audio::common::AudioPortConfig& portConfig) override;
+
+ ndk::ScopedAStatus createProxy(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort,
+ int32_t instancePortId, CachedProxy& proxy);
+ ndk::ScopedAStatus fetchAndCheckProxy(const StreamContext& context, CachedProxy& proxy);
+ ndk::ScopedAStatus findOrCreateProxy(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort, CachedProxy& proxy);
ChildInterface<BluetoothA2dp> mBluetoothA2dp;
ChildInterface<BluetoothLe> mBluetoothLe;
+ std::map<int32_t /*instantiated device port ID*/, CachedProxy> mProxies;
+ std::map<int32_t /*mix port handle*/, int32_t /*instantiated device port ID*/> mConnections;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
index 9f8acc9..613ac62 100644
--- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -29,6 +29,10 @@
// IModule interfaces
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
+ ndk::ScopedAStatus setAudioPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
+ ::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
+ bool* _aidl_return) override;
// Module interfaces
ndk::ScopedAStatus createInputStream(
@@ -43,7 +47,8 @@
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus populateConnectedDevicePort(
- ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+ ::aidl::android::media::audio::common::AudioPort* audioPort,
+ int32_t nextPortId) override;
ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index 6ee8f8a..d9ac4f0 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -44,7 +44,8 @@
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus populateConnectedDevicePort(
- ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+ ::aidl::android::media::audio::common::AudioPort* audioPort,
+ int32_t nextPortId) override;
ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
index 1258d38..35c3183 100644
--- a/audio/aidl/default/include/core-impl/StreamBluetooth.h
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -31,8 +31,16 @@
class StreamBluetooth : public StreamCommonImpl {
public:
- StreamBluetooth(StreamContext* context, const Metadata& metadata,
- ModuleBluetooth::BtProfileHandles&& btHandles);
+ static bool checkConfigParams(
+ const ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& pcmConfig,
+ const ::aidl::android::media::audio::common::AudioConfigBase& config);
+
+ StreamBluetooth(
+ StreamContext* context, const Metadata& metadata,
+ ModuleBluetooth::BtProfileHandles&& btHandles,
+ const std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>&
+ btDeviceProxy,
+ const ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& pcmConfig);
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -47,40 +55,35 @@
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
ndk::ScopedAStatus prepareToClose() override;
- const ConnectedDevices& getConnectedDevices() const override;
- ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
private:
- // Audio Pcm Config
- const uint32_t mSampleRate;
- const ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
- const ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
const size_t mFrameSizeBytes;
const bool mIsInput;
const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
const std::weak_ptr<IBluetoothLe> mBluetoothLe;
- size_t mPreferredDataIntervalUs;
- size_t mPreferredFrameCount;
-
+ const size_t mPreferredDataIntervalUs;
+ const size_t mPreferredFrameCount;
mutable std::mutex mLock;
- bool mIsInitialized GUARDED_BY(mLock);
- bool mIsReadyToClose GUARDED_BY(mLock);
- std::vector<std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>>
- mBtDeviceProxies GUARDED_BY(mLock);
-
- ::android::status_t initialize() REQUIRES(mLock);
- bool checkConfigParams(::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config);
+ // The lock is also used to serialize calls to the proxy.
+ std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl> mBtDeviceProxy
+ GUARDED_BY(mLock); // proxy may be null if the stream is not connected to a device
};
class StreamInBluetooth final : public StreamIn, public StreamBluetooth {
public:
friend class ndk::SharedRefBase;
+
+ static int32_t getNominalLatencyMs(size_t dataIntervalUs);
+
StreamInBluetooth(
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- ModuleBluetooth::BtProfileHandles&& btHandles);
+ ModuleBluetooth::BtProfileHandles&& btHandles,
+ const std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>&
+ btDeviceProxy,
+ const ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& pcmConfig);
private:
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
@@ -92,12 +95,18 @@
class StreamOutBluetooth final : public StreamOut, public StreamBluetooth {
public:
friend class ndk::SharedRefBase;
+
+ static int32_t getNominalLatencyMs(size_t dataIntervalUs);
+
StreamOutBluetooth(
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
- ModuleBluetooth::BtProfileHandles&& btHandles);
+ ModuleBluetooth::BtProfileHandles&& btHandles,
+ const std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>&
+ btDeviceProxy,
+ const ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& pcmConfig);
private:
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index ee10abf..cc06881 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -16,7 +16,6 @@
#pragma once
-#include <mutex>
#include <vector>
#include "core-impl/Stream.h"
@@ -56,13 +55,6 @@
r_submix::AudioConfig mStreamConfig;
std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
- // Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
- // locks and none of the mutex locks should be taken together.
- static std::mutex sSubmixRoutesLock;
- static std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
- std::shared_ptr<r_submix::SubmixRoute>>
- sSubmixRoutes GUARDED_BY(sSubmixRoutesLock);
-
// limit for number of read error log entries to avoid spamming the logs
static constexpr int kMaxReadErrorLogs = 5;
// The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
diff --git a/audio/aidl/default/loudnessEnhancer/Android.bp b/audio/aidl/default/loudnessEnhancer/Android.bp
index 89a72fe..cd44b50 100644
--- a/audio/aidl/default/loudnessEnhancer/Android.bp
+++ b/audio/aidl/default/loudnessEnhancer/Android.bp
@@ -27,8 +27,6 @@
name: "libloudnessenhancersw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"LoudnessEnhancerSw.cpp",
diff --git a/audio/aidl/default/noiseSuppression/Android.bp b/audio/aidl/default/noiseSuppression/Android.bp
index dad3d49..f24ded6 100644
--- a/audio/aidl/default/noiseSuppression/Android.bp
+++ b/audio/aidl/default/noiseSuppression/Android.bp
@@ -27,8 +27,6 @@
name: "libnssw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"NoiseSuppressionSw.cpp",
diff --git a/audio/aidl/default/presetReverb/Android.bp b/audio/aidl/default/presetReverb/Android.bp
index 18bdd17..d600141 100644
--- a/audio/aidl/default/presetReverb/Android.bp
+++ b/audio/aidl/default/presetReverb/Android.bp
@@ -27,8 +27,6 @@
name: "libpresetreverbsw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"PresetReverbSw.cpp",
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index 3e8dd7c..7bc783c 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -27,13 +27,36 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
+namespace {
+
+std::optional<r_submix::AudioConfig> getRemoteEndConfig(const AudioPort& audioPort) {
+ const auto& deviceAddress = audioPort.ext.get<AudioPortExt::device>().device.address;
+ const bool isInput = audioPort.flags.getTag() == AudioIoFlags::input;
+ if (auto submixRoute = r_submix::SubmixRoute::findRoute(deviceAddress);
+ submixRoute != nullptr) {
+ if ((isInput && submixRoute->isStreamOutOpen()) ||
+ (!isInput && submixRoute->isStreamInOpen())) {
+ return submixRoute->getPipeConfig();
+ }
+ }
+ return {};
+}
+
+} // namespace
+
ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
LOG(DEBUG) << __func__ << ": is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -44,6 +67,26 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus ModuleRemoteSubmix::setAudioPortConfig(const AudioPortConfig& in_requested,
+ AudioPortConfig* out_suggested,
+ bool* _aidl_return) {
+ auto fillConfig = [this](const AudioPort& port, AudioPortConfig* config) {
+ if (port.ext.getTag() == AudioPortExt::device) {
+ if (auto pipeConfig = getRemoteEndConfig(port); pipeConfig.has_value()) {
+ LOG(DEBUG) << "setAudioPortConfig: suggesting port config from the remote end.";
+ config->format = pipeConfig->format;
+ config->channelMask = pipeConfig->channelLayout;
+ config->sampleRate = Int{.value = pipeConfig->sampleRate};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ }
+ return generateDefaultPortConfig(port, config);
+ };
+ return Module::setAudioPortConfigImpl(in_requested, fillConfig, out_suggested, _aidl_return);
+}
+
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
@@ -58,8 +101,23 @@
offloadInfo);
}
-ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
- // Find the corresponding mix port and copy its profiles.
+ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
+ if (audioPort->ext.getTag() != AudioPortExt::device) {
+ LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ // If there is already a pipe with a stream for the port address, provide its configuration as
+ // the only option. Otherwise, find the corresponding mix port and copy its profiles.
+ if (auto pipeConfig = getRemoteEndConfig(*audioPort); pipeConfig.has_value()) {
+ audioPort->profiles.clear();
+ audioPort->profiles.push_back(AudioProfile{
+ .format = pipeConfig->format,
+ .channelMasks = std::vector<AudioChannelLayout>({pipeConfig->channelLayout}),
+ .sampleRates = std::vector<int>({pipeConfig->sampleRate})});
+ LOG(DEBUG) << __func__ << ": populated from remote end as: " << audioPort->toString();
+ return ndk::ScopedAStatus::ok();
+ }
+
// At this moment, the port has the same ID as the template port, see connectExternalDevice.
std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(audioPort->id);
if (routes.empty()) {
@@ -78,6 +136,7 @@
RETURN_STATUS_IF_ERROR(getAudioPort(route->sinkPortId, &mixPort));
}
audioPort->profiles = mixPort.profiles;
+ LOG(DEBUG) << __func__ << ": populated from the mix port as: " << audioPort->toString();
return ndk::ScopedAStatus::ok();
}
@@ -112,7 +171,7 @@
static constexpr int32_t kMaxLatencyMs =
(r_submix::kDefaultPipeSizeInFrames * 1000) / r_submix::kDefaultSampleRateHz;
static constexpr int32_t kMinLatencyMs = kMaxLatencyMs / r_submix::kDefaultPipePeriodCount;
- return (kMaxLatencyMs + kMinLatencyMs) / 2;
+ return kMinLatencyMs;
}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index 6258c93..df706ac 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -43,26 +43,10 @@
mStreamConfig.sampleRate = context->getSampleRate();
}
-std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
-std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
-
::android::status_t StreamRemoteSubmix::init() {
- {
- std::lock_guard guard(sSubmixRoutesLock);
- auto routeItr = sSubmixRoutes.find(mDeviceAddress);
- if (routeItr != sSubmixRoutes.end()) {
- mCurrentRoute = routeItr->second;
- }
- // If route is not available for this port, add it.
- if (mCurrentRoute == nullptr) {
- // Initialize the pipe.
- mCurrentRoute = std::make_shared<SubmixRoute>();
- if (::android::OK != mCurrentRoute->createPipe(mStreamConfig)) {
- LOG(ERROR) << __func__ << ": create pipe failed";
- return ::android::NO_INIT;
- }
- sSubmixRoutes.emplace(mDeviceAddress, mCurrentRoute);
- }
+ mCurrentRoute = SubmixRoute::findOrCreateRoute(mDeviceAddress, mStreamConfig);
+ if (mCurrentRoute == nullptr) {
+ return ::android::NO_INIT;
}
if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
LOG(ERROR) << __func__ << ": invalid stream config";
@@ -73,16 +57,13 @@
LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
return ::android::NO_INIT;
}
- // If the sink has been shutdown or pipe recreation is forced, delete the pipe and
- // recreate it.
- if (sink->isShutdown()) {
- LOG(DEBUG) << __func__ << ": Non-nullptr shut down sink when opening stream";
+ if ((!mIsInput || mCurrentRoute->isStreamInOpen()) && sink->isShutdown()) {
+ LOG(DEBUG) << __func__ << ": Shut down sink when opening stream";
if (::android::OK != mCurrentRoute->resetPipe()) {
LOG(ERROR) << __func__ << ": reset pipe failed";
return ::android::NO_INIT;
}
}
-
mCurrentRoute->openStream(mIsInput);
return ::android::OK;
}
@@ -116,14 +97,7 @@
ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
if (!mIsInput) {
- std::shared_ptr<SubmixRoute> route = nullptr;
- {
- std::lock_guard guard(sSubmixRoutesLock);
- auto routeItr = sSubmixRoutes.find(mDeviceAddress);
- if (routeItr != sSubmixRoutes.end()) {
- route = routeItr->second;
- }
- }
+ std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(mDeviceAddress);
if (route != nullptr) {
sp<MonoPipe> sink = route->getSink();
if (sink == nullptr) {
@@ -150,9 +124,7 @@
if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
mCurrentRoute->releasePipe();
LOG(DEBUG) << __func__ << ": pipe destroyed";
-
- std::lock_guard guard(sSubmixRoutesLock);
- sSubmixRoutes.erase(mDeviceAddress);
+ SubmixRoute::removeRoute(mDeviceAddress);
}
mCurrentRoute.reset();
}
@@ -203,7 +175,7 @@
// Calculate the maximum size of the pipe buffer in frames for the specified stream.
size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
- auto pipeConfig = mCurrentRoute->mPipeConfig;
+ auto pipeConfig = mCurrentRoute->getPipeConfig();
const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
}
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
index f04e607..7d706c2 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.cpp
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -23,9 +23,49 @@
#include "SubmixRoute.h"
using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::media::audio::common::AudioDeviceAddress;
namespace aidl::android::hardware::audio::core::r_submix {
+// static
+SubmixRoute::RoutesMonitor SubmixRoute::getRoutes() {
+ static std::mutex submixRoutesLock;
+ static RoutesMap submixRoutes;
+ return RoutesMonitor(submixRoutesLock, submixRoutes);
+}
+
+// static
+std::shared_ptr<SubmixRoute> SubmixRoute::findOrCreateRoute(const AudioDeviceAddress& deviceAddress,
+ const AudioConfig& pipeConfig) {
+ auto routes = getRoutes();
+ auto routeItr = routes->find(deviceAddress);
+ if (routeItr != routes->end()) {
+ return routeItr->second;
+ }
+ auto route = std::make_shared<SubmixRoute>();
+ if (::android::OK != route->createPipe(pipeConfig)) {
+ LOG(ERROR) << __func__ << ": create pipe failed";
+ return nullptr;
+ }
+ routes->emplace(deviceAddress, route);
+ return route;
+}
+
+// static
+std::shared_ptr<SubmixRoute> SubmixRoute::findRoute(const AudioDeviceAddress& deviceAddress) {
+ auto routes = getRoutes();
+ auto routeItr = routes->find(deviceAddress);
+ if (routeItr != routes->end()) {
+ return routeItr->second;
+ }
+ return nullptr;
+}
+
+// static
+void SubmixRoute::removeRoute(const AudioDeviceAddress& deviceAddress) {
+ getRoutes()->erase(deviceAddress);
+}
+
// Verify a submix input or output stream can be opened.
bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
// If the stream is already open, don't open it again.
@@ -44,6 +84,7 @@
// Compare this stream config with existing pipe config, returning false if they do *not*
// match, true otherwise.
bool SubmixRoute::isStreamConfigCompatible(const AudioConfig& streamConfig) {
+ std::lock_guard guard(mLock);
if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
<< streamConfig.channelLayout.toString()
@@ -98,6 +139,9 @@
}
mStreamInStandby = true;
mReadCounterFrames = 0;
+ if (mSink != nullptr) {
+ mSink->shutdown(false);
+ }
} else {
mStreamOutOpen = true;
}
@@ -106,8 +150,7 @@
void SubmixRoute::closeStream(bool isInput) {
std::lock_guard guard(mLock);
if (isInput) {
- mInputRefCount--;
- if (mInputRefCount == 0) {
+ if (--mInputRefCount == 0) {
mStreamInOpen = false;
if (mSink != nullptr) {
mSink->shutdown(true);
@@ -160,17 +203,14 @@
LOG(FATAL) << __func__ << ": Negotiation for the source failed, index = " << index;
return ::android::BAD_INDEX;
}
- LOG(VERBOSE) << __func__ << ": created pipe";
-
- mPipeConfig = streamConfig;
- mPipeConfig.frameCount = sink->maxFrames();
-
- LOG(VERBOSE) << __func__ << ": Pipe frame size : " << mPipeConfig.frameSize
- << ", pipe frames : " << mPipeConfig.frameCount;
+ LOG(VERBOSE) << __func__ << ": Pipe frame size : " << streamConfig.frameSize
+ << ", pipe frames : " << sink->maxFrames();
// Save references to the source and sink.
{
std::lock_guard guard(mLock);
+ mPipeConfig = streamConfig;
+ mPipeConfig.frameCount = sink->maxFrames();
mSink = std::move(sink);
mSource = std::move(source);
}
@@ -179,15 +219,15 @@
}
// Release references to the sink and source.
-void SubmixRoute::releasePipe() {
+AudioConfig SubmixRoute::releasePipe() {
std::lock_guard guard(mLock);
mSink.clear();
mSource.clear();
+ return mPipeConfig;
}
::android::status_t SubmixRoute::resetPipe() {
- releasePipe();
- return createPipe(mPipeConfig);
+ return createPipe(releasePipe());
}
void SubmixRoute::standby(bool isInput) {
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
index 252b1c9..160df41 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.h
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -25,6 +25,7 @@
#include <media/nbaio/MonoPipeReader.h>
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceAddress.h>
#include <aidl/android/media/audio/common/AudioFormatDescription.h>
using aidl::android::media::audio::common::AudioChannelLayout;
@@ -60,7 +61,13 @@
class SubmixRoute {
public:
- AudioConfig mPipeConfig;
+ static std::shared_ptr<SubmixRoute> findOrCreateRoute(
+ const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress,
+ const AudioConfig& pipeConfig);
+ static std::shared_ptr<SubmixRoute> findRoute(
+ const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
+ static void removeRoute(
+ const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
bool isStreamInOpen() {
std::lock_guard guard(mLock);
@@ -90,6 +97,10 @@
std::lock_guard guard(mLock);
return mSource;
}
+ AudioConfig getPipeConfig() {
+ std::lock_guard guard(mLock);
+ return mPipeConfig;
+ }
bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig);
void closeStream(bool isInput);
@@ -98,17 +109,31 @@
bool hasAtleastOneStreamOpen();
int notifyReadError();
void openStream(bool isInput);
- void releasePipe();
+ AudioConfig releasePipe();
::android::status_t resetPipe();
bool shouldBlockWrite();
void standby(bool isInput);
long updateReadCounterFrames(size_t frameCount);
private:
+ using RoutesMap = std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
+ std::shared_ptr<r_submix::SubmixRoute>>;
+ class RoutesMonitor {
+ public:
+ RoutesMonitor(std::mutex& mutex, RoutesMap& routes) : mLock(mutex), mRoutes(routes) {}
+ RoutesMap* operator->() { return &mRoutes; }
+
+ private:
+ std::lock_guard<std::mutex> mLock;
+ RoutesMap& mRoutes;
+ };
+
+ static RoutesMonitor getRoutes();
+
bool isStreamConfigCompatible(const AudioConfig& streamConfig);
std::mutex mLock;
-
+ AudioConfig mPipeConfig GUARDED_BY(mLock);
bool mStreamInOpen GUARDED_BY(mLock) = false;
int mInputRefCount GUARDED_BY(mLock) = 0;
bool mStreamInStandby GUARDED_BY(mLock) = true;
diff --git a/audio/aidl/default/spatializer/Android.bp b/audio/aidl/default/spatializer/Android.bp
new file mode 100644
index 0000000..05ed365
--- /dev/null
+++ b/audio/aidl/default/spatializer/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+ name: "libspatializersw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ ],
+ srcs: [
+ "SpatializerSw.cpp",
+ ":effectCommonFile",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/spatializer/SpatializerSw.cpp b/audio/aidl/default/spatializer/SpatializerSw.cpp
new file mode 100644
index 0000000..434ed5a
--- /dev/null
+++ b/audio/aidl/default/spatializer/SpatializerSw.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_SpatializerSw"
+
+#include "SpatializerSw.h"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include <optional>
+
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidSpatializerSw;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::SpatializerSw;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::HeadTracking;
+using aidl::android::media::audio::common::Spatialization;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidSpatializerSw()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (!instanceSpp) {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+
+ *instanceSpp = ndk::SharedRefBase::make<SpatializerSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidSpatializerSw()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = SpatializerSw::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string SpatializerSw::kEffectName = "SpatializerSw";
+
+const std::vector<Range::SpatializerRange> SpatializerSw::kRanges = {
+ MAKE_RANGE(Spatializer, supportedChannelLayout, std::vector<AudioChannelLayout>{},
+ std::vector<AudioChannelLayout>{}),
+ MAKE_RANGE(Spatializer, spatializationLevel, Spatialization::Level::NONE,
+ Spatialization::Level::BED_PLUS_OBJECTS),
+ MAKE_RANGE(Spatializer, spatializationMode, Spatialization::Mode::BINAURAL,
+ Spatialization::Mode::TRANSAURAL),
+ MAKE_RANGE(Spatializer, headTrackingSensorId, std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::max()),
+ MAKE_RANGE(Spatializer, headTrackingMode, HeadTracking::Mode::OTHER,
+ HeadTracking::Mode::RELATIVE_SCREEN),
+ MAKE_RANGE(Spatializer, headTrackingConnectionMode,
+ HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED,
+ HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL)};
+const Capability SpatializerSw::kCapability = {.range = {SpatializerSw::kRanges}};
+const Descriptor SpatializerSw::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidSpatializer(),
+ .uuid = getEffectImplUuidSpatializerSw()},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .hwAcceleratorMode = Flags::HardwareAccelerator::NONE},
+ .name = SpatializerSw::kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = SpatializerSw::kCapability};
+
+ndk::ScopedAStatus SpatializerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SpatializerSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::spatializer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& param = specific.get<Parameter::Specific::spatializer>();
+ RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+
+ return mContext->setParam(param.getTag(), param);
+}
+
+ndk::ScopedAStatus SpatializerSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::spatializerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto spatializerId = id.get<Parameter::Id::spatializerTag>();
+ auto spatializerTag = spatializerId.getTag();
+ switch (spatializerTag) {
+ case Spatializer::Id::commonTag: {
+ auto specificTag = spatializerId.get<Spatializer::Id::commonTag>();
+ std::optional<Spatializer> param = mContext->getParam(specificTag);
+ if (!param.has_value()) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "SpatializerTagNotSupported");
+ }
+ specific->set<Parameter::Specific::spatializer>(param.value());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "SpatializerTagNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> SpatializerSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<SpatializerSwContext>(1 /* statusFmqDepth */, common);
+ }
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> SpatializerSw::getContext() {
+ return mContext;
+}
+
+RetCode SpatializerSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+SpatializerSw::~SpatializerSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status SpatializerSw::effectProcessImpl(float* in, float* out, int samples) {
+ RETURN_VALUE_IF(!mContext, (IEffect::Status{EX_NULL_POINTER, 0, 0}), "nullContext");
+ return mContext->process(in, out, samples);
+}
+
+SpatializerSwContext::SpatializerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+}
+
+SpatializerSwContext::~SpatializerSwContext() {
+ LOG(DEBUG) << __func__;
+}
+
+template <typename TAG>
+std::optional<Spatializer> SpatializerSwContext::getParam(TAG tag) {
+ if (mParamsMap.find(tag) != mParamsMap.end()) {
+ return mParamsMap.at(tag);
+ }
+ return std::nullopt;
+}
+
+template <typename TAG>
+ndk::ScopedAStatus SpatializerSwContext::setParam(TAG tag, Spatializer spatializer) {
+ mParamsMap[tag] = spatializer;
+ return ndk::ScopedAStatus::ok();
+}
+
+IEffect::Status SpatializerSwContext::process(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+ IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+ const auto inputChannelCount = getChannelCount(mCommon.input.base.channelMask);
+ const auto outputChannelCount = getChannelCount(mCommon.output.base.channelMask);
+ if (outputChannelCount < 2 || inputChannelCount < outputChannelCount) {
+ LOG(ERROR) << __func__ << " invalid channel count, in: " << inputChannelCount
+ << " out: " << outputChannelCount;
+ return status;
+ }
+
+ int iFrames = samples / inputChannelCount;
+ for (int i = 0; i < iFrames; i++) {
+ std::memcpy(out, in, outputChannelCount);
+ in += inputChannelCount;
+ out += outputChannelCount;
+ }
+ return {STATUS_OK, static_cast<int32_t>(iFrames * inputChannelCount),
+ static_cast<int32_t>(iFrames * outputChannelCount)};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/spatializer/SpatializerSw.h b/audio/aidl/default/spatializer/SpatializerSw.h
new file mode 100644
index 0000000..b205704
--- /dev/null
+++ b/audio/aidl/default/spatializer/SpatializerSw.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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 "effect-impl/EffectContext.h"
+#include "effect-impl/EffectImpl.h"
+
+#include <fmq/AidlMessageQueue.h>
+
+#include <unordered_map>
+#include <vector>
+
+namespace aidl::android::hardware::audio::effect {
+
+class SpatializerSwContext final : public EffectContext {
+ public:
+ SpatializerSwContext(int statusDepth, const Parameter::Common& common);
+ ~SpatializerSwContext();
+
+ template <typename TAG>
+ std::optional<Spatializer> getParam(TAG tag);
+ template <typename TAG>
+ ndk::ScopedAStatus setParam(TAG tag, Spatializer spatializer);
+
+ IEffect::Status process(float* in, float* out, int samples);
+
+ private:
+ std::unordered_map<Spatializer::Tag, Spatializer> mParamsMap;
+};
+
+class SpatializerSw final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Capability kCapability;
+ static const Descriptor kDescriptor;
+ ~SpatializerSw();
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> getContext() override;
+ RetCode releaseContext() override;
+
+ std::string getEffectName() override { return kEffectName; };
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ private:
+ static const std::vector<Range::SpatializerRange> kRanges;
+ std::shared_ptr<SpatializerSwContext> mContext = nullptr;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index f926e09..1d97bc4 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -87,12 +87,13 @@
offloadInfo);
}
-ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
+ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort,
+ int32_t nextPortId) {
if (!isUsbDevicePort(*audioPort)) {
LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a usb device port";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return ModuleAlsa::populateConnectedDevicePort(audioPort);
+ return ModuleAlsa::populateConnectedDevicePort(audioPort, nextPortId);
}
ndk::ScopedAStatus ModuleUsb::checkAudioPatchEndpointsMatch(
diff --git a/audio/aidl/default/virtualizer/Android.bp b/audio/aidl/default/virtualizer/Android.bp
index ed0199d..1c41bb5 100644
--- a/audio/aidl/default/virtualizer/Android.bp
+++ b/audio/aidl/default/virtualizer/Android.bp
@@ -27,8 +27,6 @@
name: "libvirtualizersw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"VirtualizerSw.cpp",
diff --git a/audio/aidl/default/visualizer/Android.bp b/audio/aidl/default/visualizer/Android.bp
index 091daa2..68f7177 100644
--- a/audio/aidl/default/visualizer/Android.bp
+++ b/audio/aidl/default/visualizer/Android.bp
@@ -27,8 +27,6 @@
name: "libvisualizersw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"VisualizerSw.cpp",
diff --git a/audio/aidl/default/volume/Android.bp b/audio/aidl/default/volume/Android.bp
index 418bb8d..f1a051f 100644
--- a/audio/aidl/default/volume/Android.bp
+++ b/audio/aidl/default/volume/Android.bp
@@ -27,8 +27,6 @@
name: "libvolumesw",
defaults: [
"aidlaudioeffectservice_defaults",
- "latest_android_media_audio_common_types_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_shared",
],
srcs: [
"VolumeSw.cpp",
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 191f928..85319ec 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -36,16 +36,27 @@
"-Werror",
"-Wthread-safety",
],
+ test_config_template: "VtsHalAudioTargetTestTemplate.xml",
test_suites: [
"general-tests",
"vts",
],
srcs: [
- ":effectCommonFile",
"TestUtils.cpp",
],
}
+cc_defaults {
+ name: "VtsHalAudioEffectTargetTestDefaults",
+ defaults: [
+ "latest_android_hardware_audio_effect_ndk_static",
+ "VtsHalAudioTargetTestDefaults",
+ ],
+ srcs: [
+ ":effectCommonFile",
+ ],
+}
+
cc_test {
name: "VtsHalAudioCoreTargetTest",
defaults: [
@@ -61,30 +72,29 @@
"VtsHalAudioCoreConfigTargetTest.cpp",
"VtsHalAudioCoreModuleTargetTest.cpp",
],
- test_config: "VtsHalAudioCoreTargetTest.xml",
}
cc_test {
name: "VtsHalAudioEffectFactoryTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalAudioEffectFactoryTargetTest.cpp"],
}
cc_test {
name: "VtsHalAudioEffectTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalAudioEffectTargetTest.cpp"],
}
cc_test {
name: "VtsHalBassBoostTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalBassBoostTargetTest.cpp"],
}
cc_test {
name: "VtsHalDownmixTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalDownmixTargetTest.cpp"],
shared_libs: [
"libaudioutils",
@@ -93,79 +103,85 @@
cc_test {
name: "VtsHalDynamicsProcessingTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
static_libs: ["libaudioaidlranges"],
srcs: ["VtsHalDynamicsProcessingTest.cpp"],
}
cc_test {
name: "VtsHalEnvironmentalReverbTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalEnvironmentalReverbTargetTest.cpp"],
}
cc_test {
name: "VtsHalEqualizerTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalEqualizerTargetTest.cpp"],
}
cc_test {
name: "VtsHalHapticGeneratorTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalHapticGeneratorTargetTest.cpp"],
}
cc_test {
name: "VtsHalLoudnessEnhancerTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"],
}
cc_test {
name: "VtsHalPresetReverbTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalPresetReverbTargetTest.cpp"],
}
cc_test {
name: "VtsHalVirtualizerTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalVirtualizerTargetTest.cpp"],
}
cc_test {
name: "VtsHalVisualizerTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalVisualizerTargetTest.cpp"],
}
cc_test {
name: "VtsHalVolumeTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalVolumeTargetTest.cpp"],
}
cc_test {
name: "VtsHalAECTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalAECTargetTest.cpp"],
}
cc_test {
name: "VtsHalAGC1TargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalAGC1TargetTest.cpp"],
}
cc_test {
name: "VtsHalAGC2TargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalAGC2TargetTest.cpp"],
}
cc_test {
name: "VtsHalNSTargetTest",
- defaults: ["VtsHalAudioTargetTestDefaults"],
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalNSTargetTest.cpp"],
}
+
+cc_test {
+ name: "VtsHalSpatializerTargetTest",
+ defaults: ["VtsHalAudioEffectTargetTestDefaults"],
+ srcs: ["VtsHalSpatializerTargetTest.cpp"],
+}
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index a2499fd..ca36655 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -21,6 +21,7 @@
#include <unordered_map>
#include <vector>
+#include <aidl/Vintf.h>
#include <android/binder_auto_utils.h>
#include "TestUtils.h"
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index d813554..4a5c537 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -21,6 +21,7 @@
#include <string>
#include <type_traits>
#include <unordered_map>
+#include <utility>
#include <vector>
#include <Utils.h>
@@ -263,12 +264,11 @@
return s;
}
- template <typename T, typename S, Range::Tag R, typename T::Tag tag, typename Functor>
+ template <typename T, typename S, Range::Tag R, typename T::Tag tag>
static std::set<S> getTestValueSet(
- std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList,
- Functor functor) {
+ std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> descList) {
std::set<S> result;
- for (const auto& [_, desc] : kFactoryDescList) {
+ for (const auto& [_, desc] : descList) {
if (desc.capability.range.getTag() == R) {
const auto& ranges = desc.capability.range.get<R>();
for (const auto& range : ranges) {
@@ -281,6 +281,14 @@
}
}
}
+ return result;
+ }
+
+ template <typename T, typename S, Range::Tag R, typename T::Tag tag, typename Functor>
+ static std::set<S> getTestValueSet(
+ std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> descList,
+ Functor functor) {
+ auto result = getTestValueSet<T, S, R, tag>(descList);
return functor(result);
}
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index e9f3251..515b8a2 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -69,6 +69,23 @@
<< "\n but is has completed with: " << status;
}
+inline ::testing::AssertionResult assertIsOkOrUnknownTransaction(
+ const char* expr, const ::ndk::ScopedAStatus& status) {
+ if (status.getStatus() == STATUS_UNKNOWN_TRANSACTION) {
+ return ::testing::AssertionSuccess();
+ }
+ return assertIsOk(expr, status);
+}
+
+inline ::testing::AssertionResult assertResultOrUnknownTransaction(
+ const char* exp_expr, const char* act_expr, int32_t expected,
+ const ::ndk::ScopedAStatus& status) {
+ if (status.getStatus() == STATUS_UNKNOWN_TRANSACTION) {
+ return ::testing::AssertionSuccess();
+ }
+ return assertResult(exp_expr, act_expr, expected, status);
+}
+
} // namespace detail
} // namespace android::hardware::audio::common::testing
@@ -93,3 +110,15 @@
GTEST_SKIP() << "Skip data path for offload"; \
} \
})
+
+// Test that the transaction status 'isOk' if it is a known transaction
+#define EXPECT_IS_OK_OR_UNKNOWN_TRANSACTION(ret) \
+ EXPECT_PRED_FORMAT1( \
+ ::android::hardware::audio::common::testing::detail::assertIsOkOrUnknownTransaction, \
+ ret)
+
+// Test that the transaction status is as expected if it is a known transaction
+#define EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(expected, ret) \
+ EXPECT_PRED_FORMAT2( \
+ ::android::hardware::audio::common::testing::detail::assertResultOrUnknownTransaction, \
+ expected, ret)
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 39168b1..f972b84 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -18,7 +18,6 @@
#include <string>
#include <unordered_set>
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalAECParamTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index 6066025..75da589 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalAGC1ParamTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 8793e4c..5f57a88 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalAGC2ParamTest"
#include <android-base/logging.h>
#include <android/binder_enums.h>
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 697aae9..f91795b 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -573,6 +573,8 @@
WithDevicePortConnectedState& operator=(const WithDevicePortConnectedState&) = delete;
~WithDevicePortConnectedState() {
if (mModule != nullptr) {
+ EXPECT_IS_OK_OR_UNKNOWN_TRANSACTION(mModule->prepareToDisconnectExternalDevice(getId()))
+ << "when preparing to disconnect device port ID " << getId();
EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
<< "when disconnecting device port ID " << getId();
}
@@ -1753,6 +1755,9 @@
ScopedAStatus status = module->connectExternalDevice(portWithData, &connectedPort);
EXPECT_STATUS(EX_ILLEGAL_STATE, status) << "static port " << portWithData.toString();
if (status.isOk()) {
+ EXPECT_IS_OK_OR_UNKNOWN_TRANSACTION(
+ module->prepareToDisconnectExternalDevice(connectedPort.id))
+ << "when preparing to disconnect device port ID " << connectedPort.id;
EXPECT_IS_OK(module->disconnectExternalDevice(connectedPort.id))
<< "when disconnecting device port ID " << connectedPort.id;
}
@@ -1782,6 +1787,9 @@
invalidPort.id = portId;
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(invalidPort, &ignored))
<< "port ID " << portId << ", when setting CONNECTED state";
+ EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(EX_ILLEGAL_ARGUMENT,
+ module->prepareToDisconnectExternalDevice(portId))
+ << "port ID " << portId << ", when preparing to disconnect";
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(portId))
<< "port ID " << portId << ", when setting DISCONNECTED state";
}
@@ -1792,6 +1800,9 @@
if (port.ext.getTag() != AudioPortExt::Tag::device) {
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
<< "non-device port ID " << port.id << " when setting CONNECTED state";
+ EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(EX_ILLEGAL_ARGUMENT,
+ module->prepareToDisconnectExternalDevice(port.id))
+ << "non-device port ID " << port.id << " when preparing to disconnect";
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
<< "non-device port ID " << port.id << " when setting DISCONNECTED state";
} else {
@@ -1800,6 +1811,10 @@
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
<< "for a permanently attached device port ID " << port.id
<< " when setting CONNECTED state";
+ EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(
+ EX_ILLEGAL_ARGUMENT, module->prepareToDisconnectExternalDevice(port.id))
+ << "for a permanently attached device port ID " << port.id
+ << " when preparing to disconnect";
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
<< "for a permanently attached device port ID " << port.id
<< " when setting DISCONNECTED state";
@@ -1817,6 +1832,9 @@
GTEST_SKIP() << "No external devices in the module.";
}
for (const auto& port : ports) {
+ EXPECT_STATUS_OR_UNKNOWN_TRANSACTION(EX_ILLEGAL_ARGUMENT,
+ module->prepareToDisconnectExternalDevice(port.id))
+ << "when preparing to disconnect already disconnected device port ID " << port.id;
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
<< "when disconnecting already disconnected device port ID " << port.id;
AudioPort portWithData = GenerateUniqueDeviceAddress(port);
@@ -1851,6 +1869,10 @@
// Our test assumes that 'getAudioPort' returns at least one profile, and it
// is not a dynamic profile.
ASSERT_NO_FATAL_FAILURE(config.SetUp(module.get()));
+ EXPECT_IS_OK_OR_UNKNOWN_TRANSACTION(
+ module->prepareToDisconnectExternalDevice(portConnected.getId()))
+ << "when preparing to disconnect device port ID " << port.id
+ << " with active configuration " << config.getId();
EXPECT_STATUS(EX_ILLEGAL_STATE, module->disconnectExternalDevice(portConnected.getId()))
<< "when trying to disconnect device port ID " << port.id
<< " with active configuration " << config.getId();
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index aaf9ad4..418fedb 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -16,13 +16,11 @@
#define LOG_TAG "VtsHalAudioEffectTargetTest"
-#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include <aidl/Gtest.h>
-#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml b/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
similarity index 86%
rename from audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
rename to audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
index 9d3adc1..c92e852 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
+++ b/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs VtsHalAudioCoreTargetTest.">
+<configuration description="Runs {MODULE}.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
@@ -27,12 +27,12 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="VtsHalAudioCoreTargetTest->/data/local/tmp/VtsHalAudioCoreTargetTest" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsHalAudioCoreTargetTest" />
+ <option name="module-name" value="{MODULE}" />
<option name="native-test-timeout" value="10m" />
</test>
</configuration>
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 2d9a233..135940d 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-#include <limits.h>
-
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalBassBoostTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index d7db567..2272e92 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalDownmixTargetTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 2650f49..3f7a76d 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -18,7 +18,6 @@
#include <string>
#include <unordered_set>
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalDynamicsProcessingTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 474b361..765c377 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalEnvironmentalReverbTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 09396d1..76838cef 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -15,15 +15,10 @@
*/
#include <algorithm>
-#include <limits>
-#include <map>
-#include <memory>
-#include <optional>
#include <string>
#include <vector>
#include <aidl/Gtest.h>
-#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include <aidl/android/hardware/audio/effect/IFactory.h>
#define LOG_TAG "VtsHalEqualizerTest"
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index 5a32398..d312111 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -18,7 +18,6 @@
#include <utility>
#include <vector>
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalHapticGeneratorTargetTest"
#include <android-base/logging.h>
#include <android/binder_enums.h>
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 925f9ec..7f0091f 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -16,7 +16,6 @@
#include <string>
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalLoudnessEnhancerTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index 12d56b0..5c13512 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -16,7 +16,6 @@
#include <unordered_set>
-#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/effect/NoiseSuppression.h>
#define LOG_TAG "VtsHalNSParamTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 57eda09..1453495 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalPresetReverbTargetTest"
#include <android-base/logging.h>
#include <android/binder_enums.h>
diff --git a/audio/aidl/vts/VtsHalSpatializerTargetTest.cpp b/audio/aidl/vts/VtsHalSpatializerTargetTest.cpp
new file mode 100644
index 0000000..f0b51b9
--- /dev/null
+++ b/audio/aidl/vts/VtsHalSpatializerTargetTest.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 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 "VtsHalSpatializerTest"
+#include <android-base/logging.h>
+
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::Range;
+using aidl::android::hardware::audio::effect::Spatializer;
+using aidl::android::media::audio::common::HeadTracking;
+using aidl::android::media::audio::common::Spatialization;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
+using ::android::internal::ToString;
+
+enum ParamName {
+ PARAM_INSTANCE_NAME,
+ PARAM_SPATIALIZATION_LEVEL,
+ PARAM_SPATIALIZATION_MODE,
+ PARAM_HEADTRACK_SENSORID,
+ PARAM_HEADTRACK_MODE,
+ PARAM_HEADTRACK_CONNECTION_MODE
+};
+
+using SpatializerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, Spatialization::Level,
+ Spatialization::Mode, int /* sensor ID */, HeadTracking::Mode,
+ HeadTracking::ConnectionMode>;
+
+class SpatializerParamTest : public ::testing::TestWithParam<SpatializerParamTestParam>,
+ public EffectHelper {
+ public:
+ SpatializerParamTest()
+ : mSpatializerParams([&]() {
+ Spatialization::Level level = std::get<PARAM_SPATIALIZATION_LEVEL>(GetParam());
+ Spatialization::Mode mode = std::get<PARAM_SPATIALIZATION_MODE>(GetParam());
+ int sensorId = std::get<PARAM_HEADTRACK_SENSORID>(GetParam());
+ HeadTracking::Mode htMode = std::get<PARAM_HEADTRACK_MODE>(GetParam());
+ HeadTracking::ConnectionMode htConnectMode =
+ std::get<PARAM_HEADTRACK_CONNECTION_MODE>(GetParam());
+ std::map<Spatializer::Tag, Spatializer> params;
+ params[Spatializer::spatializationLevel] =
+ Spatializer::make<Spatializer::spatializationLevel>(level);
+ params[Spatializer::spatializationMode] =
+ Spatializer::make<Spatializer::spatializationMode>(mode);
+ params[Spatializer::headTrackingSensorId] =
+ Spatializer::make<Spatializer::headTrackingSensorId>(sensorId);
+ params[Spatializer::headTrackingMode] =
+ Spatializer::make<Spatializer::headTrackingMode>(htMode);
+ params[Spatializer::headTrackingConnectionMode] =
+ Spatializer::make<Spatializer::headTrackingConnectionMode>(htConnectMode);
+ return params;
+ }()) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ Spatializer spatializer = Spatializer::make<Spatializer::headTrackingSensorId>(0);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::spatializer>(spatializer);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ const std::map<Spatializer::Tag, Spatializer> mSpatializerParams;
+};
+
+TEST_P(SpatializerParamTest, SetAndGetParam) {
+ for (const auto& it : mSpatializerParams) {
+ auto& tag = it.first;
+ auto& spatializer = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isParameterValid<Spatializer, Range::spatializer>(it.second, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::spatializer>(spatializer);
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // only get if parameter in range and set success
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Id id;
+ Spatializer::Id spatializerId;
+ spatializerId.set<Spatializer::Id::commonTag>(tag);
+ id.set<Parameter::Id::spatializerTag>(spatializerId);
+ // if set success, then get should match
+ EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
+ EXPECT_EQ(expectParam, getParam);
+ }
+ }
+}
+
+std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
+INSTANTIATE_TEST_SUITE_P(
+ SpatializerTest, SpatializerParamTest,
+ ::testing::Combine(
+ testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, getEffectTypeUuidSpatializer())),
+ testing::ValuesIn(EffectHelper::getTestValueSet<
+ Spatializer, Spatialization::Level, Range::spatializer,
+ Spatializer::spatializationLevel>(kDescPair)),
+ testing::ValuesIn(EffectHelper::getTestValueSet<
+ Spatializer, Spatialization::Mode, Range::spatializer,
+ Spatializer::spatializationMode>(kDescPair)),
+ testing::ValuesIn(
+ EffectHelper::getTestValueSet<Spatializer, int, Range::spatializer,
+ Spatializer::headTrackingSensorId>(
+ kDescPair, EffectHelper::expandTestValueBasic<int>)),
+ testing::ValuesIn(EffectHelper::getTestValueSet<
+ Spatializer, HeadTracking::Mode, Range::spatializer,
+ Spatializer::headTrackingMode>(kDescPair)),
+ testing::ValuesIn(EffectHelper::getTestValueSet<
+ Spatializer, HeadTracking::ConnectionMode, Range::spatializer,
+ Spatializer::headTrackingConnectionMode>(kDescPair))),
+ [](const testing::TestParamInfo<SpatializerParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string level = ToString(std::get<PARAM_SPATIALIZATION_LEVEL>(info.param));
+ std::string mode = ToString(std::get<PARAM_SPATIALIZATION_MODE>(info.param));
+ std::string sensorId = ToString(std::get<PARAM_HEADTRACK_SENSORID>(info.param));
+ std::string htMode = ToString(std::get<PARAM_HEADTRACK_MODE>(info.param));
+ std::string htConnectMode =
+ ToString(std::get<PARAM_HEADTRACK_CONNECTION_MODE>(info.param));
+ std::string name = getPrefix(descriptor) + "_sensorID_" + level + "_mode_" + mode +
+ "_sensorID_" + sensorId + "_HTMode_" + htMode +
+ "_HTConnectionMode_" + htConnectMode;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SpatializerParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index 3e39d3a..0c24f90 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalVirtualizerTest"
#include <android-base/logging.h>
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index 1b8352b..db83715 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -16,7 +16,6 @@
#include <unordered_set>
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalVisualizerTest"
#include <android-base/logging.h>
#include <android/binder_enums.h>
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 257100b..aa2c05f 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <aidl/Vintf.h>
#define LOG_TAG "VtsHalVolumeTest"
#include <android-base/logging.h>
diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
index ccfa22d..5c5917b 100644
--- a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
+++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
@@ -41,9 +41,10 @@
void clearRemoteTaskCallback();
void notifyApStateChange(in android.hardware.automotive.remoteaccess.ApState state);
boolean isTaskScheduleSupported();
+ android.hardware.automotive.remoteaccess.TaskType[] getSupportedTaskTypesForScheduling();
void scheduleTask(in android.hardware.automotive.remoteaccess.ScheduleInfo scheduleInfo);
void unscheduleTask(String clientId, String scheduleId);
void unscheduleAllTasks(String clientId);
boolean isTaskScheduled(String clientId, String scheduleId);
- List<android.hardware.automotive.remoteaccess.ScheduleInfo> getAllScheduledTasks(String clientId);
+ List<android.hardware.automotive.remoteaccess.ScheduleInfo> getAllPendingScheduledTasks(String clientId);
}
diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
index a929e10..a5d81cf 100644
--- a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
+++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
@@ -36,6 +36,7 @@
parcelable ScheduleInfo {
String clientId;
String scheduleId;
+ android.hardware.automotive.remoteaccess.TaskType taskType;
byte[] taskData;
int count;
long startTimeInEpochSeconds;
diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl
new file mode 100644
index 0000000..da70626
--- /dev/null
+++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.remoteaccess;
+@Backing(type="int") @VintfStability
+enum TaskType {
+ CUSTOM = 0,
+ ENTER_GARAGE_MODE = 1,
+}
diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
index 4912651..705cdbd 100644
--- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
+++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl
@@ -19,12 +19,39 @@
import android.hardware.automotive.remoteaccess.ApState;
import android.hardware.automotive.remoteaccess.IRemoteTaskCallback;
import android.hardware.automotive.remoteaccess.ScheduleInfo;
+import android.hardware.automotive.remoteaccess.TaskType;
/**
- * Interface representing a remote wakeup client.
+ * The remote access HAL.
*
- * A wakeup client is a binary outside Android framework that communicates with
- * a wakeup server and receives wake up command.
+ * <p>This HAL represents an external system that is always on even when Android
+ * is powered off. It is capable of wakeing up and notifying Android when a
+ * remote task arrives.
+ *
+ * <p>For cloud-based remote access, a cloud server will issue the remote task
+ * to the external system, which will then be forwarded to Android. The client
+ * is expected to call {@code setRemoteTaskCallback} to register the remote
+ * task callback and uses the information returned from {@code getVehicleId},
+ * {@code getWakeupServiceName} and {@code getProcessorId} to register with
+ * a remote server.
+ *
+ * <p>For serverless remote access, the remote task comes from the external
+ * system alone and no server is involved. The external system may support
+ * scheduling a remote task to executed later through {@code scheduleTask}.
+ *
+ * <p>For both cloud-based and serverless remote access, the ideal use case
+ * is to wake up Android when the vehicle is not in use and then shutdown
+ * Android after the task is complete. However, user may access the vehicle
+ * during this period, and Android must not be shutdown if this happens.
+ *
+ * <p>If this interface is implemented, then VHAL property
+ * {@code VEHICLE_IN_USE} must be supported to represent whether the vehicle is
+ * currently in use. Android will check this before sending the shutdown
+ * request.
+ *
+ * <p>The external power controller system must also check whether vehicle is
+ * in use upon receiving the shutdown request and makes sure that an
+ * user-unexpected shutdown must not happen.
*/
@VintfStability
interface IRemoteAccess {
@@ -110,6 +137,17 @@
boolean isTaskScheduleSupported();
/**
+ * Returns the supported task types for scheduling.
+ *
+ * <p>If task scheduling is not supported, this returns an empty array.
+ *
+ * <p>Otherwise, at least {@code TaskType.CUSTOM} must be supported.
+ *
+ * @return An array of supported task types.
+ */
+ TaskType[] getSupportedTaskTypesForScheduling();
+
+ /**
* Schedules a task to be executed later even when the vehicle is off.
*
* <p>If {@link isTaskScheduleSupported} returns {@code false}. This is no-op.
@@ -127,6 +165,8 @@
*
* <p>Must return {@code EX_ILLEGAL_ARGUMENT} if a pending schedule with the same
* {@code scheduleId} for this client exists.
+ *
+ * <p>Must return {@code EX_ILLEGAL_ARGUMENT} if the task type is not supported.
*/
void scheduleTask(in ScheduleInfo scheduleInfo);
@@ -161,5 +201,5 @@
*
* <p>The finished scheduled tasks will not be included.
*/
- List<ScheduleInfo> getAllScheduledTasks(String clientId);
+ List<ScheduleInfo> getAllPendingScheduledTasks(String clientId);
}
diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl
index 2cd7a5d..ee6f900 100644
--- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl
+++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl
@@ -22,7 +22,7 @@
@VintfStability
interface IRemoteTaskCallback {
/**
- * A callback that is called when a remote task is requested.
+ * A callback that is called when a custom type remote task is requested.
*
* The data is passed down from the remote server to the remote task client
* which is an Android application, and is not interpreted/parsed by the
diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
index cf1437b..40fba6f 100644
--- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
+++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl
@@ -16,6 +16,8 @@
package android.hardware.automotive.remoteaccess;
+import android.hardware.automotive.remoteaccess.TaskType;
+
@VintfStability
@JavaDerive(equals=true, toString=true)
parcelable ScheduleInfo {
@@ -31,8 +33,14 @@
*/
String scheduleId;
/**
+ * The type for the task.
+ */
+ TaskType taskType;
+ /**
* The opaque task data that will be sent back to the remote task client app when the task is
* executed. It is not interpreted/parsed by the Android system.
+ *
+ * <p>This is only used for {@code TaskType.CUSTOM}.
*/
byte[] taskData;
/**
diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl
new file mode 100644
index 0000000..761eb15
--- /dev/null
+++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.automotive.remoteaccess;
+
+@VintfStability
+@Backing(type="int")
+enum TaskType {
+ /**
+ * A custom task that is opaque to anyone other than the remote task client app.
+ *
+ * <p>The opaque task data in the {@code ScheduleInfo} will be sent back to the app when the
+ * task is to be executed.
+ */
+ CUSTOM = 0,
+ /**
+ * Enters the garage mode if allowed.
+ *
+ * <p>Make the Android system enters garage mode if vehicle is currently not in use and
+ * entering garage mode is allowed (e.g. battery level is high enough).
+ *
+ * <p>This is based on best-effort and it is not guaranteed.
+ *
+ * <p>If allowed, the external system should set {@code AP_POWER_BOOTUP_REASON} to
+ * {@code SYSTEM_ENTER_GARAGE_MODE} and then boot up (or resume) the head unit.
+ */
+ ENTER_GARAGE_MODE = 1,
+}
diff --git a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
index 9224ebc..7707ee6 100644
--- a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
+++ b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
@@ -75,8 +75,9 @@
return Status::OK;
}
- Status GetAllScheduledTasks(ClientContext* context, const GetAllScheduledTasksRequest& request,
- GetAllScheduledTasksResponse* response) {
+ Status GetAllPendingScheduledTasks(ClientContext* context,
+ const GetAllPendingScheduledTasksRequest& request,
+ GetAllPendingScheduledTasksResponse* response) {
return Status::OK;
}
@@ -165,17 +166,19 @@
return nullptr;
}
- ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>* AsyncGetAllScheduledTasksRaw(
+ ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*
+ AsyncGetAllPendingScheduledTasksRaw(
[[maybe_unused]] ClientContext* context,
- [[maybe_unused]] const GetAllScheduledTasksRequest& request,
+ [[maybe_unused]] const GetAllPendingScheduledTasksRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
- ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*
- PrepareAsyncGetAllScheduledTasksRaw([[maybe_unused]] ClientContext* context,
- [[maybe_unused]] const GetAllScheduledTasksRequest& request,
- [[maybe_unused]] CompletionQueue* c) {
+ ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*
+ PrepareAsyncGetAllPendingScheduledTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetAllPendingScheduledTasksRequest& request,
+ [[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
};
diff --git a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
index 1fc4037..6266de8 100644
--- a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
+++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
@@ -81,6 +81,9 @@
ndk::ScopedAStatus isTaskScheduleSupported(bool* out) override;
+ ndk::ScopedAStatus getSupportedTaskTypesForScheduling(
+ std::vector<aidl::android::hardware::automotive::remoteaccess::TaskType>* out) override;
+
ndk::ScopedAStatus scheduleTask(
const aidl::android::hardware::automotive::remoteaccess::ScheduleInfo& scheduleInfo)
override;
@@ -93,7 +96,7 @@
ndk::ScopedAStatus isTaskScheduled(const std::string& clientId, const std::string& scheduleId,
bool* out) override;
- ndk::ScopedAStatus getAllScheduledTasks(
+ ndk::ScopedAStatus getAllPendingScheduledTasks(
const std::string& clientId,
std::vector<aidl::android::hardware::automotive::remoteaccess::ScheduleInfo>* out)
override;
diff --git a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
index e061016..14ba0a5 100644
--- a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
+++ b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
@@ -99,7 +99,8 @@
*
* <p>The finished scheduled tasks will not be included.
*/
- rpc GetAllScheduledTasks(GetAllScheduledTasksRequest) returns (GetAllScheduledTasksResponse) {}
+ rpc GetAllPendingScheduledTasks(GetAllPendingScheduledTasksRequest)
+ returns (GetAllPendingScheduledTasksResponse) {}
}
message GetRemoteTasksRequest {}
@@ -154,10 +155,10 @@
bool isTaskScheduled = 1;
}
-message GetAllScheduledTasksRequest {
+message GetAllPendingScheduledTasksRequest {
string clientId = 1;
}
-message GetAllScheduledTasksResponse {
+message GetAllPendingScheduledTasksResponse {
repeated GrpcScheduleInfo allScheduledTasks = 1;
}
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
index 0944d86..2a7f209 100644
--- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -40,6 +40,7 @@
using ::aidl::android::hardware::automotive::remoteaccess::ApState;
using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo;
+using ::aidl::android::hardware::automotive::remoteaccess::TaskType;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::android::base::Error;
using ::android::base::ParseInt;
@@ -319,6 +320,13 @@
return ScopedAStatus::ok();
}
+ndk::ScopedAStatus RemoteAccessService::getSupportedTaskTypesForScheduling(
+ std::vector<TaskType>* out) {
+ // TODO(b/316233421): support ENTER_GARAGE_MODE type.
+ out->push_back(TaskType::CUSTOM);
+ return ScopedAStatus::ok();
+}
+
ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo) {
ClientContext context;
ScheduleTaskRequest request = {};
@@ -391,13 +399,13 @@
return ScopedAStatus::ok();
}
-ScopedAStatus RemoteAccessService::getAllScheduledTasks(const std::string& clientId,
- std::vector<ScheduleInfo>* out) {
+ScopedAStatus RemoteAccessService::getAllPendingScheduledTasks(const std::string& clientId,
+ std::vector<ScheduleInfo>* out) {
ClientContext context;
- GetAllScheduledTasksRequest request = {};
- GetAllScheduledTasksResponse response = {};
+ GetAllPendingScheduledTasksRequest request = {};
+ GetAllPendingScheduledTasksResponse response = {};
request.set_clientid(clientId);
- Status status = mGrpcStub->GetAllScheduledTasks(&context, request, &response);
+ Status status = mGrpcStub->GetAllPendingScheduledTasks(&context, request, &response);
if (!status.ok()) {
return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled");
}
diff --git a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
index c0038c2..a46a983 100644
--- a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
+++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
@@ -48,6 +48,7 @@
using ::aidl::android::hardware::automotive::remoteaccess::ApState;
using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo;
+using ::aidl::android::hardware::automotive::remoteaccess::TaskType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::grpc::ClientAsyncReaderInterface;
@@ -61,6 +62,7 @@
using ::ndk::ScopedAStatus;
using ::testing::_;
using ::testing::DoAll;
+using ::testing::ElementsAre;
using ::testing::Return;
using ::testing::SetArgPointee;
@@ -93,9 +95,9 @@
MOCK_METHOD(Status, IsTaskScheduled,
(ClientContext * context, const IsTaskScheduledRequest& request,
IsTaskScheduledResponse* response));
- MOCK_METHOD(Status, GetAllScheduledTasks,
- (ClientContext * context, const GetAllScheduledTasksRequest& request,
- GetAllScheduledTasksResponse* response));
+ MOCK_METHOD(Status, GetAllPendingScheduledTasks,
+ (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
+ GetAllPendingScheduledTasksResponse* response));
// Async methods which we do not care.
MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, AsyncGetRemoteTasksRaw,
(ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq,
@@ -139,13 +141,13 @@
PrepareAsyncIsTaskScheduledRaw,
(ClientContext * context, const IsTaskScheduledRequest& request,
CompletionQueue* cq));
- MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
- AsyncGetAllScheduledTasksRaw,
- (ClientContext * context, const GetAllScheduledTasksRequest& request,
+ MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*,
+ AsyncGetAllPendingScheduledTasksRaw,
+ (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
CompletionQueue* cq));
- MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
- PrepareAsyncGetAllScheduledTasksRaw,
- (ClientContext * context, const GetAllScheduledTasksRequest& request,
+ MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*,
+ PrepareAsyncGetAllPendingScheduledTasksRaw,
+ (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
CompletionQueue* cq));
};
@@ -434,6 +436,14 @@
EXPECT_TRUE(out);
}
+TEST_F(RemoteAccessServiceUnitTest, TestGetSupportedTaskTypesForScheduling) {
+ std::vector<TaskType> out;
+ ScopedAStatus status = getService()->getSupportedTaskTypesForScheduling(&out);
+
+ EXPECT_TRUE(status.isOk());
+ EXPECT_THAT(out, ElementsAre(TaskType::CUSTOM));
+}
+
TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask) {
ScheduleTaskRequest grpcRequest = {};
EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
@@ -563,13 +573,13 @@
EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId);
}
-TEST_F(RemoteAccessServiceUnitTest, testGetAllScheduledTasks) {
+TEST_F(RemoteAccessServiceUnitTest, testGetAllPendingScheduledTasks) {
std::vector<ScheduleInfo> result;
- GetAllScheduledTasksRequest grpcRequest = {};
- EXPECT_CALL(*getGrpcWakeupClientStub(), GetAllScheduledTasks)
+ GetAllPendingScheduledTasksRequest grpcRequest = {};
+ EXPECT_CALL(*getGrpcWakeupClientStub(), GetAllPendingScheduledTasks)
.WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
- const GetAllScheduledTasksRequest& request,
- GetAllScheduledTasksResponse* response) {
+ const GetAllPendingScheduledTasksRequest& request,
+ GetAllPendingScheduledTasksResponse* response) {
grpcRequest = request;
GrpcScheduleInfo* newInfo = response->add_allscheduledtasks();
newInfo->set_clientid(kTestClientId);
@@ -581,7 +591,7 @@
return Status();
});
- ScopedAStatus status = getService()->getAllScheduledTasks(kTestClientId, &result);
+ ScopedAStatus status = getService()->getAllPendingScheduledTasks(kTestClientId, &result);
ASSERT_TRUE(status.isOk());
EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
index 2aab904..a7f47c2 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -138,9 +138,9 @@
const IsTaskScheduledRequest* request,
IsTaskScheduledResponse* response) override;
- grpc::Status GetAllScheduledTasks(grpc::ServerContext* context,
- const GetAllScheduledTasksRequest* request,
- GetAllScheduledTasksResponse* response) override;
+ grpc::Status GetAllPendingScheduledTasks(
+ grpc::ServerContext* context, const GetAllPendingScheduledTasksRequest* request,
+ GetAllPendingScheduledTasksResponse* response) override;
/**
* Starts generating fake tasks for the specific client repeatedly.
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
index 1db991c..d223353 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -469,11 +469,11 @@
return Status::OK;
}
-Status TestWakeupClientServiceImpl::GetAllScheduledTasks(ServerContext* context,
- const GetAllScheduledTasksRequest* request,
- GetAllScheduledTasksResponse* response) {
+Status TestWakeupClientServiceImpl::GetAllPendingScheduledTasks(
+ ServerContext* context, const GetAllPendingScheduledTasksRequest* request,
+ GetAllPendingScheduledTasksResponse* response) {
const std::string& clientId = request->clientid();
- printf("GetAllScheduledTasks called with client Id: %s\n", clientId.c_str());
+ printf("GetAllPendingScheduledTasks called with client Id: %s\n", clientId.c_str());
response->clear_allscheduledtasks();
{
std::unique_lock lk(mLock);
diff --git a/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
index 960020d..63458ae 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
@@ -280,7 +280,7 @@
EXPECT_EQ(getRemoteTaskResponses().size(), 0);
}
-TEST_F(TestWakeupClientServiceImplUnitTest, TestGetAllScheduledTasks) {
+TEST_F(TestWakeupClientServiceImplUnitTest, TestGetAllPendingScheduledTasks) {
std::string scheduleId1 = "scheduleId1";
std::string scheduleId2 = "scheduleId2";
int64_t time1 = getNow();
@@ -296,19 +296,19 @@
ASSERT_TRUE(status.ok());
ClientContext context;
- GetAllScheduledTasksRequest request;
- GetAllScheduledTasksResponse response;
+ GetAllPendingScheduledTasksRequest request;
+ GetAllPendingScheduledTasksResponse response;
request.set_clientid("invalid client Id");
- status = getStub()->GetAllScheduledTasks(&context, request, &response);
+ status = getStub()->GetAllPendingScheduledTasks(&context, request, &response);
ASSERT_TRUE(status.ok());
EXPECT_EQ(response.allscheduledtasks_size(), 0);
ClientContext context2;
- GetAllScheduledTasksRequest request2;
- GetAllScheduledTasksResponse response2;
+ GetAllPendingScheduledTasksRequest request2;
+ GetAllPendingScheduledTasksResponse response2;
request2.set_clientid(kTestClientId);
- status = getStub()->GetAllScheduledTasks(&context2, request2, &response2);
+ status = getStub()->GetAllPendingScheduledTasks(&context2, request2, &response2);
ASSERT_TRUE(status.ok());
ASSERT_EQ(response2.allscheduledtasks_size(), 2);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
index c16b29a..03a9df5 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
@@ -30,7 +30,7 @@
std::unique_ptr<VehiclePropValue> createVehiclePropValue(
VehiclePropertyType type, size_t vecSize) {
- auto val = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
+ auto val = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
switch (type) {
case VehiclePropertyType::INT32: // fall through
case VehiclePropertyType::INT32_VEC: // fall through
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
index d6969e5..9a6b65d 100644
--- a/automotive/vehicle/OWNERS
+++ b/automotive/vehicle/OWNERS
@@ -1,2 +1,9 @@
ericjeong@google.com
shanyu@google.com
+
+# GRPC VHAL
+per-file aidl/impl/grpc/** = chenhaosjtuacm@google.com, egranata@google.com
+
+# Property definition
+per-file aidl_property/** = tylertrephan@google.com
+per-file aidl/generated_lib/** = tylertrephan@google.com
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
index 69f6190..14469b5 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
@@ -45,8 +45,8 @@
*
* This value indicates the resolution at which continuous property updates should be sent to
* the platform. For example, if resolution is 0.01, the subscribed property value should be
- * rounded to two decimal places. If the incoming resolution value is not an integer multiple of
- * 10, VHAL should return a StatusCode::INVALID_ARG.
+ * rounded to two decimal places. If the incoming resolution value is not an integer power of
+ * 10 (i.e. 10^-2, 10^-1, 10^2, etc.), VHAL should return a StatusCode::INVALID_ARG.
*/
float resolution = 0.0f;
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
index ef38432..15056e2 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
@@ -22,8 +22,7 @@
// clang-format off
-#ifndef android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
-#define android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
+#pragma once
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
@@ -68,9 +67,11 @@
{VehicleProperty::EV_CHARGE_PORT_CONNECTED, VehiclePropertyAccess::READ},
{VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyAccess::READ},
{VehicleProperty::RANGE_REMAINING, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyAccess::READ},
{VehicleProperty::TIRE_PRESSURE, VehiclePropertyAccess::READ},
{VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyAccess::READ},
{VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::IMPACT_DETECTED, VehiclePropertyAccess::READ},
{VehicleProperty::GEAR_SELECTION, VehiclePropertyAccess::READ},
{VehicleProperty::CURRENT_GEAR, VehiclePropertyAccess::READ},
{VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyAccess::READ},
@@ -83,6 +84,8 @@
{VehicleProperty::ABS_ACTIVE, VehiclePropertyAccess::READ},
{VehicleProperty::TRACTION_CONTROL_ACTIVE, VehiclePropertyAccess::READ},
{VehicleProperty::EV_STOPPING_MODE, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyAccess::READ},
{VehicleProperty::HVAC_FAN_SPEED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::HVAC_FAN_DIRECTION, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::HVAC_TEMPERATURE_CURRENT, VehiclePropertyAccess::READ},
@@ -120,6 +123,8 @@
{VehicleProperty::AP_POWER_BOOTUP_REASON, VehiclePropertyAccess::READ},
{VehicleProperty::DISPLAY_BRIGHTNESS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::PER_DISPLAY_BRIGHTNESS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::VALET_MODE_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::HEAD_UP_DISPLAY_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::HW_KEY_INPUT, VehiclePropertyAccess::READ},
{VehicleProperty::HW_KEY_INPUT_V2, VehiclePropertyAccess::READ},
{VehicleProperty::HW_MOTION_INPUT, VehiclePropertyAccess::READ},
@@ -169,11 +174,13 @@
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_EASY_ACCESS_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_AIRBAG_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, VehiclePropertyAccess::READ},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_WALK_IN_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED, VehiclePropertyAccess::READ},
{VehicleProperty::SEAT_OCCUPANCY, VehiclePropertyAccess::READ},
{VehicleProperty::WINDOW_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::WINDOW_MOVE, VehiclePropertyAccess::READ_WRITE},
@@ -192,6 +199,12 @@
{VehicleProperty::GLOVE_BOX_LOCKED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::VEHICLE_MAP_SERVICE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::LOCATION_CHARACTERIZATION, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_POSITION, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_ORIENTATION, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_FIELD_OF_VIEW, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_DETECTION_RANGE, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_SUPPORTED_RANGES, VehiclePropertyAccess::READ},
+ {VehicleProperty::ULTRASONICS_SENSOR_MEASURED_DISTANCE, VehiclePropertyAccess::READ},
{VehicleProperty::OBD2_LIVE_FRAME, VehiclePropertyAccess::READ},
{VehicleProperty::OBD2_FREEZE_FRAME, VehiclePropertyAccess::READ},
{VehicleProperty::OBD2_FREEZE_FRAME_INFO, VehiclePropertyAccess::READ},
@@ -282,6 +295,12 @@
{VehicleProperty::DRIVER_DISTRACTION_STATE, VehiclePropertyAccess::READ},
{VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::DRIVER_DISTRACTION_WARNING, VehiclePropertyAccess::READ},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, VehiclePropertyAccess::READ},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess::READ},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess::READ},
};
} // namespace vehicle
@@ -289,5 +308,3 @@
} // namespace hardware
} // namespace android
} // aidl
-
-#endif // android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
index 22f3e64..d3f97e3 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
@@ -22,8 +22,7 @@
// clang-format off
-#ifndef android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
-#define android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
+#pragma once
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
@@ -68,9 +67,11 @@
{VehicleProperty::EV_CHARGE_PORT_CONNECTED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyChangeMode::CONTINUOUS},
{VehicleProperty::RANGE_REMAINING, VehiclePropertyChangeMode::CONTINUOUS},
+ {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyChangeMode::CONTINUOUS},
{VehicleProperty::TIRE_PRESSURE, VehiclePropertyChangeMode::CONTINUOUS},
{VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyChangeMode::STATIC},
{VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::IMPACT_DETECTED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::GEAR_SELECTION, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::CURRENT_GEAR, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyChangeMode::ON_CHANGE},
@@ -83,6 +84,8 @@
{VehicleProperty::ABS_ACTIVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::TRACTION_CONTROL_ACTIVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_STOPPING_MODE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HVAC_FAN_SPEED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HVAC_FAN_DIRECTION, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HVAC_TEMPERATURE_CURRENT, VehiclePropertyChangeMode::ON_CHANGE},
@@ -120,6 +123,8 @@
{VehicleProperty::AP_POWER_BOOTUP_REASON, VehiclePropertyChangeMode::STATIC},
{VehicleProperty::DISPLAY_BRIGHTNESS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::PER_DISPLAY_BRIGHTNESS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::VALET_MODE_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::HEAD_UP_DISPLAY_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HW_KEY_INPUT, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HW_KEY_INPUT_V2, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::HW_MOTION_INPUT, VehiclePropertyChangeMode::ON_CHANGE},
@@ -169,11 +174,13 @@
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_AIRBAG_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_WALK_IN_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_OCCUPANCY, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::WINDOW_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::WINDOW_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
@@ -192,6 +199,12 @@
{VehicleProperty::GLOVE_BOX_LOCKED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::VEHICLE_MAP_SERVICE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::LOCATION_CHARACTERIZATION, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_POSITION, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_ORIENTATION, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_FIELD_OF_VIEW, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_DETECTION_RANGE, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_SUPPORTED_RANGES, VehiclePropertyChangeMode::STATIC},
+ {VehicleProperty::ULTRASONICS_SENSOR_MEASURED_DISTANCE, VehiclePropertyChangeMode::CONTINUOUS},
{VehicleProperty::OBD2_LIVE_FRAME, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::OBD2_FREEZE_FRAME, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::OBD2_FREEZE_FRAME_INFO, VehiclePropertyChangeMode::ON_CHANGE},
@@ -282,6 +295,12 @@
{VehicleProperty::DRIVER_DISTRACTION_STATE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::DRIVER_DISTRACTION_WARNING, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
};
} // namespace vehicle
@@ -289,5 +308,3 @@
} // namespace hardware
} // namespace android
} // aidl
-
-#endif // android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
new file mode 100644
index 0000000..70c914d
--- /dev/null
+++ b/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+/**
+ * DO NOT EDIT MANUALLY!!!
+ *
+ * Generated by tools/generate_annotation_enums.py.
+ */
+
+// clang-format off
+
+#pragma once
+
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
+
+#include <unordered_map>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+std::unordered_map<VehicleProperty, int32_t> VersionForVehicleProperty = {
+ {VehicleProperty::INFO_VIN, 2},
+ {VehicleProperty::INFO_MAKE, 2},
+ {VehicleProperty::INFO_MODEL, 2},
+ {VehicleProperty::INFO_MODEL_YEAR, 2},
+ {VehicleProperty::INFO_FUEL_CAPACITY, 2},
+ {VehicleProperty::INFO_FUEL_TYPE, 2},
+ {VehicleProperty::INFO_EV_BATTERY_CAPACITY, 2},
+ {VehicleProperty::INFO_EV_CONNECTOR_TYPE, 2},
+ {VehicleProperty::INFO_FUEL_DOOR_LOCATION, 2},
+ {VehicleProperty::INFO_EV_PORT_LOCATION, 2},
+ {VehicleProperty::INFO_DRIVER_SEAT, 2},
+ {VehicleProperty::INFO_EXTERIOR_DIMENSIONS, 2},
+ {VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS, 2},
+ {VehicleProperty::PERF_ODOMETER, 2},
+ {VehicleProperty::PERF_VEHICLE_SPEED, 2},
+ {VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY, 2},
+ {VehicleProperty::PERF_STEERING_ANGLE, 2},
+ {VehicleProperty::PERF_REAR_STEERING_ANGLE, 2},
+ {VehicleProperty::ENGINE_COOLANT_TEMP, 2},
+ {VehicleProperty::ENGINE_OIL_LEVEL, 2},
+ {VehicleProperty::ENGINE_OIL_TEMP, 2},
+ {VehicleProperty::ENGINE_RPM, 2},
+ {VehicleProperty::WHEEL_TICK, 2},
+ {VehicleProperty::FUEL_LEVEL, 2},
+ {VehicleProperty::FUEL_DOOR_OPEN, 2},
+ {VehicleProperty::EV_BATTERY_LEVEL, 2},
+ {VehicleProperty::EV_CURRENT_BATTERY_CAPACITY, 2},
+ {VehicleProperty::EV_CHARGE_PORT_OPEN, 2},
+ {VehicleProperty::EV_CHARGE_PORT_CONNECTED, 2},
+ {VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, 2},
+ {VehicleProperty::RANGE_REMAINING, 2},
+ {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, 3},
+ {VehicleProperty::TIRE_PRESSURE, 2},
+ {VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, 2},
+ {VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, 2},
+ {VehicleProperty::IMPACT_DETECTED, 3},
+ {VehicleProperty::GEAR_SELECTION, 2},
+ {VehicleProperty::CURRENT_GEAR, 2},
+ {VehicleProperty::PARKING_BRAKE_ON, 2},
+ {VehicleProperty::PARKING_BRAKE_AUTO_APPLY, 2},
+ {VehicleProperty::EV_BRAKE_REGENERATION_LEVEL, 2},
+ {VehicleProperty::FUEL_LEVEL_LOW, 2},
+ {VehicleProperty::NIGHT_MODE, 2},
+ {VehicleProperty::TURN_SIGNAL_STATE, 2},
+ {VehicleProperty::IGNITION_STATE, 2},
+ {VehicleProperty::ABS_ACTIVE, 2},
+ {VehicleProperty::TRACTION_CONTROL_ACTIVE, 2},
+ {VehicleProperty::EV_STOPPING_MODE, 2},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, 3},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 2},
+ {VehicleProperty::HVAC_FAN_SPEED, 2},
+ {VehicleProperty::HVAC_FAN_DIRECTION, 2},
+ {VehicleProperty::HVAC_TEMPERATURE_CURRENT, 2},
+ {VehicleProperty::HVAC_TEMPERATURE_SET, 2},
+ {VehicleProperty::HVAC_DEFROSTER, 2},
+ {VehicleProperty::HVAC_AC_ON, 2},
+ {VehicleProperty::HVAC_MAX_AC_ON, 2},
+ {VehicleProperty::HVAC_MAX_DEFROST_ON, 2},
+ {VehicleProperty::HVAC_RECIRC_ON, 2},
+ {VehicleProperty::HVAC_DUAL_ON, 2},
+ {VehicleProperty::HVAC_AUTO_ON, 2},
+ {VehicleProperty::HVAC_SEAT_TEMPERATURE, 2},
+ {VehicleProperty::HVAC_SIDE_MIRROR_HEAT, 2},
+ {VehicleProperty::HVAC_STEERING_WHEEL_HEAT, 2},
+ {VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS, 2},
+ {VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM, 2},
+ {VehicleProperty::HVAC_POWER_ON, 2},
+ {VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE, 2},
+ {VehicleProperty::HVAC_AUTO_RECIRC_ON, 2},
+ {VehicleProperty::HVAC_SEAT_VENTILATION, 2},
+ {VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON, 2},
+ {VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION, 2},
+ {VehicleProperty::DISTANCE_DISPLAY_UNITS, 2},
+ {VehicleProperty::FUEL_VOLUME_DISPLAY_UNITS, 2},
+ {VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS, 2},
+ {VehicleProperty::EV_BATTERY_DISPLAY_UNITS, 2},
+ {VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME, 2},
+ {VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS, 2},
+ {VehicleProperty::EXTERNAL_CAR_TIME, 2},
+ {VehicleProperty::ANDROID_EPOCH_TIME, 2},
+ {VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED, 2},
+ {VehicleProperty::ENV_OUTSIDE_TEMPERATURE, 2},
+ {VehicleProperty::AP_POWER_STATE_REQ, 2},
+ {VehicleProperty::AP_POWER_STATE_REPORT, 2},
+ {VehicleProperty::AP_POWER_BOOTUP_REASON, 2},
+ {VehicleProperty::DISPLAY_BRIGHTNESS, 2},
+ {VehicleProperty::PER_DISPLAY_BRIGHTNESS, 2},
+ {VehicleProperty::VALET_MODE_ENABLED, 3},
+ {VehicleProperty::HEAD_UP_DISPLAY_ENABLED, 3},
+ {VehicleProperty::HW_KEY_INPUT, 2},
+ {VehicleProperty::HW_KEY_INPUT_V2, 2},
+ {VehicleProperty::HW_MOTION_INPUT, 2},
+ {VehicleProperty::HW_ROTARY_INPUT, 2},
+ {VehicleProperty::HW_CUSTOM_INPUT, 2},
+ {VehicleProperty::DOOR_POS, 2},
+ {VehicleProperty::DOOR_MOVE, 2},
+ {VehicleProperty::DOOR_LOCK, 2},
+ {VehicleProperty::DOOR_CHILD_LOCK_ENABLED, 2},
+ {VehicleProperty::MIRROR_Z_POS, 2},
+ {VehicleProperty::MIRROR_Z_MOVE, 2},
+ {VehicleProperty::MIRROR_Y_POS, 2},
+ {VehicleProperty::MIRROR_Y_MOVE, 2},
+ {VehicleProperty::MIRROR_LOCK, 2},
+ {VehicleProperty::MIRROR_FOLD, 2},
+ {VehicleProperty::MIRROR_AUTO_FOLD_ENABLED, 2},
+ {VehicleProperty::MIRROR_AUTO_TILT_ENABLED, 2},
+ {VehicleProperty::SEAT_MEMORY_SELECT, 2},
+ {VehicleProperty::SEAT_MEMORY_SET, 2},
+ {VehicleProperty::SEAT_BELT_BUCKLED, 2},
+ {VehicleProperty::SEAT_BELT_HEIGHT_POS, 2},
+ {VehicleProperty::SEAT_BELT_HEIGHT_MOVE, 2},
+ {VehicleProperty::SEAT_FORE_AFT_POS, 2},
+ {VehicleProperty::SEAT_FORE_AFT_MOVE, 2},
+ {VehicleProperty::SEAT_BACKREST_ANGLE_1_POS, 2},
+ {VehicleProperty::SEAT_BACKREST_ANGLE_1_MOVE, 2},
+ {VehicleProperty::SEAT_BACKREST_ANGLE_2_POS, 2},
+ {VehicleProperty::SEAT_BACKREST_ANGLE_2_MOVE, 2},
+ {VehicleProperty::SEAT_HEIGHT_POS, 2},
+ {VehicleProperty::SEAT_HEIGHT_MOVE, 2},
+ {VehicleProperty::SEAT_DEPTH_POS, 2},
+ {VehicleProperty::SEAT_DEPTH_MOVE, 2},
+ {VehicleProperty::SEAT_TILT_POS, 2},
+ {VehicleProperty::SEAT_TILT_MOVE, 2},
+ {VehicleProperty::SEAT_LUMBAR_FORE_AFT_POS, 2},
+ {VehicleProperty::SEAT_LUMBAR_FORE_AFT_MOVE, 2},
+ {VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS, 2},
+ {VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE, 2},
+ {VehicleProperty::SEAT_HEADREST_HEIGHT_POS, 2},
+ {VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2, 2},
+ {VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE, 2},
+ {VehicleProperty::SEAT_HEADREST_ANGLE_POS, 2},
+ {VehicleProperty::SEAT_HEADREST_ANGLE_MOVE, 2},
+ {VehicleProperty::SEAT_HEADREST_FORE_AFT_POS, 2},
+ {VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE, 2},
+ {VehicleProperty::SEAT_FOOTWELL_LIGHTS_STATE, 2},
+ {VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH, 2},
+ {VehicleProperty::SEAT_EASY_ACCESS_ENABLED, 2},
+ {VehicleProperty::SEAT_AIRBAG_ENABLED, 3},
+ {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, 2},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, 2},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, 2},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, 2},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, 2},
+ {VehicleProperty::SEAT_WALK_IN_POS, 2},
+ {VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED, 3},
+ {VehicleProperty::SEAT_OCCUPANCY, 2},
+ {VehicleProperty::WINDOW_POS, 2},
+ {VehicleProperty::WINDOW_MOVE, 2},
+ {VehicleProperty::WINDOW_LOCK, 2},
+ {VehicleProperty::WINDSHIELD_WIPERS_PERIOD, 2},
+ {VehicleProperty::WINDSHIELD_WIPERS_STATE, 2},
+ {VehicleProperty::WINDSHIELD_WIPERS_SWITCH, 2},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_POS, 2},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_MOVE, 2},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_POS, 2},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE, 2},
+ {VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED, 2},
+ {VehicleProperty::STEERING_WHEEL_LOCKED, 2},
+ {VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED, 2},
+ {VehicleProperty::GLOVE_BOX_DOOR_POS, 2},
+ {VehicleProperty::GLOVE_BOX_LOCKED, 2},
+ {VehicleProperty::VEHICLE_MAP_SERVICE, 2},
+ {VehicleProperty::LOCATION_CHARACTERIZATION, 2},
+ {VehicleProperty::ULTRASONICS_SENSOR_POSITION, 3},
+ {VehicleProperty::ULTRASONICS_SENSOR_ORIENTATION, 3},
+ {VehicleProperty::ULTRASONICS_SENSOR_FIELD_OF_VIEW, 3},
+ {VehicleProperty::ULTRASONICS_SENSOR_DETECTION_RANGE, 3},
+ {VehicleProperty::ULTRASONICS_SENSOR_SUPPORTED_RANGES, 3},
+ {VehicleProperty::ULTRASONICS_SENSOR_MEASURED_DISTANCE, 3},
+ {VehicleProperty::OBD2_LIVE_FRAME, 2},
+ {VehicleProperty::OBD2_FREEZE_FRAME, 2},
+ {VehicleProperty::OBD2_FREEZE_FRAME_INFO, 2},
+ {VehicleProperty::OBD2_FREEZE_FRAME_CLEAR, 2},
+ {VehicleProperty::HEADLIGHTS_STATE, 2},
+ {VehicleProperty::HIGH_BEAM_LIGHTS_STATE, 2},
+ {VehicleProperty::FOG_LIGHTS_STATE, 2},
+ {VehicleProperty::HAZARD_LIGHTS_STATE, 2},
+ {VehicleProperty::HEADLIGHTS_SWITCH, 2},
+ {VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH, 2},
+ {VehicleProperty::FOG_LIGHTS_SWITCH, 2},
+ {VehicleProperty::HAZARD_LIGHTS_SWITCH, 2},
+ {VehicleProperty::CABIN_LIGHTS_STATE, 2},
+ {VehicleProperty::CABIN_LIGHTS_SWITCH, 2},
+ {VehicleProperty::READING_LIGHTS_STATE, 2},
+ {VehicleProperty::READING_LIGHTS_SWITCH, 2},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_STATE, 2},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH, 2},
+ {VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION, 2},
+ {VehicleProperty::DISABLED_OPTIONAL_FEATURES, 2},
+ {VehicleProperty::INITIAL_USER_INFO, 2},
+ {VehicleProperty::SWITCH_USER, 2},
+ {VehicleProperty::CREATE_USER, 2},
+ {VehicleProperty::REMOVE_USER, 2},
+ {VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 2},
+ {VehicleProperty::EVS_SERVICE_REQUEST, 2},
+ {VehicleProperty::POWER_POLICY_REQ, 2},
+ {VehicleProperty::POWER_POLICY_GROUP_REQ, 2},
+ {VehicleProperty::CURRENT_POWER_POLICY, 2},
+ {VehicleProperty::WATCHDOG_ALIVE, 2},
+ {VehicleProperty::WATCHDOG_TERMINATED_PROCESS, 2},
+ {VehicleProperty::VHAL_HEARTBEAT, 2},
+ {VehicleProperty::CLUSTER_SWITCH_UI, 2},
+ {VehicleProperty::CLUSTER_DISPLAY_STATE, 2},
+ {VehicleProperty::CLUSTER_REPORT_STATE, 2},
+ {VehicleProperty::CLUSTER_REQUEST_DISPLAY, 2},
+ {VehicleProperty::CLUSTER_NAVIGATION_STATE, 2},
+ {VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE, 2},
+ {VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS, 2},
+ {VehicleProperty::FRONT_FOG_LIGHTS_STATE, 2},
+ {VehicleProperty::FRONT_FOG_LIGHTS_SWITCH, 2},
+ {VehicleProperty::REAR_FOG_LIGHTS_STATE, 2},
+ {VehicleProperty::REAR_FOG_LIGHTS_SWITCH, 2},
+ {VehicleProperty::EV_CHARGE_CURRENT_DRAW_LIMIT, 2},
+ {VehicleProperty::EV_CHARGE_PERCENT_LIMIT, 2},
+ {VehicleProperty::EV_CHARGE_STATE, 2},
+ {VehicleProperty::EV_CHARGE_SWITCH, 2},
+ {VehicleProperty::EV_CHARGE_TIME_REMAINING, 2},
+ {VehicleProperty::EV_REGENERATIVE_BRAKING_STATE, 2},
+ {VehicleProperty::TRAILER_PRESENT, 2},
+ {VehicleProperty::VEHICLE_CURB_WEIGHT, 2},
+ {VehicleProperty::GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT, 2},
+ {VehicleProperty::SUPPORTED_PROPERTY_IDS, 2},
+ {VehicleProperty::SHUTDOWN_REQUEST, 2},
+ {VehicleProperty::VEHICLE_IN_USE, 2},
+ {VehicleProperty::CLUSTER_HEARTBEAT, 3},
+ {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, 3},
+ {VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 2},
+ {VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE, 2},
+ {VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED, 2},
+ {VehicleProperty::FORWARD_COLLISION_WARNING_STATE, 2},
+ {VehicleProperty::BLIND_SPOT_WARNING_ENABLED, 2},
+ {VehicleProperty::BLIND_SPOT_WARNING_STATE, 2},
+ {VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED, 2},
+ {VehicleProperty::LANE_DEPARTURE_WARNING_STATE, 2},
+ {VehicleProperty::LANE_KEEP_ASSIST_ENABLED, 2},
+ {VehicleProperty::LANE_KEEP_ASSIST_STATE, 2},
+ {VehicleProperty::LANE_CENTERING_ASSIST_ENABLED, 2},
+ {VehicleProperty::LANE_CENTERING_ASSIST_COMMAND, 2},
+ {VehicleProperty::LANE_CENTERING_ASSIST_STATE, 2},
+ {VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED, 2},
+ {VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE, 2},
+ {VehicleProperty::CRUISE_CONTROL_ENABLED, 2},
+ {VehicleProperty::CRUISE_CONTROL_TYPE, 2},
+ {VehicleProperty::CRUISE_CONTROL_STATE, 2},
+ {VehicleProperty::CRUISE_CONTROL_COMMAND, 2},
+ {VehicleProperty::CRUISE_CONTROL_TARGET_SPEED, 2},
+ {VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP, 2},
+ {VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE, 2},
+ {VehicleProperty::HANDS_ON_DETECTION_ENABLED, 2},
+ {VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE, 2},
+ {VehicleProperty::HANDS_ON_DETECTION_WARNING, 2},
+ {VehicleProperty::DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED, 3},
+ {VehicleProperty::DRIVER_DROWSINESS_ATTENTION_STATE, 3},
+ {VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED, 3},
+ {VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING, 3},
+ {VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED, 3},
+ {VehicleProperty::DRIVER_DISTRACTION_STATE, 3},
+ {VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, 2},
+ {VehicleProperty::DRIVER_DISTRACTION_WARNING, 3},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED, 3},
+ {VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, 3},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED, 3},
+ {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, 3},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 3},
+ {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, 3},
+};
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
index acadf7d..e55f4dc 100644
--- a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
@@ -60,9 +60,11 @@
Map.entry(VehicleProperty.EV_CHARGE_PORT_CONNECTED, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.RANGE_REMAINING, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.TIRE_PRESSURE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.IMPACT_DETECTED, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.GEAR_SELECTION, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyAccess.READ),
@@ -75,6 +77,8 @@
Map.entry(VehicleProperty.ABS_ACTIVE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.TRACTION_CONTROL_ACTIVE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.EV_STOPPING_MODE, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.HVAC_FAN_SPEED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.HVAC_TEMPERATURE_CURRENT, VehiclePropertyAccess.READ),
@@ -112,6 +116,8 @@
Map.entry(VehicleProperty.AP_POWER_BOOTUP_REASON, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.DISPLAY_BRIGHTNESS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.PER_DISPLAY_BRIGHTNESS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.VALET_MODE_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.HEAD_UP_DISPLAY_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.HW_KEY_INPUT, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.HW_KEY_INPUT_V2, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.HW_MOTION_INPUT, VehiclePropertyAccess.READ),
@@ -161,11 +167,13 @@
Map.entry(VehicleProperty.SEAT_FOOTWELL_LIGHTS_SWITCH, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_EASY_ACCESS_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_AIRBAG_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_AIRBAGS_DEPLOYED, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_WALK_IN_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_BELT_PRETENSIONER_DEPLOYED, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.SEAT_OCCUPANCY, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.WINDOW_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.WINDOW_MOVE, VehiclePropertyAccess.READ_WRITE),
@@ -184,6 +192,12 @@
Map.entry(VehicleProperty.GLOVE_BOX_LOCKED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.VEHICLE_MAP_SERVICE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.LOCATION_CHARACTERIZATION, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_POSITION, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_ORIENTATION, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_FIELD_OF_VIEW, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_DETECTION_RANGE, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_SUPPORTED_RANGES, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_MEASURED_DISTANCE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.OBD2_LIVE_FRAME, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME_INFO, VehiclePropertyAccess.READ),
@@ -273,7 +287,13 @@
Map.entry(VehicleProperty.DRIVER_DISTRACTION_SYSTEM_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.DRIVER_DISTRACTION_STATE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING_ENABLED, VehiclePropertyAccess.READ_WRITE),
- Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, VehiclePropertyAccess.READ)
+ Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.LOW_SPEED_COLLISION_WARNING_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.LOW_SPEED_COLLISION_WARNING_STATE, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess.READ)
);
}
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
index dfdb85b..e351a3f 100644
--- a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
@@ -60,9 +60,11 @@
Map.entry(VehicleProperty.EV_CHARGE_PORT_CONNECTED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyChangeMode.CONTINUOUS),
Map.entry(VehicleProperty.RANGE_REMAINING, VehiclePropertyChangeMode.CONTINUOUS),
+ Map.entry(VehicleProperty.EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyChangeMode.CONTINUOUS),
Map.entry(VehicleProperty.TIRE_PRESSURE, VehiclePropertyChangeMode.CONTINUOUS),
Map.entry(VehicleProperty.CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyChangeMode.STATIC),
Map.entry(VehicleProperty.ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.IMPACT_DETECTED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.GEAR_SELECTION, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyChangeMode.ON_CHANGE),
@@ -75,6 +77,8 @@
Map.entry(VehicleProperty.ABS_ACTIVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.TRACTION_CONTROL_ACTIVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_STOPPING_MODE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HVAC_FAN_SPEED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HVAC_TEMPERATURE_CURRENT, VehiclePropertyChangeMode.ON_CHANGE),
@@ -112,6 +116,8 @@
Map.entry(VehicleProperty.AP_POWER_BOOTUP_REASON, VehiclePropertyChangeMode.STATIC),
Map.entry(VehicleProperty.DISPLAY_BRIGHTNESS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.PER_DISPLAY_BRIGHTNESS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.VALET_MODE_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.HEAD_UP_DISPLAY_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HW_KEY_INPUT, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HW_KEY_INPUT_V2, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.HW_MOTION_INPUT, VehiclePropertyChangeMode.ON_CHANGE),
@@ -161,11 +167,13 @@
Map.entry(VehicleProperty.SEAT_FOOTWELL_LIGHTS_SWITCH, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_AIRBAG_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_AIRBAGS_DEPLOYED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_WALK_IN_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_BELT_PRETENSIONER_DEPLOYED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_OCCUPANCY, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.WINDOW_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.WINDOW_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
@@ -184,6 +192,12 @@
Map.entry(VehicleProperty.GLOVE_BOX_LOCKED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.VEHICLE_MAP_SERVICE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.LOCATION_CHARACTERIZATION, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_POSITION, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_ORIENTATION, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_FIELD_OF_VIEW, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_DETECTION_RANGE, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_SUPPORTED_RANGES, VehiclePropertyChangeMode.STATIC),
+ Map.entry(VehicleProperty.ULTRASONICS_SENSOR_MEASURED_DISTANCE, VehiclePropertyChangeMode.CONTINUOUS),
Map.entry(VehicleProperty.OBD2_LIVE_FRAME, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME_INFO, VehiclePropertyChangeMode.ON_CHANGE),
@@ -273,7 +287,13 @@
Map.entry(VehicleProperty.DRIVER_DISTRACTION_SYSTEM_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.DRIVER_DISTRACTION_STATE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
- Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, VehiclePropertyChangeMode.ON_CHANGE)
+ Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.LOW_SPEED_COLLISION_WARNING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.LOW_SPEED_COLLISION_WARNING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode.ON_CHANGE)
);
}
diff --git a/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java
index 3c2cfa2e..4b8060f 100644
--- a/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java
@@ -37,11 +37,13 @@
Map.entry(VehicleProperty.INFO_DRIVER_SEAT, List.of(VehicleAreaSeat.class)),
Map.entry(VehicleProperty.INFO_MULTI_EV_PORT_LOCATIONS, List.of(PortLocationType.class)),
Map.entry(VehicleProperty.ENGINE_OIL_LEVEL, List.of(VehicleOilLevel.class)),
+ Map.entry(VehicleProperty.IMPACT_DETECTED, List.of(ImpactSensorLocation.class)),
Map.entry(VehicleProperty.GEAR_SELECTION, List.of(VehicleGear.class)),
Map.entry(VehicleProperty.CURRENT_GEAR, List.of(VehicleGear.class)),
Map.entry(VehicleProperty.TURN_SIGNAL_STATE, List.of(VehicleTurnSignal.class)),
Map.entry(VehicleProperty.IGNITION_STATE, List.of(VehicleIgnitionState.class)),
Map.entry(VehicleProperty.EV_STOPPING_MODE, List.of(EvStoppingMode.class)),
+ Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, List.of(ElectronicStabilityControlState.class, ErrorState.class)),
Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, List.of(VehicleHvacFanDirection.class)),
Map.entry(VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS, List.of(VehicleUnit.class)),
Map.entry(VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE, List.of(VehicleHvacFanDirection.class)),
@@ -53,6 +55,7 @@
Map.entry(VehicleProperty.HW_CUSTOM_INPUT, List.of(CustomInputType.class)),
Map.entry(VehicleProperty.SEAT_FOOTWELL_LIGHTS_STATE, List.of(VehicleLightState.class)),
Map.entry(VehicleProperty.SEAT_FOOTWELL_LIGHTS_SWITCH, List.of(VehicleLightSwitch.class)),
+ Map.entry(VehicleProperty.SEAT_AIRBAGS_DEPLOYED, List.of(VehicleAirbagLocation.class)),
Map.entry(VehicleProperty.SEAT_OCCUPANCY, List.of(VehicleSeatOccupancyState.class)),
Map.entry(VehicleProperty.WINDSHIELD_WIPERS_STATE, List.of(WindshieldWipersState.class)),
Map.entry(VehicleProperty.WINDSHIELD_WIPERS_SWITCH, List.of(WindshieldWipersSwitch.class)),
@@ -98,7 +101,10 @@
Map.entry(VehicleProperty.DRIVER_DROWSINESS_ATTENTION_STATE, List.of(DriverDrowsinessAttentionState.class, ErrorState.class)),
Map.entry(VehicleProperty.DRIVER_DROWSINESS_ATTENTION_WARNING, List.of(DriverDrowsinessAttentionWarning.class, ErrorState.class)),
Map.entry(VehicleProperty.DRIVER_DISTRACTION_STATE, List.of(DriverDistractionState.class, ErrorState.class)),
- Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, List.of(DriverDistractionWarning.class, ErrorState.class))
+ Map.entry(VehicleProperty.DRIVER_DISTRACTION_WARNING, List.of(DriverDistractionWarning.class, ErrorState.class)),
+ Map.entry(VehicleProperty.LOW_SPEED_COLLISION_WARNING_STATE, List.of(LowSpeedCollisionWarningState.class, ErrorState.class)),
+ Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, List.of(CrossTrafficMonitoringWarningState.class, ErrorState.class)),
+ Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, List.of(LowSpeedAutomaticEmergencyBrakingState.class, ErrorState.class))
);
}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
index 26bda22..3e6e7dc 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -38,6 +38,7 @@
using ::aidl::android::hardware::automotive::vehicle::AutomaticEmergencyBrakingState;
using ::aidl::android::hardware::automotive::vehicle::BlindSpotWarningState;
using ::aidl::android::hardware::automotive::vehicle::ChangeModeForVehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::CrossTrafficMonitoringWarningState;
using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
using ::aidl::android::hardware::automotive::vehicle::CruiseControlState;
using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
@@ -45,6 +46,7 @@
using ::aidl::android::hardware::automotive::vehicle::DriverDistractionWarning;
using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionState;
using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionWarning;
+using ::aidl::android::hardware::automotive::vehicle::ElectronicStabilityControlState;
using ::aidl::android::hardware::automotive::vehicle::EmergencyLaneKeepAssistState;
using ::aidl::android::hardware::automotive::vehicle::ErrorState;
using ::aidl::android::hardware::automotive::vehicle::EvConnectorType;
@@ -55,12 +57,16 @@
using ::aidl::android::hardware::automotive::vehicle::GsrComplianceRequirementType;
using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionDriverState;
using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionWarning;
+using ::aidl::android::hardware::automotive::vehicle::ImpactSensorLocation;
using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistCommand;
using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistState;
using ::aidl::android::hardware::automotive::vehicle::LaneDepartureWarningState;
using ::aidl::android::hardware::automotive::vehicle::LaneKeepAssistState;
using ::aidl::android::hardware::automotive::vehicle::LocationCharacterization;
+using ::aidl::android::hardware::automotive::vehicle::LowSpeedAutomaticEmergencyBrakingState;
+using ::aidl::android::hardware::automotive::vehicle::LowSpeedCollisionWarningState;
using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAirbagLocation;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
@@ -247,6 +253,10 @@
std::make_unique<ConstantParser<WindshieldWipersSwitch>>();
mConstantParsersByType["VehicleAutonomousState"] =
std::make_unique<ConstantParser<VehicleAutonomousState>>();
+ mConstantParsersByType["VehicleAirbagLocation"] =
+ std::make_unique<ConstantParser<VehicleAirbagLocation>>();
+ mConstantParsersByType["ImpactSensorLocation"] =
+ std::make_unique<ConstantParser<ImpactSensorLocation>>();
mConstantParsersByType["EmergencyLaneKeepAssistState"] =
std::make_unique<ConstantParser<EmergencyLaneKeepAssistState>>();
mConstantParsersByType["CruiseControlType"] =
@@ -282,6 +292,14 @@
std::make_unique<ConstantParser<LaneCenteringAssistCommand>>();
mConstantParsersByType["LaneCenteringAssistState"] =
std::make_unique<ConstantParser<LaneCenteringAssistState>>();
+ mConstantParsersByType["LowSpeedCollisionWarningState"] =
+ std::make_unique<ConstantParser<LowSpeedCollisionWarningState>>();
+ mConstantParsersByType["ElectronicStabilityControlState"] =
+ std::make_unique<ConstantParser<ElectronicStabilityControlState>>();
+ mConstantParsersByType["CrossTrafficMonitoringWarningState"] =
+ std::make_unique<ConstantParser<CrossTrafficMonitoringWarningState>>();
+ mConstantParsersByType["LowSpeedAutomaticEmergencyBrakingState"] =
+ std::make_unique<ConstantParser<LowSpeedAutomaticEmergencyBrakingState>>();
mConstantParsersByType["Constants"] = std::make_unique<LocalVariableParser>();
#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
mConstantParsersByType["TestVendorProperty"] =
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 88541d8..56d8b4b 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -1328,6 +1328,75 @@
]
},
{
+ "property": "VehicleProperty::SEAT_AIRBAGS_DEPLOYED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "supportedEnumValues": [
+ "VehicleAirbagLocation::FRONT",
+ "VehicleAirbagLocation::KNEE",
+ "VehicleAirbagLocation::LEFT_SIDE",
+ "VehicleAirbagLocation::RIGHT_SIDE",
+ "VehicleAirbagLocation::CURTAIN"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "supportedEnumValues": [
+ "VehicleAirbagLocation::FRONT",
+ "VehicleAirbagLocation::KNEE",
+ "VehicleAirbagLocation::LEFT_SIDE",
+ "VehicleAirbagLocation::RIGHT_SIDE",
+ "VehicleAirbagLocation::CURTAIN"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "supportedEnumValues": [
+ "VehicleAirbagLocation::FRONT",
+ "VehicleAirbagLocation::CURTAIN"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "supportedEnumValues": [
+ "VehicleAirbagLocation::FRONT",
+ "VehicleAirbagLocation::CURTAIN"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::SEAT_OCCUPANCY",
"defaultValue": {
"int32Values": [
@@ -1560,6 +1629,16 @@
"minSampleRate": 1.0
},
{
+ "property": "VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE",
+ "defaultValue": {
+ "floatValues": [
+ 25.0
+ ]
+ },
+ "maxSampleRate": 2.0,
+ "minSampleRate": 1.0
+ },
+ {
"property": "VehicleProperty::TIRE_PRESSURE",
"defaultValue": {
"floatValues": [
@@ -2368,9 +2447,9 @@
160,
280,
5,
- 600,
- 840,
- 10
+ 608,
+ 824,
+ 9
]
},
{
@@ -2380,7 +2459,7 @@
66.19999694824219,
"VehicleUnit::FAHRENHEIT",
19.0,
- 66.0
+ 66.2
]
}
},
@@ -2503,6 +2582,27 @@
}
},
{
+ "property": "VehicleProperty::IMPACT_DETECTED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ImpactSensorLocation::FRONT",
+ "ImpactSensorLocation::FRONT_LEFT_DOOR_SIDE",
+ "ImpactSensorLocation::FRONT_RIGHT_DOOR_SIDE",
+ "ImpactSensorLocation::REAR_LEFT_DOOR_SIDE",
+ "ImpactSensorLocation::REAR_RIGHT_DOOR_SIDE",
+ "ImpactSensorLocation::REAR"
+ ]
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::DOOR_LOCK",
"areas": [
{
@@ -3111,6 +3211,27 @@
]
},
{
+ "property": "VehicleProperty::VALET_MODE_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HEAD_UP_DISPLAY_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::OBD2_LIVE_FRAME",
"configArray": [
0,
@@ -3991,6 +4112,128 @@
]
}
]
+ },
+ {
+ "property": "VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "LowSpeedCollisionWarningState::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "LowSpeedCollisionWarningState::NO_WARNING",
+ "LowSpeedCollisionWarningState::WARNING"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "ElectronicStabilityControlState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "ElectronicStabilityControlState::ENABLED",
+ "ElectronicStabilityControlState::ACTIVATED"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "CrossTrafficMonitoringWarningState::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "CrossTrafficMonitoringWarningState::NO_WARNING",
+ "CrossTrafficMonitoringWarningState::WARNING_FRONT_LEFT",
+ "CrossTrafficMonitoringWarningState::WARNING_FRONT_RIGHT",
+ "CrossTrafficMonitoringWarningState::WARNING_FRONT_BOTH",
+ "CrossTrafficMonitoringWarningState::WARNING_REAR_LEFT",
+ "CrossTrafficMonitoringWarningState::WARNING_REAR_RIGHT",
+ "CrossTrafficMonitoringWarningState::WARNING_REAR_BOTH"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "LowSpeedAutomaticEmergencyBrakingState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "LowSpeedAutomaticEmergencyBrakingState::ENABLED",
+ "LowSpeedAutomaticEmergencyBrakingState::ACTIVATED",
+ "LowSpeedAutomaticEmergencyBrakingState::USER_OVERRIDE"
+ ]
+ }
+ ]
}
]
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 7b62b2d..385f616 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -225,6 +225,34 @@
toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING),
},
},
+ // LSCW
+ {
+ toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE),
+ },
+ },
+ // ESC
+ {
+ toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE),
+ },
+ },
+ // CTMW
+ {
+ toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED),
+ {
+ toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE),
+ },
+ },
+ // LSAEB
+ {
+ toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ {
+ toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE),
+ },
+ },
};
} // namespace
@@ -468,7 +496,7 @@
int increment) {
requestedTemp = std::max(requestedTemp, minTemp);
requestedTemp = std::min(requestedTemp, maxTemp);
- int numIncrements = (requestedTemp - minTemp) / increment;
+ int numIncrements = std::round((requestedTemp - minTemp) / static_cast<float>(increment));
return numIncrements;
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 3b6f717..6d2efd5 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -1593,6 +1593,116 @@
},
},
SetSpecialValueTestCase{
+ .name = "set_low_speed_collision_warning_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_low_speed_collision_warning_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ LOW_SPEED_COLLISION_WARNING_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_electronic_stability_control_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_electronic_stability_control_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ ELECTRONIC_STABILITY_CONTROL_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
.name = "set_shutdown_request",
.valuesToSet =
{
@@ -2149,6 +2259,20 @@
toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
},
},
+ // LSCW
+ {
+ toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE),
+ },
+ },
+ // ESC
+ {
+ toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE),
+ },
+ },
};
// First subscribe to all the properties that we will change.
diff --git a/automotive/vehicle/aidl/impl/grpc/OWNERS b/automotive/vehicle/aidl/impl/grpc/OWNERS
deleted file mode 100644
index 7a96f23..0000000
--- a/automotive/vehicle/aidl/impl/grpc/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-shanyu@google.com
-chenhaosjtuacm@google.com
-egranata@google.com
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 42cd993..0c8ebbd 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -19,6 +19,7 @@
#include <aidl/android/hardware/automotive/vehicle/AutomaticEmergencyBrakingState.h>
#include <aidl/android/hardware/automotive/vehicle/BlindSpotWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.h>
#include <aidl/android/hardware/automotive/vehicle/CruiseControlCommand.h>
#include <aidl/android/hardware/automotive/vehicle/CruiseControlState.h>
#include <aidl/android/hardware/automotive/vehicle/CruiseControlType.h>
@@ -28,6 +29,7 @@
#include <aidl/android/hardware/automotive/vehicle/DriverDistractionWarning.h>
#include <aidl/android/hardware/automotive/vehicle/DriverDrowsinessAttentionState.h>
#include <aidl/android/hardware/automotive/vehicle/DriverDrowsinessAttentionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/ElectronicStabilityControlState.h>
#include <aidl/android/hardware/automotive/vehicle/EmergencyLaneKeepAssistState.h>
#include <aidl/android/hardware/automotive/vehicle/ErrorState.h>
#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
@@ -42,11 +44,14 @@
#include <aidl/android/hardware/automotive/vehicle/GsrComplianceRequirementType.h>
#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionDriverState.h>
#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/ImpactSensorLocation.h>
#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistCommand.h>
#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistState.h>
#include <aidl/android/hardware/automotive/vehicle/LaneDepartureWarningState.h>
#include <aidl/android/hardware/automotive/vehicle/LaneKeepAssistState.h>
#include <aidl/android/hardware/automotive/vehicle/LocationCharacterization.h>
+#include <aidl/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.h>
+#include <aidl/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
@@ -59,6 +64,7 @@
#include <aidl/android/hardware/automotive/vehicle/SetValueResults.h>
#include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
#include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAirbagLocation.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
index 6e812d1..501ce40 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -235,7 +235,7 @@
bool isDisposable(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
size_t vectorSize) const {
- return vectorSize > mMaxRecyclableVectorSize || isComplexType(type);
+ return vectorSize == 0 || vectorSize > mMaxRecyclableVectorSize || isComplexType(type);
}
RecyclableType obtainDisposable(
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 546421e..523cac5 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -124,7 +124,6 @@
break; // Valid, but nothing to do.
default:
ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
- val.reset(nullptr);
}
return val;
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
index 2480a73..7e02767 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -55,13 +55,6 @@
int propId = src.prop;
VehiclePropertyType type = getPropType(propId);
size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
- if (vectorSize == 0 && !isComplexType(type)) {
- ALOGW("empty vehicle prop value, contains no content");
- ALOGW("empty vehicle prop value, contains no content, prop: %d", propId);
- // Return any empty VehiclePropValue.
- return RecyclableType{new VehiclePropValue{}, mDisposableDeleter};
- }
-
auto dest = obtain(type, vectorSize);
dest->prop = propId;
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
index a62532c..6226e89 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
@@ -267,6 +267,20 @@
ASSERT_EQ(*gotValue, prop);
}
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt32ValuesEmptyArray) {
+ VehiclePropValue prop{
+ // INT32_VEC property.
+ .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+ .areaId = 2,
+ .timestamp = 3,
+ .value = {.int32Values = {}},
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
TEST_F(VehicleObjectPoolTest, testObtainCopyInt64Values) {
VehiclePropValue prop{
// INT64_VEC property.
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index c29345f..20bba7f 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -61,6 +61,7 @@
],
header_libs: [
"IVehicleHardware",
+ "IVehicleGeneratedHeaders",
],
shared_libs: [
"libbinder_ndk",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index f7a71b4..250b30c 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -49,6 +49,9 @@
explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
+ // Test-only
+ DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware, int32_t testInterfaceVersion);
+
~DefaultVehicleHal();
ndk::ScopedAStatus getAllPropConfigs(
@@ -153,6 +156,8 @@
mPropertyChangeEventsBatchingConsumer;
// Only set once during initialization.
std::chrono::nanoseconds mEventBatchingWindow;
+ // Only used for testing.
+ int32_t mTestInterfaceVersion = 0;
std::mutex mLock;
std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -227,6 +232,8 @@
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
batchedEvents);
+ int32_t getVhalInterfaceVersion();
+
// Puts the property change events into a queue so that they can handled in batch.
static void batchPropertyChangeEvent(
const std::weak_ptr<ConcurrentQueue<
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 76d2f31..cc5edcc 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -22,6 +22,7 @@
#include <LargeParcelableBase.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
+#include <VersionForVehicleProperty.h>
#include <android-base/result.h>
#include <android-base/stringprintf.h>
@@ -61,6 +62,7 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty;
using ::android::automotive::car_binder_lib::LargeParcelableBase;
using ::android::base::Error;
using ::android::base::expected;
@@ -94,8 +96,13 @@
} // namespace
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
+ : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0){};
+
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
+ int32_t testInterfaceVersion)
: mVehicleHardware(std::move(vehicleHardware)),
- mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
+ mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
+ mTestInterfaceVersion(testInterfaceVersion) {
if (!getAllPropConfigsFromHardware()) {
return;
}
@@ -312,13 +319,46 @@
mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
}
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() {
+ if (mTestInterfaceVersion != 0) {
+ return mTestInterfaceVersion;
+ }
+ int32_t myVersion = 0;
+ getInterfaceVersion(&myVersion);
+ return myVersion;
+}
+
bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
auto configs = mVehicleHardware->getAllPropertyConfigs();
+ std::vector<VehiclePropConfig> filteredConfigs;
+ int32_t myVersion = getVhalInterfaceVersion();
for (auto& config : configs) {
+ if (!isSystemProp(config.prop)) {
+ filteredConfigs.push_back(std::move(config));
+ continue;
+ }
+ VehicleProperty property = static_cast<VehicleProperty>(config.prop);
+ std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
+ auto it = VersionForVehicleProperty.find(property);
+ if (it == VersionForVehicleProperty.end()) {
+ ALOGE("The property: %s is not a supported system property, ignore",
+ propertyName.c_str());
+ continue;
+ }
+ int requiredVersion = it->second;
+ if (myVersion < requiredVersion) {
+ ALOGE("The property: %s is not supported for current client VHAL version, "
+ "require %d, current version: %d, ignore",
+ propertyName.c_str(), requiredVersion, myVersion);
+ continue;
+ }
+ filteredConfigs.push_back(std::move(config));
+ }
+ for (auto& config : filteredConfigs) {
mConfigsByPropId[config.prop] = config;
}
VehiclePropConfigs vehiclePropConfigs;
- vehiclePropConfigs.payloads = std::move(configs);
+ vehiclePropConfigs.payloads = std::move(filteredConfigs);
auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
if (!result.ok()) {
ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
@@ -413,9 +453,9 @@
.status = getErrorCode(result),
.prop = {},
});
- } else {
- hardwareRequests.push_back(request);
+ continue;
}
+ hardwareRequests.push_back(request);
}
// The set of request Ids that we would send to hardware.
@@ -816,6 +856,7 @@
if (!result.ok()) {
return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
}
+
const VehiclePropConfig* config = result.value();
const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
@@ -900,6 +941,7 @@
dprintf(fd, "Vehicle HAL State: \n");
{
std::scoped_lock<std::mutex> lockGuard(mLock);
+ dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index a63cb84..bb82108 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -79,36 +79,37 @@
using ::ndk::SpAIBinder;
using ::testing::ContainsRegex;
+using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
using ::testing::WhenSortedBy;
constexpr int32_t INVALID_PROP_ID = 0;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t READ_ONLY_PROP = 10006 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_CONTINUOUS_PROP_NO_VUR = 10008 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_NONE_ACCESS_PROP = 10009 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_NONE_ACCESS_PROP = 10010 + 0x10000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t READ_ONLY_PROP = 10006 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_CONTINUOUS_PROP_NO_VUR = 10008 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_NONE_ACCESS_PROP = 10009 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_NONE_ACCESS_PROP = 10010 + 0x20000000 + 0x03000000 + 0x00400000;
int32_t testInt32VecProp(size_t i) {
- // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
- return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000;
+ // VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ return static_cast<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
}
std::string toString(const std::vector<SubscribeOptions>& options) {
@@ -556,10 +557,10 @@
TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
auto testConfigs = std::vector<VehiclePropConfig>({
VehiclePropConfig{
- .prop = 1,
+ .prop = testInt32VecProp(1),
},
VehiclePropConfig{
- .prop = 2,
+ .prop = testInt32VecProp(2),
},
});
@@ -580,7 +581,7 @@
// 5000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
for (size_t i = 0; i < 5000; i++) {
testConfigs.push_back(VehiclePropConfig{
- .prop = static_cast<int32_t>(i),
+ .prop = testInt32VecProp(i),
});
}
@@ -600,13 +601,42 @@
ASSERT_EQ(result.value().getObject()->payloads, testConfigs);
}
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsFilterOutUnsupportedPropIdsForThisVersion) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ // This is supported from V2.
+ VehiclePropConfig{
+ .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ },
+ // This is supported from V3
+ VehiclePropConfig{
+ .prop = toInt(VehicleProperty::ULTRASONICS_SENSOR_POSITION),
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware),
+ /* testInterfaceVersion= */ 2);
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ VehiclePropConfigs output;
+ auto status = client->getAllPropConfigs(&output);
+
+ ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
+ ASSERT_THAT(output.payloads, ElementsAre(VehiclePropConfig{
+ .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ }));
+}
+
TEST_F(DefaultVehicleHalTest, testGetPropConfigs) {
+ int32_t propId1 = testInt32VecProp(1);
+ int32_t propId2 = testInt32VecProp(2);
auto testConfigs = std::vector<VehiclePropConfig>({
VehiclePropConfig{
- .prop = 1,
+ .prop = propId1,
},
VehiclePropConfig{
- .prop = 2,
+ .prop = propId2,
},
});
@@ -616,7 +646,7 @@
std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
VehiclePropConfigs output;
- auto status = client->getPropConfigs(std::vector<int32_t>({1, 2}), &output);
+ auto status = client->getPropConfigs(std::vector<int32_t>({propId1, propId2}), &output);
ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
ASSERT_EQ(output.payloads, testConfigs);
@@ -625,10 +655,10 @@
TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
auto testConfigs = std::vector<VehiclePropConfig>({
VehiclePropConfig{
- .prop = 1,
+ .prop = testInt32VecProp(1),
},
VehiclePropConfig{
- .prop = 2,
+ .prop = testInt32VecProp(2),
},
});
@@ -638,7 +668,9 @@
std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
VehiclePropConfigs output;
- auto status = client->getPropConfigs(std::vector<int32_t>({1, 2, 3}), &output);
+ auto status = client->getPropConfigs(
+ std::vector<int32_t>({testInt32VecProp(1), testInt32VecProp(2), testInt32VecProp(3)}),
+ &output);
ASSERT_FALSE(status.isOk()) << "getPropConfigs must fail with invalid prop ID";
ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
diff --git a/automotive/vehicle/aidl_property/OWNERS b/automotive/vehicle/aidl_property/OWNERS
deleted file mode 100644
index 73e45ca..0000000
--- a/automotive/vehicle/aidl_property/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-tylertrephan@google.com
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl
new file mode 100644
index 0000000..90e2d8d
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum CrossTrafficMonitoringWarningState {
+ OTHER = 0,
+ NO_WARNING = 1,
+ WARNING_FRONT_LEFT = 2,
+ WARNING_FRONT_RIGHT = 3,
+ WARNING_FRONT_BOTH = 4,
+ WARNING_REAR_LEFT = 5,
+ WARNING_REAR_RIGHT = 6,
+ WARNING_REAR_BOTH = 7,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl
new file mode 100644
index 0000000..b061a25
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum ElectronicStabilityControlState {
+ OTHER = 0,
+ ENABLED = 1,
+ ACTIVATED = 2,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl
new file mode 100644
index 0000000..6b75d8c
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum ImpactSensorLocation {
+ OTHER = 0x01,
+ FRONT = 0x02,
+ FRONT_LEFT_DOOR_SIDE = 0x04,
+ FRONT_RIGHT_DOOR_SIDE = 0x08,
+ REAR_LEFT_DOOR_SIDE = 0x10,
+ REAR_RIGHT_DOOR_SIDE = 0x20,
+ REAR = 0x40,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl
new file mode 100644
index 0000000..70014e1
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum LowSpeedAutomaticEmergencyBrakingState {
+ OTHER = 0,
+ ENABLED = 1,
+ ACTIVATED = 2,
+ USER_OVERRIDE = 3,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl
new file mode 100644
index 0000000..6f6338b
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum LowSpeedCollisionWarningState {
+ OTHER = 0,
+ NO_WARNING = 1,
+ WARNING = 2,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl
new file mode 100644
index 0000000..9b966d7
--- /dev/null
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAirbagLocation {
+ OTHER = 0x01,
+ FRONT = 0x02,
+ KNEE = 0x04,
+ LEFT_SIDE = 0x08,
+ RIGHT_SIDE = 0x10,
+ CURTAIN = 0x20,
+}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
index 9720aca..55af2ab 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
@@ -37,4 +37,5 @@
USER_POWER_ON = 0,
SYSTEM_USER_DETECTION = 1,
SYSTEM_REMOTE_ACCESS = 2,
+ SYSTEM_ENTER_GARAGE_MODE = 3,
}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
index 3fde1c7..8b345b2 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
@@ -40,4 +40,5 @@
SLEEP_IMMEDIATELY = 4,
HIBERNATE_IMMEDIATELY = 5,
CAN_HIBERNATE = 6,
+ EMERGENCY_SHUTDOWN = 7,
}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleArea.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleArea.aidl
index db867f4..b63003a 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleArea.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleArea.aidl
@@ -40,5 +40,6 @@
SEAT = 0x05000000,
DOOR = 0x06000000,
WHEEL = 0x07000000,
+ VENDOR = 0x08000000,
MASK = 0x0f000000,
}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 84df774..52876d1 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -66,9 +66,11 @@
EV_CHARGE_PORT_CONNECTED = (((0x030B + 0x10000000) + 0x01000000) + 0x00200000) /* 287310603 */,
EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = (((0x030C + 0x10000000) + 0x01000000) + 0x00600000) /* 291504908 */,
RANGE_REMAINING = (((0x0308 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504904 */,
+ EV_BATTERY_AVERAGE_TEMPERATURE = (((0x030E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504910 */,
TIRE_PRESSURE = (((0x0309 + 0x10000000) + 0x07000000) + 0x00600000) /* 392168201 */,
CRITICALLY_LOW_TIRE_PRESSURE = (((0x030A + 0x10000000) + 0x07000000) + 0x00600000) /* 392168202 */,
ENGINE_IDLE_AUTO_STOP_ENABLED = (((0x0320 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310624 */,
+ IMPACT_DETECTED = (((0x0330 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289407792 */,
GEAR_SELECTION = (((0x0400 + 0x10000000) + 0x01000000) + 0x00400000) /* 289408000 */,
CURRENT_GEAR = (((0x0401 + 0x10000000) + 0x01000000) + 0x00400000) /* 289408001 */,
PARKING_BRAKE_ON = (((0x0402 + 0x10000000) + 0x01000000) + 0x00200000) /* 287310850 */,
@@ -81,6 +83,8 @@
ABS_ACTIVE = (((0x040A + 0x10000000) + 0x01000000) + 0x00200000) /* 287310858 */,
TRACTION_CONTROL_ACTIVE = (((0x040B + 0x10000000) + 0x01000000) + 0x00200000) /* 287310859 */,
EV_STOPPING_MODE = (((0x040D + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408013 */,
+ ELECTRONIC_STABILITY_CONTROL_ENABLED = (((0x040E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310862 */,
+ ELECTRONIC_STABILITY_CONTROL_STATE = (((0x040F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408015 */,
HVAC_FAN_SPEED = (((0x0500 + 0x10000000) + 0x05000000) + 0x00400000) /* 356517120 */,
HVAC_FAN_DIRECTION = (((0x0501 + 0x10000000) + 0x05000000) + 0x00400000) /* 356517121 */,
HVAC_TEMPERATURE_CURRENT = (((0x0502 + 0x10000000) + 0x05000000) + 0x00600000) /* 358614274 */,
@@ -118,6 +122,8 @@
AP_POWER_BOOTUP_REASON = (((0x0A02 + 0x10000000) + 0x01000000) + 0x00400000) /* 289409538 */,
DISPLAY_BRIGHTNESS = (((0x0A03 + 0x10000000) + 0x01000000) + 0x00400000) /* 289409539 */,
PER_DISPLAY_BRIGHTNESS = (((0x0A04 + 0x10000000) + 0x01000000) + 0x00410000) /* 289475076 */,
+ VALET_MODE_ENABLED = (((0x0A05 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287312389 */,
+ HEAD_UP_DISPLAY_ENABLED = (((0x0A06 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 354421254 */,
HW_KEY_INPUT = (((0x0A10 + 0x10000000) + 0x01000000) + 0x00410000) /* 289475088 */,
HW_KEY_INPUT_V2 = (((0x0A11 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.MIXED) /* 367004177 */,
HW_MOTION_INPUT = (((0x0A12 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.MIXED) /* 367004178 */,
@@ -167,11 +173,13 @@
SEAT_FOOTWELL_LIGHTS_SWITCH = (((0x0B9C + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518812 */,
SEAT_EASY_ACCESS_ENABLED = (((0x0B9D + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 354421661 */,
SEAT_AIRBAG_ENABLED = (((0x0B9E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 354421662 */,
+ SEAT_AIRBAGS_DEPLOYED = (((0x0BA5 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518821 */,
SEAT_CUSHION_SIDE_SUPPORT_POS = (((0x0B9F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518815 */,
SEAT_CUSHION_SIDE_SUPPORT_MOVE = (((0x0BA0 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518816 */,
SEAT_LUMBAR_VERTICAL_POS = (((0x0BA1 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518817 */,
SEAT_LUMBAR_VERTICAL_MOVE = (((0x0BA2 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518818 */,
SEAT_WALK_IN_POS = (((0x0BA3 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 356518819 */,
+ SEAT_BELT_PRETENSIONER_DEPLOYED = (((0x0BA6 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 354421670 */,
SEAT_OCCUPANCY = (((0x0BB0 + 0x10000000) + 0x05000000) + 0x00400000) /* 356518832 */,
WINDOW_POS = (((0x0BC0 + 0x10000000) + 0x03000000) + 0x00400000) /* 322964416 */,
WINDOW_MOVE = (((0x0BC1 + 0x10000000) + 0x03000000) + 0x00400000) /* 322964417 */,
@@ -190,6 +198,12 @@
GLOVE_BOX_LOCKED = (((0x0BF1 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.SEAT) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 354421745 */,
VEHICLE_MAP_SERVICE = (((0x0C00 + 0x10000000) + 0x01000000) + 0x00e00000) /* 299895808 */,
LOCATION_CHARACTERIZATION = (((0x0C10 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289410064 */,
+ ULTRASONICS_SENSOR_POSITION = (((0x0C20 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916128 */,
+ ULTRASONICS_SENSOR_ORIENTATION = (((0x0C21 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916129 */,
+ ULTRASONICS_SENSOR_FIELD_OF_VIEW = (((0x0C22 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916130 */,
+ ULTRASONICS_SENSOR_DETECTION_RANGE = (((0x0C23 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916131 */,
+ ULTRASONICS_SENSOR_SUPPORTED_RANGES = (((0x0C24 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916132 */,
+ ULTRASONICS_SENSOR_MEASURED_DISTANCE = (((0x0C25 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.VENDOR) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 406916133 */,
OBD2_LIVE_FRAME = (((0x0D00 + 0x10000000) + 0x01000000) + 0x00e00000) /* 299896064 */,
OBD2_FREEZE_FRAME = (((0x0D01 + 0x10000000) + 0x01000000) + 0x00e00000) /* 299896065 */,
OBD2_FREEZE_FRAME_INFO = (((0x0D02 + 0x10000000) + 0x01000000) + 0x00e00000) /* 299896066 */,
@@ -280,4 +294,10 @@
DRIVER_DISTRACTION_STATE = (((0x101E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289411102 */,
DRIVER_DISTRACTION_WARNING_ENABLED = (((0x101F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313951 */,
DRIVER_DISTRACTION_WARNING = (((0x1020 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289411104 */,
+ LOW_SPEED_COLLISION_WARNING_ENABLED = (((0x1021 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313953 */,
+ LOW_SPEED_COLLISION_WARNING_STATE = (((0x1022 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289411106 */,
+ CROSS_TRAFFIC_MONITORING_ENABLED = (((0x1023 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313955 */,
+ CROSS_TRAFFIC_MONITORING_WARNING_STATE = (((0x1024 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289411108 */,
+ LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED = (((0x1025 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313957 */,
+ LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE = (((0x1026 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289411110 */,
}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl
new file mode 100644
index 0000000..05be65d
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the state of Cross Traffic Monitoring Warning system.
+ */
+@VintfStability
+@Backing(type="int")
+enum CrossTrafficMonitoringWarningState {
+
+ /**
+ * This state is used as an alternative to any CrossTrafficMonitoringWarningState value that is
+ * not defined in the platform. Ideally, implementations of
+ * VehicleProperty#CROSS_TRAFFIC_MONITORING_WARNING_STATE should not use this state. The
+ * framework can use this field to remain backwards compatible if
+ * CrossTrafficMonitoringWarningState is extended to include additional states.
+ */
+ OTHER = 0,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and monitoring safety, but no potential collision
+ * is detected.
+ */
+ NO_WARNING = 1,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from the driver's left side in front of the vehicle.
+ */
+ WARNING_FRONT_LEFT = 2,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from the driver's right side in front of the vehicle.
+ */
+ WARNING_FRONT_RIGHT = 3,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from both the driver's left side and the driver's right side in front
+ * of the vehicle.
+ */
+ WARNING_FRONT_BOTH = 4,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from the driver's left side behind the vehicle.
+ */
+ WARNING_REAR_LEFT = 5,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from the driver's right side behind the vehicle.
+ */
+ WARNING_REAR_RIGHT = 6,
+ /**
+ * Cross Traffic Monitoring Warning is enabled and is actively warning the user of incoming
+ * moving objects coming from the driver's left side and the driver's right side behind the
+ * vehicle.
+ */
+ WARNING_REAR_BOTH = 7,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl
new file mode 100644
index 0000000..006bbf2
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ElectronicStabilityControlState.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the state of Electronic Stability Control (ESC).
+ */
+@VintfStability
+@Backing(type="int")
+enum ElectronicStabilityControlState {
+
+ /**
+ * This state is used as an alternative to any ElectronicStabilityControlState value that is not
+ * defined in the platform. Ideally, implementations of
+ * VehicleProperty#ELECTRONIC_STABILITY_CONTROL_STATE should not use this state. The framework
+ * can use this field to remain backwards compatible if ElectronicStabilityControlState is
+ * extended to include additional states.
+ */
+ OTHER = 0,
+ /**
+ * ESC is enabled and monitoring safety, but is not actively controlling the tires to prevent
+ * the car from skidding.
+ */
+ ENABLED = 1,
+ /**
+ * ESC is enabled and is actively controlling the tires to prevent the car from skidding.
+ */
+ ACTIVATED = 2,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl
new file mode 100644
index 0000000..0fc1a50
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/ImpactSensorLocation.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the various impact sensor locations on the car.
+ */
+@VintfStability
+@Backing(type="int")
+enum ImpactSensorLocation {
+ /**
+ * Other impact sensor location. Ideally this should never be used.
+ */
+ OTHER = 0x01,
+ /**
+ * Frontal impact sensor. Used for the sensor that detects head-on impact.
+ */
+ FRONT = 0x02,
+ /**
+ * Front-left door side impact sensor. Used for the sensor that detects collisions from the
+ * side, in particular on the front-left door.
+ */
+ FRONT_LEFT_DOOR_SIDE = 0x04,
+ /**
+ * Front-right door side impact sensor. Used for the sensor that detects collisions from the
+ * side, in particular on the front-right door.
+ */
+ FRONT_RIGHT_DOOR_SIDE = 0x08,
+ /**
+ * Rear-left door side impact sensor. Used for the sensor that detects collisions from the
+ * side, in particular on the rear-left door.
+ */
+ REAR_LEFT_DOOR_SIDE = 0x10,
+ /**
+ * Rear-right door side impact sensor. Used for the sensor that detects collisions from the
+ * side, in particular on the rear-right door.
+ */
+ REAR_RIGHT_DOOR_SIDE = 0x20,
+ /**
+ * Rear impact sensor. Used for the sensor that detects collisions from the rear.
+ */
+ REAR = 0x40,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl
new file mode 100644
index 0000000..978da25
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the state of Low Speed Automatic Emergency Braking.
+ */
+@VintfStability
+@Backing(type="int")
+enum LowSpeedAutomaticEmergencyBrakingState {
+
+ /**
+ * This state is used as an alternative to any LowSpeedAutomaticEmergencyBrakingState value that
+ * is not defined in the platform. Ideally, implementations of
+ * VehicleProperty#LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE should not use this state. The
+ * framework can use this field to remain backwards compatible if
+ * LowSpeedAutomaticEmergencyBrakingState is extended to include additional states.
+ */
+ OTHER = 0,
+ /**
+ * Low Speed Automatic Emergency Braking is enabled and monitoring safety, but brakes are not
+ * activated.
+ */
+ ENABLED = 1,
+ /**
+ * Low Speed Automatic Emergency Braking is enabled and currently has the brakes applied for the
+ * vehicle.
+ */
+ ACTIVATED = 2,
+ /**
+ * Many Low Speed Automatic Emergency Braking implementations allow the driver to override Low
+ * Speed Automatic Emergency Braking. This means that the car has determined it should brake,
+ * but a user decides to take over and do something else. This is often done for safety reasons
+ * and to ensure that the driver can always take control of the vehicle. This state should be
+ * set when the user is actively overriding the low speed automatic emergency braking system.
+ */
+ USER_OVERRIDE = 3,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl
new file mode 100644
index 0000000..028a2d9
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the state of Low Speed Collision Warning State.
+ */
+@VintfStability
+@Backing(type="int")
+enum LowSpeedCollisionWarningState {
+
+ /**
+ * This state is used as an alternative to any LowSpeedCollisionWarningState value that is not
+ * defined in the platform. Ideally, implementations of
+ * VehicleProperty#LOW_SPEED_COLLISION_WARNING_STATE should not use this state. The framework
+ * can use this field to remain backwards compatible if LowSpeedCollisionWarningState is
+ * extended to include additional states.
+ */
+ OTHER = 0,
+ /**
+ * Low Speed Collision Warning is enabled and monitoring for potential collision, but no
+ * potential collision is detected.
+ */
+ NO_WARNING = 1,
+ /**
+ * Low Speed Collision Warning is enabled, detects a potential collision, and is actively
+ * warning the user.
+ */
+ WARNING = 2,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl
new file mode 100644
index 0000000..e4c43f7
--- /dev/null
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAirbagLocation.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.automotive.vehicle;
+
+/**
+ * Used to enumerate the various airbag locations per seat.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleAirbagLocation {
+ /**
+ * This state is used as an alternative to any VehicleAirbagLocation value that is not defined
+ * in the platform. Ideally, implementations of VehicleProperty::SEAT_AIRBAGS_DEPLOYED should
+ * not use this state. The framework can use this field to remain backwards compatible if
+ * VehicleAirbagLocation is extended to include additional states.
+ */
+ OTHER = 0x01,
+ /**
+ * Front airbags. This enum is for the airbags that protect the seated person from the front,
+ * particularly the seated person's torso.
+ */
+ FRONT = 0x02,
+ /**
+ * Knee airbags. This enum is for the airbags that protect the seated person's knees.
+ */
+ KNEE = 0x04,
+ /**
+ * Left side airbags. This enum is for the side airbags that protect the left side of the seated
+ * person.
+ */
+ LEFT_SIDE = 0x08,
+ /**
+ * Right side airbags. This enum is for the side airbags that protect the right side of the
+ * seated person.
+ */
+ RIGHT_SIDE = 0x10,
+ /**
+ * Curtain airbags. This enum is for the airbags lined above the windows of the vehicle.
+ */
+ CURTAIN = 0x20,
+}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
index e325b38..8c8c2da 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
@@ -34,7 +34,24 @@
SYSTEM_USER_DETECTION = 1,
/**
* Automatic power on to execute a remote task. This is triggered by
- * receiving a wakeup message from TCU wakeup client.
+ * receiving a wakeup message from an external system in the vehicle.
*/
SYSTEM_REMOTE_ACCESS = 2,
+ /**
+ * Automatic power on to enter garage mode. This is triggered by
+ * receiving a wakeup message from an external system in the vehicle.
+ *
+ * Note that this does not necessarily mean Android will enter
+ * the garage mode since user may enter the vehicle after this is set.
+ * The system will only enter garage mode if VEHICLE_IN_USE is not true
+ * upon check.
+ *
+ * To consider the Time-Of-Check-Time-Of-Use issue, there is a slight chance
+ * that the vehicle become in-use after car service does the VEHICLE_IN_USE
+ * check. The external power controller must also check whether the vehicle
+ * is in use upon receiving the SHUTDOWN_REQUEST, before sending out
+ * SHUTDOWN_PREPARE, to make sure the system does not enter garage mode or
+ * shutdown if the vehicle is currently in use.
+ */
+ SYSTEM_ENTER_GARAGE_MODE = 3,
}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
index a863d14..966ff65 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
@@ -20,29 +20,41 @@
@Backing(type="int")
enum VehicleApPowerStateShutdownParam {
/**
- * AP must shutdown immediately. Postponing is not allowed.
+ * AP must shutdown without Garage mode. Postponing is not allowed.
+ * If AP need to shutdown as soon as possible, EMERGENCY_SHUTDOWN shall be used.
*/
SHUTDOWN_IMMEDIATELY = 1,
/**
* AP can enter deep sleep instead of shutting down completely.
+ * AP can postpone entering deep sleep to run Garage mode.
*/
CAN_SLEEP = 2,
/**
- * AP can only shutdown with postponing allowed.
+ * AP can only shutdown.
+ * AP can postpone shutdown to run Garage mode.
*/
SHUTDOWN_ONLY = 3,
/**
- * AP may enter deep sleep, but must either sleep or shut down immediately.
+ * AP can enter deep sleep, without Garage mode.
* Postponing is not allowed.
+ * Depending on the actual implementation, it may shut down immediately
*/
SLEEP_IMMEDIATELY = 4,
/**
- * AP must hibernate (suspend to disk) immediately. Postponing is not allowed.
- * Depending on the actual implementation, it may shut down immediately
+ * AP can hibernate (suspend to disk) without Garage mode.
+ * Postponing is not allowed.
+ * Depending on the actual implementation, it may shut down immediately.
*/
HIBERNATE_IMMEDIATELY = 5,
/**
* AP can enter hibernation (suspend to disk) instead of shutting down completely.
+ * AP can postpone hibernation to run Garage mode.
*/
CAN_HIBERNATE = 6,
+ /**
+ * AP must shutdown (gracefully) without a delay. AP cannot run Garage mode.
+ * This type must be used only in critical situations when AP must shutdown as soon as possible.
+ * CarService will only notify listeners, but will not wait for completion reports.
+ */
+ EMERGENCY_SHUTDOWN = 7,
}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleArea.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleArea.aidl
index 6f7f783..259b231 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleArea.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleArea.aidl
@@ -49,6 +49,11 @@
DOOR = 0x06000000,
/** WHEEL maps to enum VehicleAreaWheel */
WHEEL = 0x07000000,
+ /**
+ * A property with the VENDOR vehicle area contains area IDs that are vendor defined. Each area
+ * ID within this area type must be unique with no overlapping bits set.
+ */
+ VENDOR = 0x08000000,
MASK = 0x0f000000,
}
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 1827c89..026c040 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -52,6 +52,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_VIN = 0x0100 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -60,6 +61,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_MAKE = 0x0101 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -68,6 +70,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_MODEL = 0x0102 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -77,6 +80,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:YEAR
+ * @version 2
*/
INFO_MODEL_YEAR = 0x0103 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -86,6 +90,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLILITER
+ * @version 2
*/
INFO_FUEL_CAPACITY = 0x0104 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -105,6 +110,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum FuelType
+ * @version 2
*/
INFO_FUEL_TYPE = 0x0105 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -119,6 +125,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:WH
+ * @version 2
*/
INFO_EV_BATTERY_CAPACITY = 0x0106 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -128,6 +135,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @data_enum EvConnectorType
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_EV_CONNECTOR_TYPE = 0x0107 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -137,6 +145,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @data_enum PortLocationType
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_FUEL_DOOR_LOCATION = 0x0108 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -146,6 +155,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum PortLocationType
+ * @version 2
*/
INFO_EV_PORT_LOCATION = 0x0109 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -156,6 +166,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @data_enum VehicleAreaSeat
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
INFO_DRIVER_SEAT = 0x010A + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -174,6 +185,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLIMETER
+ * @version 2
*/
INFO_EXTERIOR_DIMENSIONS = 0x010B + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -189,6 +201,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum PortLocationType
+ * @version 2
*/
INFO_MULTI_EV_PORT_LOCATIONS = 0x010C + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -198,6 +211,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:KILOMETER
+ * @version 2
*/
PERF_ODOMETER = 0x0204 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -213,6 +227,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:METER_PER_SEC
+ * @version 2
*/
PERF_VEHICLE_SPEED = 0x0207 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -225,6 +240,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:METER_PER_SEC
+ * @version 2
*/
PERF_VEHICLE_SPEED_DISPLAY = 0x0208 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -236,6 +252,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:DEGREES
+ * @version 2
*/
PERF_STEERING_ANGLE = 0x0209 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -247,6 +264,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:DEGREES
+ * @version 2
*/
PERF_REAR_STEERING_ANGLE = 0x0210 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -256,6 +274,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:CELSIUS
+ * @version 2
*/
ENGINE_COOLANT_TEMP = 0x0301 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -265,6 +284,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleOilLevel
+ * @version 2
*/
ENGINE_OIL_LEVEL = 0x0303 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -274,6 +294,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:CELSIUS
+ * @version 2
*/
ENGINE_OIL_TEMP = 0x0304 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -283,6 +304,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:RPM
+ * @version 2
*/
ENGINE_RPM = 0x0305 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -323,6 +345,7 @@
*
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
WHEEL_TICK = 0x0306 + 0x10000000 + 0x01000000
+ 0x00510000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64_VEC
@@ -334,6 +357,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLILITER
+ * @version 2
*/
FUEL_LEVEL = 0x0307 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -346,6 +370,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
FUEL_DOOR_OPEN = 0x0308 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -359,6 +384,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:WH
+ * @version 2
*/
EV_BATTERY_LEVEL = 0x0309 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -373,6 +399,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:WH
+ * @version 2
*/
EV_CURRENT_BATTERY_CAPACITY =
0x030D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT,
@@ -385,6 +412,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EV_CHARGE_PORT_OPEN = 0x030A + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -393,6 +421,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EV_CHARGE_PORT_CONNECTED = 0x030B + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -405,6 +434,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MW
+ * @version 2
*/
EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 0x030C + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -423,10 +453,25 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:METER
+ * @version 2
*/
RANGE_REMAINING = 0x0308 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
/**
+ * EV battery average temperature
+ *
+ * Exposes the temperature of the battery in an EV. If multiple batteries exist in the EV, or
+ * multiple temperature sensors exist, this property should be set to the mean or a meaningful
+ * weighted average that best represents the overall temperature of the battery system.
+ *
+ * @change_mode VehiclePropertyChangeMode.CONTINUOUS
+ * @access VehiclePropertyAccess.READ
+ * @unit VehicleUnit:CELSIUS
+ * @version 3
+ */
+ EV_BATTERY_AVERAGE_TEMPERATURE =
+ 0x030E + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT,
+ /**
* Tire pressure
*
* Each tires is identified by its areaConfig.areaId config and their
@@ -450,6 +495,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:KILOPASCAL
+ * @version 2
*/
TIRE_PRESSURE = 0x0309 + 0x10000000 + 0x07000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
@@ -465,6 +511,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:KILOPASCAL
+ * @version 2
*/
CRITICALLY_LOW_TIRE_PRESSURE = 0x030A + 0x10000000 + 0x07000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
@@ -480,10 +527,28 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
ENGINE_IDLE_AUTO_STOP_ENABLED =
0x0320 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
/**
+ * Impact detected.
+ *
+ * Bit flag property to relay information on whether an impact has occurred on a particular side
+ * of the vehicle as described through the ImpactSensorLocation enum. As a bit flag property,
+ * this property can be set to multiple ORed together values of the enum when necessary.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
+ * unless all bit flags of ImpactSensorLocation are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum ImpactSensorLocation
+ * @version 3
+ */
+ IMPACT_DETECTED =
+ 0x0330 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
* Currently selected gear
*
* This is the gear selected by the user.
@@ -500,6 +565,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleGear
+ * @version 2
*/
GEAR_SELECTION = 0x0400 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -519,6 +585,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleGear
+ * @version 2
*/
CURRENT_GEAR = 0x0401 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -530,6 +597,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
PARKING_BRAKE_ON = 0x0402 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -547,6 +615,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
PARKING_BRAKE_AUTO_APPLY = 0x0403 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -565,6 +634,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EV_BRAKE_REGENERATION_LEVEL =
0x040C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -583,6 +653,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
FUEL_LEVEL_LOW = 0x0405 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -595,6 +666,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
NIGHT_MODE = 0x0407 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -604,6 +676,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleTurnSignal
+ * @version 2
*/
TURN_SIGNAL_STATE = 0x0408 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -613,6 +686,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleIgnitionState
+ * @version 2
*/
IGNITION_STATE = 0x0409 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -625,6 +699,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
ABS_ACTIVE = 0x040A + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -637,6 +712,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
TRACTION_CONTROL_ACTIVE = 0x040B + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -655,10 +731,52 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum EvStoppingMode
+ * @version 2
*/
EV_STOPPING_MODE =
0x040D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
/**
+ * Enable or disable Electronic Stability Control (ESC).
+ *
+ * Set true to enable ESC and false to disable ESC. When ESC is enabled, a system in the vehicle
+ * should be controlling the tires during instances with high risk of skidding to actively
+ * prevent the same from happening.
+ *
+ * In general, ELECTRONIC_STABILITY_CONTROL_ENABLED should always return true or false. If the
+ * feature is not available due to some temporary state, such as the vehicle speed being too
+ * high, that information must be conveyed through the ErrorState values in the
+ * ELECTRONIC_STABILITY_CONTROL_STATE property.
+ *
+ * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+ * implement it as VehiclePropertyAccess.READ only.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ELECTRONIC_STABILITY_CONTROL_ENABLED =
+ 0x040E + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+ /**
+ * Electronic Stability Control (ESC) state.
+ *
+ * Returns the current state of ESC. This property must always return a valid state defined in
+ * ElectronicStabilityControlState or ErrorState. It must not surface errors through StatusCode
+ * and must use the supported error states instead.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
+ * unless all states of both ElectronicStabilityControlState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum ElectronicStabilityControlState
+ * @data_enum ErrorState
+ * @version 2
+ */
+ ELECTRONIC_STABILITY_CONTROL_STATE =
+ 0x040F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
* HVAC Properties
*
* Additional rules for mapping non-GLOBAL VehicleArea type HVAC properties
@@ -721,6 +839,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_FAN_SPEED = 0x0500 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -734,6 +853,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleHvacFanDirection
+ * @version 2
*/
HVAC_FAN_DIRECTION = 0x0501 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -743,6 +863,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:CELSIUS
+ * @version 2
*/
HVAC_TEMPERATURE_CURRENT = 0x0502 + 0x10000000 + 0x05000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
@@ -774,6 +895,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:CELSIUS
+ * @version 2
*/
HVAC_TEMPERATURE_SET = 0x0503 + 0x10000000 + 0x05000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
@@ -786,6 +908,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_DEFROSTER = 0x0504 + 0x10000000 + 0x03000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -799,6 +922,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @config_flags Supported areaIds
+ * @version 2
*/
HVAC_AC_ON = 0x0505 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -816,6 +940,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_MAX_AC_ON = 0x0506 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -839,6 +964,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_MAX_DEFROST_ON = 0x0507 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -856,6 +982,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_RECIRC_ON = 0x0508 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -895,6 +1022,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_DUAL_ON = 0x0509 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -917,6 +1045,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_AUTO_ON = 0x050A + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -939,6 +1068,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_SEAT_TEMPERATURE = 0x050B + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -962,6 +1092,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_SIDE_MIRROR_HEAT = 0x050C + 0x10000000 + 0x04000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -985,6 +1116,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_STEERING_WHEEL_HEAT = 0x050D + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1011,6 +1143,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @version 2
*/
HVAC_TEMPERATURE_DISPLAY_UNITS = 0x050E + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1019,6 +1152,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_ACTUAL_FAN_SPEED_RPM = 0x050F + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1065,6 +1199,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_POWER_ON = 0x0510 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1084,6 +1219,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum VehicleHvacFanDirection
+ * @version 2
*/
HVAC_FAN_DIRECTION_AVAILABLE = 0x0511 + 0x10000000 + 0x05000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32_VEC
@@ -1100,6 +1236,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_AUTO_RECIRC_ON = 0x0512 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1125,6 +1262,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_SEAT_VENTILATION = 0x0513 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1137,6 +1275,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HVAC_ELECTRIC_DEFROSTER_ON = 0x0514 + 0x10000000 + 0x03000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -1177,6 +1316,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
HVAC_TEMPERATURE_VALUE_SUGGESTION = 0x0515 + 0x10000000 + 0x01000000
+ 0x00610000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT_VEC
@@ -1202,6 +1342,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @version 2
*/
DISTANCE_DISPLAY_UNITS = 0x0600 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1226,6 +1367,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @version 2
*/
FUEL_VOLUME_DISPLAY_UNITS = 0x0601 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1251,6 +1393,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @version 2
*/
TIRE_PRESSURE_DISPLAY_UNITS = 0x0602 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1276,6 +1419,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @version 2
*/
EV_BATTERY_DISPLAY_UNITS = 0x0603 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1292,6 +1436,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 0x0604 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1315,6 +1460,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1359,6 +1505,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLI_SECS
+ * @version 2
*/
EXTERNAL_CAR_TIME = 0x0608 + 0x10000000 // VehiclePropertyGroup:SYSTEM
+ 0x01000000 // VehicleArea:GLOBAL
@@ -1388,6 +1535,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
* @unit VehicleUnit:MILLI_SECS
+ * @version 2
*/
ANDROID_EPOCH_TIME = 0x0606 + 0x10000000 + 0x01000000
+ 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
@@ -1402,6 +1550,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
STORAGE_ENCRYPTION_BINDING_SEED = 0x0607 + 0x10000000 + 0x01000000
+ 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
@@ -1411,6 +1560,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:CELSIUS
+ * @version 2
*/
ENV_OUTSIDE_TEMPERATURE = 0x0703 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -1429,6 +1579,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
AP_POWER_STATE_REQ = 0x0A00 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -1443,6 +1594,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
AP_POWER_STATE_REPORT = 0x0A01 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -1457,6 +1609,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
AP_POWER_BOOTUP_REASON = 0x0A02 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1479,6 +1632,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
DISPLAY_BRIGHTNESS = 0x0A03 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1502,10 +1656,45 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
PER_DISPLAY_BRIGHTNESS = 0x0A04 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
/**
+ * Valet mode enabled
+ *
+ * This property allows the user to enable/disable valet mode in their vehicle. Valet mode is
+ * a privacy and security setting that prevents an untrusted driver to access more private areas
+ * in the vehicle, such as the glove box or the trunk(s).
+ *
+ * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+ * implement it as VehiclePropertyAccess.READ only.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ VALET_MODE_ENABLED =
+ 0x0A05 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+ /**
+ * Head up display (HUD) enabled
+ *
+ * This property allows the user to turn on/off the HUD for their seat.
+ *
+ * Each HUD in the vehicle should be assigned to the seat that is intended to use it. For
+ * example, if there is a single HUD in the vehicle that is used by the driver so that they no
+ * longer need to continuously look at the instrument cluster, then this property should be
+ * defined with a single area ID equal to the driver's seat area value.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ HEAD_UP_DISPLAY_ENABLED =
+ 0x0A06 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
+ /**
* Property to feed H/W input events to android
*
* int32Values[0] : action defined by VehicleHwKeyInputAction
@@ -1519,6 +1708,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @config_flags
+ * @version 2
*/
HW_KEY_INPUT = 0x0A10 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -1541,6 +1731,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @config_flags
+ * @version 2
*/
HW_KEY_INPUT_V2 =
0x0A11 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.MIXED,
@@ -1575,6 +1766,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @config_flags
+ * @version 2
*/
HW_MOTION_INPUT =
0x0A12 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.MIXED,
@@ -1598,6 +1790,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @data_enum RotaryInputType
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HW_ROTARY_INPUT = 0x0A20 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -1621,6 +1814,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @data_enum CustomInputType
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HW_CUSTOM_INPUT = 0X0A30 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -1665,6 +1859,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DOOR_POS = 0x0B00 + 0x10000000 + 0x06000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
@@ -1690,6 +1885,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DOOR_MOVE = 0x0B01 + 0x10000000 + 0x06000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
@@ -1704,6 +1900,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DOOR_LOCK = 0x0B02 + 0x10000000 + 0x06000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:BOOLEAN
@@ -1720,6 +1917,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DOOR_CHILD_LOCK_ENABLED =
0x0B03 + VehiclePropertyGroup.SYSTEM + VehicleArea.DOOR + VehiclePropertyType.BOOLEAN,
@@ -1746,6 +1944,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_Z_POS = 0x0B40 + 0x10000000 + 0x04000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1772,6 +1971,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_Z_MOVE = 0x0B41 + 0x10000000 + 0x04000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1798,6 +1998,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_Y_POS = 0x0B42 + 0x10000000 + 0x04000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1823,6 +2024,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_Y_MOVE = 0x0B43 + 0x10000000 + 0x04000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1837,6 +2039,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_LOCK = 0x0B44 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1851,6 +2054,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_FOLD = 0x0B45 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1868,6 +2072,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_AUTO_FOLD_ENABLED =
@@ -1886,6 +2091,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
MIRROR_AUTO_TILT_ENABLED =
@@ -1905,6 +2111,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
SEAT_MEMORY_SELECT = 0x0B80 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1918,6 +2125,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
SEAT_MEMORY_SET = 0x0B81 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1935,6 +2143,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BELT_BUCKLED = 0x0B82 + 0x10000000 + 0x05000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1960,6 +2169,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BELT_HEIGHT_POS = 0x0B83 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1988,6 +2198,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BELT_HEIGHT_MOVE = 0x0B84 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2013,6 +2224,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_FORE_AFT_POS = 0x0B85 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2040,6 +2252,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_FORE_AFT_MOVE = 0x0B86 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2067,6 +2280,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BACKREST_ANGLE_1_POS = 0x0B87 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2094,6 +2308,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BACKREST_ANGLE_1_MOVE = 0x0B88 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2123,6 +2338,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BACKREST_ANGLE_2_POS = 0x0B89 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2150,6 +2366,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_BACKREST_ANGLE_2_MOVE = 0x0B8A + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2173,6 +2390,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEIGHT_POS = 0x0B8B + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2198,6 +2416,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEIGHT_MOVE = 0x0B8C + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2226,6 +2445,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_DEPTH_POS = 0x0B8D + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2252,6 +2472,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_DEPTH_MOVE = 0x0B8E + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2279,6 +2500,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_TILT_POS = 0x0B8F + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2306,6 +2528,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_TILT_MOVE = 0x0B90 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2331,6 +2554,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_FORE_AFT_POS = 0x0B91 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2359,6 +2583,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_FORE_AFT_MOVE = 0x0B92 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2384,6 +2609,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x0B93 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2412,6 +2638,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2432,6 +2659,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_HEIGHT_POS = 0x0B95 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -2459,6 +2687,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_HEIGHT_POS_V2 =
0x0BA4 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2488,6 +2717,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_HEIGHT_MOVE = 0x0B96 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2511,6 +2741,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_ANGLE_POS = 0x0B97 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2539,6 +2770,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_ANGLE_MOVE = 0x0B98 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2562,6 +2794,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_FORE_AFT_POS = 0x0B99 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2590,6 +2823,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2611,6 +2845,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
SEAT_FOOTWELL_LIGHTS_STATE =
0x0B9B + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2636,6 +2871,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
SEAT_FOOTWELL_LIGHTS_SWITCH =
0x0B9C + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2652,6 +2888,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_EASY_ACCESS_ENABLED =
0x0B9D + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -2672,10 +2909,34 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 3
*/
SEAT_AIRBAG_ENABLED =
0x0B9E + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
/**
+ * Seat airbags deployed
+ *
+ * Bit flag property to relay information on which airbags have been deployed in the vehicle at
+ * each seat, vs which ones are currently still armed. If SEAT_AIRBAG_ENABLED is set to false at
+ * a particular areaId, this property should return status code UNAVAILABLE at that areaId.
+ *
+ * Enums apply to each seat, not the global vehicle. For example, VehicleAirbagsLocation#CURTAIN
+ * at the driver seat areaId represents whether the driver side curtain airbag has been
+ * deployed. Multiple bit flags can be set to indicate that multiple different airbags have been
+ * deployed for the seat.
+ *
+ * For each seat area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless
+ * all states of VehicleAirbagLocation are supported (including OTHER, which is not
+ * recommended).
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum VehicleAirbagLocation
+ * @version 2
+ */
+ SEAT_AIRBAGS_DEPLOYED =
+ 0x0BA5 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+ /**
* Represents property for seat’s hipside (bottom cushion’s side) support position.
*
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
@@ -2697,6 +2958,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_CUSHION_SIDE_SUPPORT_POS =
0x0B9F + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2725,6 +2987,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_CUSHION_SIDE_SUPPORT_MOVE =
0x0BA0 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2748,6 +3011,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_VERTICAL_POS =
0x0BA1 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2774,6 +3038,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_LUMBAR_VERTICAL_MOVE =
0x0BA2 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2800,10 +3065,30 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SEAT_WALK_IN_POS =
0x0BA3 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
/**
+ * Seat belt pretensioner deployed.
+ *
+ * Property to relay information on whether the seat belt pretensioner has been deployed for a
+ * particular seat due to a collision. This is different from the regular seat belt tightening
+ * system that continuously adds tension to the seat belts so that they fit snugly around the
+ * person sitting in the seat, nor is it the seat belt retractor system that locks the seat belt
+ * in place during sudden brakes or when the user jerks the seat belt.
+ *
+ * If this property is dependant on the state of other properties, and those properties are
+ * currently in the state that doesn't support this property, this should return
+ * StatusCode#NOT_AVAILABLE
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ SEAT_BELT_PRETENSIONER_DEPLOYED =
+ 0x0BA6 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
+ /**
* Seat Occupancy
*
* Indicates whether a particular seat is occupied or not, to the best of the car's ability
@@ -2812,6 +3097,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleSeatOccupancyState
+ * @version 2
*/
SEAT_OCCUPANCY = 0x0BB0 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2848,6 +3134,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
WINDOW_POS = 0x0BC0 + 0x10000000 + 0x03000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
@@ -2890,6 +3177,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
@@ -2904,6 +3192,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
WINDOW_LOCK = 0x0BC4 + 0x10000000 + 0x03000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -2924,6 +3213,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLI_SECS
+ * @version 2
*/
WINDSHIELD_WIPERS_PERIOD =
0x0BC5 + VehiclePropertyGroup.SYSTEM + VehicleArea.WINDOW + VehiclePropertyType.INT32,
@@ -2945,6 +3235,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum WindshieldWipersState
+ * @version 2
*/
WINDSHIELD_WIPERS_STATE =
0x0BC6 + VehiclePropertyGroup.SYSTEM + VehicleArea.WINDOW + VehiclePropertyType.INT32,
@@ -2971,6 +3262,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum WindshieldWipersSwitch
+ * @version 2
*/
WINDSHIELD_WIPERS_SWITCH =
0x0BC7 + VehiclePropertyGroup.SYSTEM + VehicleArea.WINDOW + VehiclePropertyType.INT32,
@@ -2997,6 +3289,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_DEPTH_POS =
0x0BE0 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3023,6 +3316,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_DEPTH_MOVE =
0x0BE1 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3046,6 +3340,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_HEIGHT_POS =
0x0BE2 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3072,6 +3367,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_HEIGHT_MOVE =
0x0BE3 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3087,6 +3383,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_THEFT_LOCK_ENABLED =
0x0BE4 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3101,6 +3398,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_LOCKED =
0x0BE5 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3116,6 +3414,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
STEERING_WHEEL_EASY_ACCESS_ENABLED =
0x0BE6 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3143,6 +3442,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
GLOVE_BOX_DOOR_POS =
0x0BF0 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -3162,6 +3462,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
GLOVE_BOX_LOCKED =
0x0BF1 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -3181,6 +3482,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
VEHICLE_MAP_SERVICE = 0x0C00 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3200,9 +3502,187 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
LOCATION_CHARACTERIZATION =
0x0C10 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+
+ /**
+ * Static data for the position of each ultrasonic sensor installed on the vehicle.
+ *
+ * Each individual sensor is identified by its unique VehicleAreaConfig#areaId and returns the
+ * sensor's position formatted as [x, y, z] where:
+ *
+ * int32Values[0] = x, the position of the sensor along the x-axis relative to the origin of
+ * the Android Automotive sensor coordinate frame in millimeters
+ * int32Values[1] = y, the position of the sensor along the y-axis relative to the origin of
+ * the Android Automotive sensor coordinate frame in millimeters.
+ * int32Values[2] = z, the position of the sensor along the z-axis relative to the origin of
+ * the Android Automotive sensor coordinate frame in millimeters.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.STATIC
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_POSITION = 0x0C20 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
+ /**
+ * Static data for the orientation of each ultrasonic sensor installed on the vehicle.
+ *
+ * Each individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's
+ * orientation formatted as [qw, qx, qy, qz] where:
+ *
+ * int32Values[0] = qw, the quaternion coefficient w within the quaterinion (w + xi + yj +
+ * zk) describing the rotation of the sensor relative to the Android
+ * Automotive sensor coordinate frame.
+ * int32Values[1] = qx, the quaternion coefficient x within the quaterinion (w + xi + yj +
+ * zk) describing the rotation of the sensor relative to the Android
+ * Automotive sensor coordinate frame.
+ * int32Values[2] = qy, the quaternion coefficient y within the quaterinion (w + xi + yj +
+ * zk) describing the rotation of the sensor relative to the Android
+ * Automotive sensor coordinate frame.
+ * int32Values[3] = qz, the quaternion coefficient z within the quaterinion (w + xi + yj +
+ * zk) describing the rotation of the sensor relative to the Android
+ * Automotive sensor coordinate frame.
+ *
+ * This assumes each sensor uses the same axes conventions as Android Automotive.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.STATIC
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_ORIENTATION = 0x0C21 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
+ /**
+ * Static data for the field of view of each ultrasonic sensor in degrees.
+ *
+ * Each individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's
+ * field of view formatted as [horizontal, vertical] where:
+ *
+ * int32Values[0] = horizontal, the horizontal field of view for the specified ultrasonic
+ * sensor in degrees.
+ * int32Values[1] = vertical, the vertical field of view for the associated specified
+ * ultrasonic sensor in degrees.
+ *
+ * This assumes each sensor uses the same axes conventions as Android Automotive.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.STATIC
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_FIELD_OF_VIEW = 0x0C22 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
+ /**
+ * Static data for the detection range of each ultrasonic sensor in millimeters.
+ *
+ * Each individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's
+ * detection range formatted as [minimum, maximum] where:
+ *
+ * int32Values[0] = minimum, the minimum range detectable by the ultrasonic sensor in
+ * millimeters.
+ * int32Values[1] = maximum, the maximum range detectable by the ultrasonic sensor in
+ * millimeters.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.STATIC
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_DETECTION_RANGE = 0x0C23 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
+ /**
+ * Static data for the supported ranges of each ultrasonic sensor in millimeters.
+ *
+ * For ultrasonic sensors that only support readings within a specific range. For example, if
+ * an ultrasonic sensor detects an object at 700mm, but can only report that an object has been
+ * detected between 500mm and 1000mm.
+ *
+ * Each individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's
+ * supported ranges formatted as [range_min_1, range_max_1, range_min_2, range_max_2, ...]
+ * where:
+ *
+ * int32Values[0] = range_min_1, the minimum of one supported range by the specified sensor
+ * in millimeters, inclusive.
+ * int32Values[1] = range_max_1, the maximum of one supported range by the specified sensor
+ * in millimeters, inclusive.
+ * int32Values[2] = range_min_2, the minimum of another supported range by the specified
+ * sensor in millimeters, inclusive.
+ * int32Values[3] = range_max_2, the maximum of another supported range by the specified
+ sensor in millimeters, inclusive.
+ *
+ * Example:
+ * - Ultrasonic sensor supports the following ranges:
+ * - 150mm to 499mm
+ * - 500mm to 999mm
+ * - 1000mm to 1500mm
+ * - The associated supported ranges should be formatted as:
+ * - int32Values[0] = 150
+ * - int32Values[1] = 499
+ * - int32Values[2] = 500
+ * - int32Values[3] = 999
+ * - int32Values[4] = 1000
+ * - int32Values[5] = 1500
+ *
+ * If this property is not defined, all the values within the ULTRASONICS_SENSOR_DETECTION_RANGE
+ * for the specified sensor are assumed to be supported.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.STATIC
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_SUPPORTED_RANGES = 0x0C24 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
+ /**
+ * The distance reading of the nearest detected object per sensor in millimeters.
+ *
+ * Each individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's
+ * measured distance formatted as [distance, distance_error] where:
+ *
+ * int32Values[0] = distance, the measured distance of the nearest object in millimeters.
+ * If only a range is supported, this value must be set to the minimum
+ * supported distance in the detected range as specified in
+ * ULTRASONICS_SENSOR_SUPPORTED_RANGES.
+ * int32Values[1] = distance_error, the error of the measured distance value in
+ * millimeters.
+ *
+ * If no object is detected, an empty vector must be returned. If distance_error is not
+ * available then an array of only the measured distance must be returned.
+ *
+ * If the data is aggregated by another ECU, then OEMs have the option of reporting the same
+ * reading across all included sensors or reporting a virtual representation of all the included
+ * sensors as if they were one sensor.
+ *
+ * @change_mode VehiclePropertyChangeMode.CONTINUOUS
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ ULTRASONICS_SENSOR_MEASURED_DISTANCE = 0x0C25 + VehiclePropertyGroup.SYSTEM + VehicleArea.VENDOR
+ + VehiclePropertyType.INT32_VEC,
+
/**
* OBD2 Live Sensor Data
*
@@ -3243,6 +3723,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
OBD2_LIVE_FRAME = 0x0D00 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3269,6 +3750,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
OBD2_FREEZE_FRAME = 0x0D01 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3286,6 +3768,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
OBD2_FREEZE_FRAME_INFO = 0x0D02 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3308,6 +3791,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
OBD2_FREEZE_FRAME_CLEAR = 0x0D03 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3319,6 +3803,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
HEADLIGHTS_STATE = 0x0E00 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3330,6 +3815,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
HIGH_BEAM_LIGHTS_STATE = 0x0E01 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3357,6 +3843,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
FOG_LIGHTS_STATE = 0x0E02 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3368,6 +3855,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
HAZARD_LIGHTS_STATE = 0x0E03 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3383,6 +3871,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
HEADLIGHTS_SWITCH = 0x0E10 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3398,6 +3887,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
HIGH_BEAM_LIGHTS_SWITCH = 0x0E11 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3429,6 +3919,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
FOG_LIGHTS_SWITCH = 0x0E12 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3444,6 +3935,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
HAZARD_LIGHTS_SWITCH = 0x0E13 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3455,6 +3947,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
CABIN_LIGHTS_STATE = 0x0F01 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3473,6 +3966,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
CABIN_LIGHTS_SWITCH = 0x0F02 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -3484,6 +3978,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
READING_LIGHTS_STATE = 0x0F03 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -3502,6 +3997,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
READING_LIGHTS_SWITCH = 0x0F04 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -3523,6 +4019,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
STEERING_WHEEL_LIGHTS_STATE =
0x0F0C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3548,6 +4045,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
STEERING_WHEEL_LIGHTS_SWITCH =
0x0F0D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3576,6 +4074,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = 0x0F05 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -3592,6 +4091,7 @@
* ex) "com.android.car.user.CarUserNoticeService,storage_monitoring"
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DISABLED_OPTIONAL_FEATURES = 0x0F06 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -3642,6 +4142,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
INITIAL_USER_INFO = 0x0F07 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3808,6 +4309,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
SWITCH_USER = 0x0F08 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3854,6 +4356,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
CREATE_USER = 0x0F09 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3885,6 +4388,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
REMOVE_USER = 0x0F0A + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3960,6 +4464,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
USER_IDENTIFICATION_ASSOCIATION = 0x0F0B + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -3979,6 +4484,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EVS_SERVICE_REQUEST = 0x0F10 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -3996,6 +4502,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
POWER_POLICY_REQ = 0x0F21 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -4015,6 +4522,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
POWER_POLICY_GROUP_REQ = 0x0F22 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -4027,6 +4535,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @version 2
*/
CURRENT_POWER_POLICY = 0x0F23 + 0x10000000 + 0x01000000
+ 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
@@ -4038,6 +4547,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
WATCHDOG_ALIVE = 0xF31 + 0x10000000 + 0x01000000
+ 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
@@ -4049,6 +4559,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
WATCHDOG_TERMINATED_PROCESS = 0x0F32 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -4064,6 +4575,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
VHAL_HEARTBEAT = 0x0F33 + 0x10000000 + 0x01000000
+ 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
@@ -4077,6 +4589,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
CLUSTER_SWITCH_UI = 0x0F34 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4101,6 +4614,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
CLUSTER_DISPLAY_STATE = 0x0F35 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -4136,6 +4650,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
CLUSTER_REPORT_STATE = 0x0F36 + 0x10000000 + 0x01000000
+ 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
@@ -4150,6 +4665,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
CLUSTER_REQUEST_DISPLAY = 0x0F37 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4160,6 +4676,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 2
*/
CLUSTER_NAVIGATION_STATE = 0x0F38 + 0x10000000 + 0x01000000
+ 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
@@ -4173,6 +4690,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum ElectronicTollCollectionCardType
+ * @version 2
*/
ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = 0x0F39 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4187,6 +4705,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum ElectronicTollCollectionCardStatus
+ * @version 2
*/
ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = 0x0F3A + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4200,6 +4719,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
FRONT_FOG_LIGHTS_STATE = 0x0F3B + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4218,6 +4738,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
FRONT_FOG_LIGHTS_SWITCH = 0x0F3C + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4232,6 +4753,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
+ * @version 2
*/
REAR_FOG_LIGHTS_STATE = 0x0F3D + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4250,6 +4772,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightSwitch
+ * @version 2
*/
REAR_FOG_LIGHTS_SWITCH = 0x0F3E + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4267,6 +4790,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:AMPERE
+ * @version 2
*/
EV_CHARGE_CURRENT_DRAW_LIMIT = 0x0F3F + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -4288,6 +4812,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EV_CHARGE_PERCENT_LIMIT = 0x0F40 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -4300,6 +4825,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum EvChargeState
+ * @version 2
*/
EV_CHARGE_STATE = 0x0F41 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4316,6 +4842,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EV_CHARGE_SWITCH = 0x0F42 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -4328,6 +4855,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:SECS
+ * @version 2
*/
EV_CHARGE_TIME_REMAINING = 0x0F43 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4341,6 +4869,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum EvRegenerativeBrakingState
+ * @version 2
*/
EV_REGENERATIVE_BRAKING_STATE = 0x0F44 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4353,6 +4882,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum TrailerState
+ * @version 2
*/
TRAILER_PRESENT = 0x0F45 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4376,6 +4906,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:KILOGRAM
+ * @version 2
*/
VEHICLE_CURB_WEIGHT = 0x0F46 + 0x10000000 + 0x01000000
@@ -4390,6 +4921,7 @@
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum GsrComplianceRequirementType
+ * @version 2
*/
GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT = 0x0F47 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -4414,6 +4946,7 @@
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
SUPPORTED_PROPERTY_IDS = 0x0F48 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
@@ -4421,12 +4954,22 @@
/**
* Request the head unit to be shutdown.
*
+ * <p>This is required for executing a task when the head unit is powered off (remote task
+ * feature). After the head unit is powered-on to execute the task, the head unit should
+ * be shutdown. The head unit will send this message once the task is finished.
+ *
+ * <p>This is not for the case when a user wants to shutdown the head unit.
+ *
* <p>This usually involves telling a separate system outside the head unit (e.g. a power
* controller) to prepare shutting down the head unit.
*
- * <p>This does not mean the head unit will shutdown immediately.
+ * <p>Note that the external system must validate whether this request is valid by checking
+ * whether the vehicle is currently in use. If a user enters the vehicle after a
+ * SHUTDOWN_REQUEST is sent, then the system must ignore this request. It
+ * is recommended to store a VehicleInUse property in the power controller and exposes it
+ * through VEHICLE_IN_USE property. A shutdown request must be ignored if VehicleInUse is true.
*
- * <p>This means that another system will start sending a shutdown signal to the head unit,
+ * <p>If allowed, the external system will start sending a shutdown signal to the head unit,
* which will cause VHAL to send SHUTDOWN_PREPARE message to Android. Android will then start
* the shut down process by handling the message.
*
@@ -4451,6 +4994,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
* @data_enum VehicleApPowerStateShutdownParam
+ * @version 2
*/
SHUTDOWN_REQUEST =
0x0F49 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4483,6 +5027,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
VEHICLE_IN_USE =
0x0F4A + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4497,6 +5042,7 @@
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @version 3
*/
CLUSTER_HEARTBEAT =
0x0F4B + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.MIXED,
@@ -4516,6 +5062,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleAutonomousState
+ * @version 3
*/
VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL =
0x0F4C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4530,7 +5077,9 @@
* Enable or disable Automatic Emergency Braking (AEB).
*
* Set true to enable AEB and false to disable AEB. When AEB is enabled, the ADAS system in the
- * vehicle should be turned on and monitoring to avoid potential collisions.
+ * vehicle should be turned on and monitoring to avoid potential collisions. This property
+ * should apply for higher speed applications only. For enabling low speed automatic emergency
+ * braking, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED should be used.
*
* In general, AUTOMATIC_EMERGENCY_BRAKING_ENABLED should always return true or false. If the
* feature is not available due to some temporary state, such as the vehicle speed being too
@@ -4543,6 +5092,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
AUTOMATIC_EMERGENCY_BRAKING_ENABLED =
0x1000 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4552,7 +5102,9 @@
*
* Returns the current state of AEB. This property must always return a valid state defined in
* AutomaticEmergencyBrakingState or ErrorState. It must not surface errors through StatusCode
- * and must use the supported error states instead.
+ * and must use the supported error states instead. This property should apply for higher speed
+ * applications only. For representing the state of the low speed automatic emergency braking
+ * system, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE should be used.
*
* If AEB includes forward collision warnings before activating the brakes, those warnings must
* be surfaced through the Forward Collision Warning (FCW) properties.
@@ -4565,6 +5117,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum AutomaticEmergencyBrakingState
* @data_enum ErrorState
+ * @version 2
*/
AUTOMATIC_EMERGENCY_BRAKING_STATE =
0x1001 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4586,6 +5139,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
FORWARD_COLLISION_WARNING_ENABLED =
0x1002 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4605,6 +5159,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum ForwardCollisionWarningState
* @data_enum ErrorState
+ * @version 2
*/
FORWARD_COLLISION_WARNING_STATE =
0x1003 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4626,6 +5181,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
BLIND_SPOT_WARNING_ENABLED =
0x1004 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4645,6 +5201,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum BlindSpotWarningState
* @data_enum ErrorState
+ * @version 2
*/
BLIND_SPOT_WARNING_STATE =
0x1005 + VehiclePropertyGroup.SYSTEM + VehicleArea.MIRROR + VehiclePropertyType.INT32,
@@ -4667,6 +5224,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
LANE_DEPARTURE_WARNING_ENABLED =
0x1006 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4686,6 +5244,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum LaneDepartureWarningState
* @data_enum ErrorState
+ * @version 2
*/
LANE_DEPARTURE_WARNING_STATE =
0x1007 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4712,6 +5271,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
LANE_KEEP_ASSIST_ENABLED =
0x1008 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4734,6 +5294,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum LaneKeepAssistState
* @data_enum ErrorState
+ * @version 2
*/
LANE_KEEP_ASSIST_STATE =
0x1009 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4761,6 +5322,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
LANE_CENTERING_ASSIST_ENABLED =
0x100A + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4791,6 +5353,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
* @data_enum LaneCenteringAssistCommand
+ * @version 2
*/
LANE_CENTERING_ASSIST_COMMAND =
0x100B + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4813,6 +5376,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum LaneCenteringAssistState
* @data_enum ErrorState
+ * @version 2
*/
LANE_CENTERING_ASSIST_STATE =
0x100C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4836,6 +5400,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
EMERGENCY_LANE_KEEP_ASSIST_ENABLED =
0x100D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4856,6 +5421,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum EmergencyLaneKeepAssistState
* @data_enum ErrorState
+ * @version 2
*/
EMERGENCY_LANE_KEEP_ASSIST_STATE =
0x100E + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4880,6 +5446,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
CRUISE_CONTROL_ENABLED =
0x100F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4908,6 +5475,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum CruiseControlType
* @data_enum ErrorState
+ * @version 2
*/
CRUISE_CONTROL_TYPE =
0x1010 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4928,6 +5496,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum CruiseControlState
* @data_enum ErrorState
+ * @version 2
*/
CRUISE_CONTROL_STATE =
0x1011 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4951,6 +5520,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
* @data_enum CruiseControlCommand
+ * @version 2
*/
CRUISE_CONTROL_COMMAND =
0x1012 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -4974,6 +5544,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:METER_PER_SEC
+ * @version 2
*/
CRUISE_CONTROL_TARGET_SPEED =
0x1013 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT,
@@ -5005,6 +5576,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLI_SECS
+ * @version 2
*/
ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP =
0x1014 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5035,6 +5607,7 @@
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit:MILLIMETER
+ * @version 2
*/
ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE =
0x1015 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5056,6 +5629,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
HANDS_ON_DETECTION_ENABLED =
0x1016 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -5080,6 +5654,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum HandsOnDetectionDriverState
* @data_enum ErrorState
+ * @version 2
*/
HANDS_ON_DETECTION_DRIVER_STATE =
0x1017 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5102,6 +5677,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum HandsOnDetectionWarning
* @data_enum ErrorState
+ * @version 2
*/
HANDS_ON_DETECTION_WARNING =
0x1018 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5124,6 +5700,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 3
*/
DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED =
0x1019 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -5150,6 +5727,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum DriverDrowsinessAttentionState
* @data_enum ErrorState
+ * @version 3
*/
DRIVER_DROWSINESS_ATTENTION_STATE =
0x101A + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5174,6 +5752,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 3
*/
DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED =
0x101B + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -5195,6 +5774,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum DriverDrowsinessAttentionWarning
* @data_enum ErrorState
+ * @version 3
*/
DRIVER_DROWSINESS_ATTENTION_WARNING =
0x101C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5217,6 +5797,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 3
*/
DRIVER_DISTRACTION_SYSTEM_ENABLED =
0x101D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -5241,6 +5822,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum DriverDistractionState
* @data_enum ErrorState
+ * @version 3
*/
DRIVER_DISTRACTION_STATE =
0x101E + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -5264,6 +5846,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @version 2
*/
DRIVER_DISTRACTION_WARNING_ENABLED =
0x101F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -5285,10 +5868,157 @@
* @access VehiclePropertyAccess.READ
* @data_enum DriverDistractionWarning
* @data_enum ErrorState
+ * @version 3
*/
DRIVER_DISTRACTION_WARNING =
0x1020 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Enable or disable Low Speed Collision Warning.
+ *
+ * Set true to enable low speed collision warning and false to disable low speed collision
+ * warning. When low speed collision warning is enabled, the ADAS system in the vehicle should
+ * warn the driver of potential collisions at low speeds. This property is different from the
+ * pre-existing FORWARD_COLLISION_WARNING_ENABLED, which should apply to higher speed
+ * applications only. If the vehicle doesn't have a separate collision detection system for low
+ * speed environments, this property should not be implemented.
+ *
+ * In general, LOW_SPEED_COLLISION_WARNING_ENABLED should always return true or false. If the
+ * feature is not available due to some temporary state, such as the vehicle speed being too
+ * high, that information must be conveyed through the ErrorState values in the
+ * LOW_SPEED_COLLISION_WARNING_STATE property.
+ *
+ * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+ * implement it as VehiclePropertyAccess.READ only.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ LOW_SPEED_COLLISION_WARNING_ENABLED =
+ 0x1021 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+
+ /**
+ * Low Speed Collision Warning state.
+ *
+ * Returns the current state of Low Speed Collision Warning. This property must always return a
+ * valid state defined in LowSpeedCollisionWarningState or ErrorState. It must not surface
+ * errors through StatusCode and must use the supported error states instead. This property is
+ * different from the pre-existing FORWARD_COLLISION_WARNING_STATE, which should apply to higher
+ * speed applications only. If the vehicle doesn't have a separate collision detection system
+ * for low speed environments, this property should not be implemented.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
+ * unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum LowSpeedCollisionWarningState
+ * @data_enum ErrorState
+ * @version 3
+ */
+ LOW_SPEED_COLLISION_WARNING_STATE =
+ 0x1022 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+
+ /**
+ * Enable or disable Cross Traffic Monitoring.
+ *
+ * Set true to enable Cross Traffic Monitoring and false to disable Cross Traffic Monitoring.
+ * When Cross Traffic Monitoring is enabled, the ADAS system in the vehicle should be turned on
+ * and monitoring for potential sideways collisions.
+ *
+ * In general, CROSS_TRAFFIC_MONITORING_ENABLED should always return true or false. If the
+ * feature is not available due to some temporary state, such as the vehicle speed being too
+ * high, that information must be conveyed through the ErrorState values in the
+ * CROSS_TRAFFIC_MONITORING_STATE property.
+ *
+ * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+ * implement it as VehiclePropertyAccess.READ only.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ CROSS_TRAFFIC_MONITORING_ENABLED =
+ 0x1023 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+
+ /**
+ * Cross Traffic Monitoring warning state.
+ *
+ * Returns the current state of Cross Traffic Monitoring Warning. This property must always
+ * return a valid state defined in CrossTrafficMonitoringWarningState or ErrorState. It must not
+ * surface errors through StatusCode and must use the supported error states instead.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
+ * unless all states of both CrossTrafficMonitoringWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum CrossTrafficMonitoringWarningState
+ * @data_enum ErrorState
+ * @version 3
+ */
+ CROSS_TRAFFIC_MONITORING_WARNING_STATE =
+ 0x1024 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+
+ /**
+ * Enable or disable Low Speed Automatic Emergency Braking.
+ *
+ * Set true to enable Low Speed Automatic Emergency Braking or false to disable Low Speed
+ * Automatic Emergency Braking. When Low Speed Automatic Emergency Braking is enabled, the ADAS
+ * system in the vehicle should be turned on and monitoring to avoid potential collisions in low
+ * speed conditions. This property is different from the pre-existing
+ * AUTOMATIC_EMERGENCY_BRAKING_ENABLED, which should apply to higher speed applications only. If
+ * the vehicle doesn't have a separate collision avoidance system for low speed environments,
+ * this property should not be implemented.
+ *
+ * In general, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED should always return true or false.
+ * If the feature is not available due to some temporary state, such as the vehicle speed being
+ * too low, that information must be conveyed through the ErrorState values in the
+ * LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE property.
+ *
+ * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+ * implement it as VehiclePropertyAccess.READ only.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
+ * @version 3
+ */
+ LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED =
+ 0x1025 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+
+ /**
+ * Low Speed Automatic Emergency Braking state.
+ *
+ * Returns the current state of Low Speed Automatic Emergency Braking. This property must always
+ * return a valid state defined in LowSpeedAutomaticEmergencyBrakingState or ErrorState. It must
+ * not surface errors through StatusCode and must use the supported error states instead. This
+ * property is different from the pre-existing AUTOMATIC_EMERGENCY_BRAKING_STATE, which should
+ * apply to higher speed applications only. If the vehicle doesn't have a separate collision
+ * avoidance system for low speed environments, this property should not be implemented.
+ *
+ * If Low Speed Automatic Emergency Braking includes collision warnings before activating the
+ * brakes, those warnings must be surfaced through use of LOW_SPEED_COLLISION_WARNING_ENABLED
+ * and LOW_SPEED_COLLISION_WARNING_STATE.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
+ * unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is
+ * not recommended) and ErrorState are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum LowSpeedAutomaticEmergencyBrakingState
+ * @data_enum ErrorState
+ * @version 3
+ */
+ LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE =
+ 0x1026 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+
/***************************************************************************
* End of ADAS Properties
**************************************************************************/
diff --git a/automotive/vehicle/tools/generate_annotation_enums.py b/automotive/vehicle/tools/generate_annotation_enums.py
index 05fc99a..87e9bdc 100755
--- a/automotive/vehicle/tools/generate_annotation_enums.py
+++ b/automotive/vehicle/tools/generate_annotation_enums.py
@@ -42,6 +42,8 @@
'AccessForVehicleProperty.java')
ENUM_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
'EnumForVehicleProperty.java')
+VERSION_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
+ 'VersionForVehicleProperty.h')
SCRIPT_PATH = 'hardware/interfaces/automotive/vehicle/tools/generate_annotation_enums.py'
TAB = ' '
@@ -50,6 +52,7 @@
RE_COMMENT_BEGIN = re.compile('\s*\/\*\*?')
RE_COMMENT_END = re.compile('\s*\*\/')
RE_CHANGE_MODE = re.compile('\s*\* @change_mode (\S+)\s*')
+RE_VERSION = re.compile('\s*\* @version (\S+)\s*')
RE_ACCESS = re.compile('\s*\* @access (\S+)\s*')
RE_DATA_ENUM = re.compile('\s*\* @data_enum (\S+)\s*')
RE_UNIT = re.compile('\s*\* @unit (\S+)\s+')
@@ -81,8 +84,7 @@
"""
-CHANGE_MODE_CPP_HEADER = """#ifndef android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
-#define android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
+CHANGE_MODE_CPP_HEADER = """#pragma once
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
@@ -98,7 +100,7 @@
std::unordered_map<VehicleProperty, VehiclePropertyChangeMode> ChangeModeForVehicleProperty = {
"""
-CHANGE_MODE_CPP_FOOTER = """
+CPP_FOOTER = """
};
} // namespace vehicle
@@ -106,12 +108,9 @@
} // namespace hardware
} // namespace android
} // aidl
-
-#endif // android_hardware_automotive_vehicle_aidl_generated_lib_ChangeModeForVehicleProperty_H_
"""
-ACCESS_CPP_HEADER = """#ifndef android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
-#define android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
+ACCESS_CPP_HEADER = """#pragma once
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
@@ -127,16 +126,19 @@
std::unordered_map<VehicleProperty, VehiclePropertyAccess> AccessForVehicleProperty = {
"""
-ACCESS_CPP_FOOTER = """
-};
+VERSION_CPP_HEADER = """#pragma once
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-} // aidl
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
-#endif // android_hardware_automotive_vehicle_aidl_generated_lib_AccessForVehicleProperty_H_
+#include <unordered_map>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+std::unordered_map<VehicleProperty, int32_t> VersionForVehicleProperty = {
"""
CHANGE_MODE_JAVA_HEADER = """package android.hardware.automotive.vehicle;
@@ -148,7 +150,7 @@
public static final Map<Integer, Integer> values = Map.ofEntries(
"""
-CHANGE_MODE_JAVA_FOOTER = """
+JAVA_FOOTER = """
);
}
@@ -163,12 +165,6 @@
public static final Map<Integer, Integer> values = Map.ofEntries(
"""
-ACCESS_JAVA_FOOTER = """
- );
-
-}
-"""
-
ENUM_JAVA_HEADER = """package android.hardware.automotive.vehicle;
import java.util.List;
@@ -179,12 +175,6 @@
public static final Map<Integer, List<Class<?>>> values = Map.ofEntries(
"""
-ENUM_JAVA_FOOTER = """
- );
-
-}
-"""
-
class PropertyConfig:
"""Represents one VHAL property definition in VehicleProperty.aidl."""
@@ -196,6 +186,7 @@
self.access_modes = []
self.enum_types = []
self.unit_type = None
+ self.version = None
def __repr__(self):
return self.__str__()
@@ -258,6 +249,11 @@
match = RE_DATA_ENUM.match(line)
if match:
config.enum_types.append(match.group(1))
+ match = RE_VERSION.match(line)
+ if match:
+ if config.version != None:
+ raise Exception('Duplicate version annotation for property: ' + prop_name)
+ config.version = match.group(1)
else:
match = RE_VALUE.match(line)
if match:
@@ -270,6 +266,9 @@
if not config.access_modes:
raise Exception(
'No access_mode annotation for property: ' + prop_name)
+ if not config.version:
+ raise Exception(
+ 'no version annotation for property: ' + prop_name)
config.name = prop_name
configs.append(config)
@@ -295,6 +294,9 @@
continue;
if not cpp:
annotation = "List.of(" + ', '.join([class_name + ".class" for class_name in config.enum_types]) + ")"
+ elif field == 'version':
+ if cpp:
+ annotation = config.version
else:
raise Exception('Unknown field: ' + field)
if counter != 0:
@@ -347,6 +349,69 @@
return f.name
+class GeneratedFile:
+
+ def __init__(self, type):
+ self.type = type
+ self.cpp_file_path = None
+ self.java_file_path = None
+ self.cpp_header = None
+ self.java_header = None
+ self.cpp_footer = None
+ self.java_footer = None
+ self.cpp_output_file = None
+ self.java_output_file = None
+
+ def setCppFilePath(self, cpp_file_path):
+ self.cpp_file_path = cpp_file_path
+
+ def setJavaFilePath(self, java_file_path):
+ self.java_file_path = java_file_path
+
+ def setCppHeader(self, cpp_header):
+ self.cpp_header = cpp_header
+
+ def setCppFooter(self, cpp_footer):
+ self.cpp_footer = cpp_footer
+
+ def setJavaHeader(self, java_header):
+ self.java_header = java_header
+
+ def setJavaFooter(self, java_footer):
+ self.java_footer = java_footer
+
+ def convert(self, file_parser, check_only, temp_files):
+ if self.cpp_file_path:
+ output_file = GeneratedFile._getOutputFile(self.cpp_file_path, check_only, temp_files)
+ file_parser.convert(output_file, self.cpp_header, self.cpp_footer, True, self.type)
+ self.cpp_output_file = output_file
+
+ if self.java_file_path:
+ output_file = GeneratedFile._getOutputFile(self.java_file_path, check_only, temp_files)
+ file_parser.convert(output_file, self.java_header, self.java_footer, False, self.type)
+ self.java_output_file = output_file
+
+ def cmp(self):
+ if self.cpp_file_path:
+ if not filecmp.cmp(self.cpp_output_file, self.cpp_file_path):
+ return False
+
+ if self.java_file_path:
+ if not filecmp.cmp(self.java_output_file, self.java_file_path):
+ return False
+
+ return True
+
+ @staticmethod
+ def _getOutputFile(file_path, check_only, temp_files):
+ if not check_only:
+ return file_path
+
+ temp_file = createTempFile()
+ temp_files.append(temp_file)
+ return temp_file
+
+
def main():
parser = argparse.ArgumentParser(
description='Generate Java and C++ enums based on annotations in VehicleProperty.aidl')
@@ -382,51 +447,52 @@
f.outputAsCsv(args.output_csv)
return
- change_mode_cpp_file = os.path.join(android_top, CHANGE_MODE_CPP_FILE_PATH);
- access_cpp_file = os.path.join(android_top, ACCESS_CPP_FILE_PATH);
- change_mode_java_file = os.path.join(android_top, CHANGE_MODE_JAVA_FILE_PATH);
- access_java_file = os.path.join(android_top, ACCESS_JAVA_FILE_PATH);
- enum_java_file = os.path.join(android_top, ENUM_JAVA_FILE_PATH);
+ generated_files = []
+
+ change_mode = GeneratedFile('change_mode')
+ change_mode.setCppFilePath(os.path.join(android_top, CHANGE_MODE_CPP_FILE_PATH))
+ change_mode.setJavaFilePath(os.path.join(android_top, CHANGE_MODE_JAVA_FILE_PATH))
+ change_mode.setCppHeader(CHANGE_MODE_CPP_HEADER)
+ change_mode.setCppFooter(CPP_FOOTER)
+ change_mode.setJavaHeader(CHANGE_MODE_JAVA_HEADER)
+ change_mode.setJavaFooter(JAVA_FOOTER)
+ generated_files.append(change_mode)
+
+ access_mode = GeneratedFile('access_mode')
+ access_mode.setCppFilePath(os.path.join(android_top, ACCESS_CPP_FILE_PATH))
+ access_mode.setJavaFilePath(os.path.join(android_top, ACCESS_JAVA_FILE_PATH))
+ access_mode.setCppHeader(ACCESS_CPP_HEADER)
+ access_mode.setCppFooter(CPP_FOOTER)
+ access_mode.setJavaHeader(ACCESS_JAVA_HEADER)
+ access_mode.setJavaFooter(JAVA_FOOTER)
+ generated_files.append(access_mode)
+
+ enum_types = GeneratedFile('enum_types')
+ enum_types.setJavaFilePath(os.path.join(android_top, ENUM_JAVA_FILE_PATH))
+ enum_types.setJavaHeader(ENUM_JAVA_HEADER)
+ enum_types.setJavaFooter(JAVA_FOOTER)
+ generated_files.append(enum_types)
+
+ version = GeneratedFile('version')
+ version.setCppFilePath(os.path.join(android_top, VERSION_CPP_FILE_PATH))
+ version.setCppHeader(VERSION_CPP_HEADER)
+ version.setCppFooter(CPP_FOOTER)
+ generated_files.append(version)
+
temp_files = []
- if not args.check_only:
- change_mode_cpp_output = change_mode_cpp_file
- access_cpp_output = access_cpp_file
- change_mode_java_output = change_mode_java_file
- access_java_output = access_java_file
- enum_java_output = enum_java_file
- else:
- change_mode_cpp_output = createTempFile()
- temp_files.append(change_mode_cpp_output)
- access_cpp_output = createTempFile()
- temp_files.append(access_cpp_output)
- change_mode_java_output = createTempFile()
- temp_files.append(change_mode_java_output)
- access_java_output = createTempFile()
- temp_files.append(access_java_output)
- enum_java_output = createTempFile()
- temp_files.append(enum_java_output)
-
try:
- f.convert(change_mode_cpp_output, CHANGE_MODE_CPP_HEADER, CHANGE_MODE_CPP_FOOTER,
- True, 'change_mode')
- f.convert(change_mode_java_output, CHANGE_MODE_JAVA_HEADER,
- CHANGE_MODE_JAVA_FOOTER, False, 'change_mode')
- f.convert(access_cpp_output, ACCESS_CPP_HEADER, ACCESS_CPP_FOOTER, True, 'access_mode')
- f.convert(access_java_output, ACCESS_JAVA_HEADER, ACCESS_JAVA_FOOTER, False, 'access_mode')
- f.convert(enum_java_output, ENUM_JAVA_HEADER, ENUM_JAVA_FOOTER, False, 'enum_types')
+ for generated_file in generated_files:
+ generated_file.convert(f, args.check_only, temp_files)
if not args.check_only:
return
- if ((not filecmp.cmp(change_mode_cpp_output, change_mode_cpp_file)) or
- (not filecmp.cmp(change_mode_java_output, change_mode_java_file)) or
- (not filecmp.cmp(access_cpp_output, access_cpp_file)) or
- (not filecmp.cmp(access_java_output, access_java_file)) or
- (not filecmp.cmp(enum_java_output, enum_java_file))):
- print('The generated enum files for VehicleProperty.aidl requires update, ')
- print('Run \npython ' + android_top + '/' + SCRIPT_PATH)
- sys.exit(1)
+ for generated_file in generated_files:
+ if not generated_file.cmp():
+ print('The generated enum files for VehicleProperty.aidl requires update, ')
+ print('Run \npython ' + android_top + '/' + SCRIPT_PATH)
+ sys.exit(1)
except Exception as e:
print('Error parsing VehicleProperty.aidl')
print(e)
diff --git a/automotive/vehicle/vts/OWNERS b/automotive/vehicle/vts/OWNERS
index c93a843..0f88eec 100644
--- a/automotive/vehicle/vts/OWNERS
+++ b/automotive/vehicle/vts/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 533426
shanyu@google.com
-kwangsudo@google.com
+tylertrephan@google.com
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index c216e76..b5ee335 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -548,6 +548,44 @@
VehicleArea::GLOBAL, VehiclePropertyType::INT32);
}
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorPositionConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_POSITION, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::VENDOR, VehiclePropertyType::INT32_VEC);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorOrientationConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_ORIENTATION, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::VENDOR, VehiclePropertyType::INT32_VEC);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorFieldOfViewConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_FIELD_OF_VIEW, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::VENDOR, VehiclePropertyType::INT32_VEC);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorDetectionRangeConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_DETECTION_RANGE, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::VENDOR, VehiclePropertyType::INT32_VEC);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorSupportedRangesConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_SUPPORTED_RANGES,
+ VehiclePropertyAccess::READ, VehiclePropertyChangeMode::STATIC,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::VENDOR,
+ VehiclePropertyType::INT32_VEC);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyUltrasonicsSensorMeasuredDistanceConfig) {
+ verifyProperty(VehicleProperty::ULTRASONICS_SENSOR_MEASURED_DISTANCE,
+ VehiclePropertyAccess::READ, VehiclePropertyChangeMode::CONTINUOUS,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::VENDOR,
+ VehiclePropertyType::INT32_VEC);
+}
+
TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyEmergencyLaneKeepAssistEnabledConfig) {
verifyProperty(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED,
VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
@@ -945,6 +983,90 @@
VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32);
}
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatAirbagsDeployedConfig) {
+ verifyProperty(VehicleProperty::SEAT_AIRBAGS_DEPLOYED, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatBeltPretensionerDeployedConfig) {
+ verifyProperty(VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyImpactDetectedConfig) {
+ verifyProperty(VehicleProperty::IMPACT_DETECTED, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyEvBatteryAverageTemperatureConfig) {
+ verifyProperty(VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::CONTINUOUS, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::FLOAT);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyLowSpeedCollisionWarningEnabledConfig) {
+ verifyProperty(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyLowSpeedCollisionWarningStateConfig) {
+ verifyProperty(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyValetModeEnabledConfig) {
+ verifyProperty(VehicleProperty::VALET_MODE_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyElectronicStabilityControlEnabledConfig) {
+ verifyProperty(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyElectronicStabilityControlStateConfig) {
+ verifyProperty(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyCrossTrafficMonitoringEnabledConfig) {
+ verifyProperty(VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyCrossTrafficMonitoringWarningStateConfig) {
+ verifyProperty(VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE,
+ VehiclePropertyAccess::READ, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyHeadUpDisplayEnabledConfig) {
+ verifyProperty(VehicleProperty::HEAD_UP_DISPLAY_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyLowSpeedAutomaticEmergencyBrakingEnabledConfig) {
+ verifyProperty(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyLowSpeedAutomaticEmergencyBrakingStateConfig) {
+ verifyProperty(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE,
+ VehiclePropertyAccess::READ, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) {
auto result = mVhalClient->getPropConfigs({propertyId});
return result.ok();
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
index 0d977a9..7adf402 100644
--- a/biometrics/face/aidl/Android.bp
+++ b/biometrics/face/aidl/Android.bp
@@ -60,8 +60,16 @@
"android.hardware.keymaster-V4",
],
},
+ {
+ version: "4",
+ imports: [
+ "android.hardware.biometrics.common-V4",
+ "android.hardware.common-V2",
+ "android.hardware.keymaster-V4",
+ ],
+ },
],
- frozen: false,
+ frozen: true,
}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/.hash b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/.hash
new file mode 100644
index 0000000..e9a5aa3
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/.hash
@@ -0,0 +1 @@
+c43fbb9be4a662cc9ace640dba21cccdb84c6c21
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AcquiredInfo.aidl
new file mode 100644
index 0000000..1420cdc
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum AcquiredInfo {
+ UNKNOWN,
+ GOOD,
+ INSUFFICIENT,
+ TOO_BRIGHT,
+ TOO_DARK,
+ TOO_CLOSE,
+ TOO_FAR,
+ FACE_TOO_HIGH,
+ FACE_TOO_LOW,
+ FACE_TOO_RIGHT,
+ FACE_TOO_LEFT,
+ POOR_GAZE,
+ NOT_DETECTED,
+ TOO_MUCH_MOTION,
+ RECALIBRATE,
+ TOO_DIFFERENT,
+ TOO_SIMILAR,
+ PAN_TOO_EXTREME,
+ TILT_TOO_EXTREME,
+ ROLL_TOO_EXTREME,
+ FACE_OBSCURED,
+ START,
+ SENSOR_DIRTY,
+ VENDOR,
+ FIRST_FRAME_RECEIVED,
+ DARK_GLASSES_DETECTED,
+ MOUTH_COVERING_DETECTED,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AuthenticationFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AuthenticationFrame.aidl
new file mode 100644
index 0000000..bbaca12
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/AuthenticationFrame.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable AuthenticationFrame {
+ android.hardware.biometrics.face.BaseFrame data;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/BaseFrame.aidl
new file mode 100644
index 0000000..1dd0a9c
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/BaseFrame.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable BaseFrame {
+ android.hardware.biometrics.face.AcquiredInfo acquiredInfo = android.hardware.biometrics.face.AcquiredInfo.UNKNOWN;
+ int vendorCode;
+ float pan;
+ float tilt;
+ float distance;
+ boolean isCancellable;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Cell.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Cell.aidl
new file mode 100644
index 0000000..d423a69
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Cell.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable Cell {
+ int x;
+ int y;
+ int z;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentFrame.aidl
new file mode 100644
index 0000000..90be5d0
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentFrame.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable EnrollmentFrame {
+ @nullable android.hardware.biometrics.face.Cell cell;
+ android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN;
+ android.hardware.biometrics.face.BaseFrame data;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStage.aidl
new file mode 100644
index 0000000..89b06ca
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStage.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum EnrollmentStage {
+ UNKNOWN,
+ FIRST_FRAME_RECEIVED,
+ WAITING_FOR_CENTERING,
+ HOLD_STILL_IN_CENTER,
+ ENROLLING_MOVEMENT_1,
+ ENROLLING_MOVEMENT_2,
+ ENROLLMENT_FINISHED,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
new file mode 100644
index 0000000..ee1c01a
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentStageConfig.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable EnrollmentStageConfig {
+ android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN;
+ List<android.hardware.biometrics.face.Cell> cells;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentType.aidl
new file mode 100644
index 0000000..180ea5d
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/EnrollmentType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum EnrollmentType {
+ DEFAULT,
+ ACCESSIBILITY,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Error.aidl
new file mode 100644
index 0000000..5761e31
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Error.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum Error {
+ UNKNOWN,
+ HW_UNAVAILABLE,
+ UNABLE_TO_PROCESS,
+ TIMEOUT,
+ NO_SPACE,
+ CANCELED,
+ UNABLE_TO_REMOVE,
+ VENDOR,
+ REENROLL_REQUIRED,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceEnrollOptions.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceEnrollOptions.aidl
new file mode 100644
index 0000000..c961531
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceEnrollOptions.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable FaceEnrollOptions {
+ android.hardware.keymaster.HardwareAuthToken hardwareAuthToken;
+ android.hardware.biometrics.face.EnrollmentType enrollmentType;
+ android.hardware.biometrics.face.Feature[] features;
+ /**
+ * @deprecated use {@link surfacePreview} instead {@link NativeHandle} a handle used to render content from the face HAL. Note that only one of [{@link surfacePreview}, {@link nativeHandlePreview}] should be set at one time.
+ */
+ @nullable android.hardware.common.NativeHandle nativeHandlePreview;
+ @nullable android.view.Surface surfacePreview;
+ @nullable android.hardware.biometrics.common.OperationContext context;
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceSensorType.aidl
new file mode 100644
index 0000000..ec03733
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/FaceSensorType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum FaceSensorType {
+ UNKNOWN,
+ RGB,
+ IR,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Feature.aidl
new file mode 100644
index 0000000..3337df8
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/Feature.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum Feature {
+ REQUIRE_ATTENTION,
+ REQUIRE_DIVERSE_POSES,
+ DEBUG,
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/IFace.aidl
new file mode 100644
index 0000000..1ae76de
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/IFace.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+interface IFace {
+ android.hardware.biometrics.face.SensorProps[] getSensorProps();
+ android.hardware.biometrics.face.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.face.ISessionCallback cb);
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISession.aidl
new file mode 100644
index 0000000..b655d5f
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISession.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+interface ISession {
+ void generateChallenge();
+ void revokeChallenge(in long challenge);
+ android.hardware.biometrics.face.EnrollmentStageConfig[] getEnrollmentConfig(in android.hardware.biometrics.face.EnrollmentType enrollmentType);
+ /**
+ * @deprecated use {@link enrollWithOptions} instead.
+ */
+ android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in @nullable android.hardware.common.NativeHandle previewSurface);
+ android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
+ android.hardware.biometrics.common.ICancellationSignal detectInteraction();
+ void enumerateEnrollments();
+ void removeEnrollments(in int[] enrollmentIds);
+ void getFeatures();
+ void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.Feature feature, boolean enabled);
+ void getAuthenticatorId();
+ void invalidateAuthenticatorId();
+ void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
+ void close();
+ android.hardware.biometrics.common.ICancellationSignal authenticateWithContext(in long operationId, in android.hardware.biometrics.common.OperationContext context);
+ /**
+ * @deprecated use {@link enrollWithOptions} instead.
+ */
+ android.hardware.biometrics.common.ICancellationSignal enrollWithContext(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in @nullable android.hardware.common.NativeHandle previewSurface, in android.hardware.biometrics.common.OperationContext context);
+ android.hardware.biometrics.common.ICancellationSignal detectInteractionWithContext(in android.hardware.biometrics.common.OperationContext context);
+ void onContextChanged(in android.hardware.biometrics.common.OperationContext context);
+ android.hardware.biometrics.common.ICancellationSignal enrollWithOptions(in android.hardware.biometrics.face.FaceEnrollOptions options);
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISessionCallback.aidl
new file mode 100644
index 0000000..c6c035b
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+interface ISessionCallback {
+ void onChallengeGenerated(in long challenge);
+ void onChallengeRevoked(in long challenge);
+ void onAuthenticationFrame(in android.hardware.biometrics.face.AuthenticationFrame frame);
+ void onEnrollmentFrame(in android.hardware.biometrics.face.EnrollmentFrame frame);
+ void onError(in android.hardware.biometrics.face.Error error, in int vendorCode);
+ void onEnrollmentProgress(in int enrollmentId, int remaining);
+ void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat);
+ void onAuthenticationFailed();
+ void onLockoutTimed(in long durationMillis);
+ void onLockoutPermanent();
+ void onLockoutCleared();
+ void onInteractionDetected();
+ void onEnrollmentsEnumerated(in int[] enrollmentIds);
+ void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features);
+ void onFeatureSet(android.hardware.biometrics.face.Feature feature);
+ void onEnrollmentsRemoved(in int[] enrollmentIds);
+ void onAuthenticatorIdRetrieved(in long authenticatorId);
+ void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
+ void onSessionClosed();
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/SensorProps.aidl
new file mode 100644
index 0000000..918332b
--- /dev/null
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/4/android/hardware/biometrics/face/SensorProps.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.face;
+/* @hide */
+@VintfStability
+parcelable SensorProps {
+ android.hardware.biometrics.common.CommonProps commonProps;
+ android.hardware.biometrics.face.FaceSensorType sensorType = android.hardware.biometrics.face.FaceSensorType.UNKNOWN;
+ boolean halControlsPreview;
+ int previewDisplayId;
+ int enrollPreviewWidth;
+ int enrollPreviewHeight;
+ float enrollTranslationX;
+ float enrollTranslationY;
+ float enrollPreviewScale;
+ boolean supportsDetectInteraction;
+}
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 4816219..4e8390a 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -30,6 +30,7 @@
"libnativewindow",
],
srcs: [
+ "FakeLockoutTracker.cpp",
"main.cpp",
"Face.cpp",
"FakeFaceEngine.cpp",
@@ -63,6 +64,33 @@
srcs: [
"tests/FakeFaceEngineTest.cpp",
"FakeFaceEngine.cpp",
+ "FakeLockoutTracker.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libnativewindow",
+ ],
+ include_dirs: [
+ "frameworks/native/aidl/gui",
+ ],
+ static_libs: [
+ "libandroid.hardware.biometrics.face.VirtualProps",
+ "android.hardware.biometrics.face-V4-ndk",
+ "android.hardware.biometrics.common-V4-ndk",
+ "android.hardware.keymaster-V4-ndk",
+ "android.hardware.biometrics.common.util",
+ ],
+ vendor: true,
+ test_suites: ["general-tests"],
+ require_root: true,
+}
+
+cc_test {
+ name: "android.hardware.biometrics.face.FakeLockoutTrackerTest",
+ srcs: [
+ "tests/FakeLockoutTrackerTest.cpp",
+ "FakeLockoutTracker.cpp",
],
shared_libs: [
"libbase",
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.cpp b/biometrics/face/aidl/default/FakeFaceEngine.cpp
index dc524bb..7380611 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.cpp
+++ b/biometrics/face/aidl/default/FakeFaceEngine.cpp
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2023 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 "FaceVirtualHalEngine"
+
#include "FakeFaceEngine.h"
#include <android-base/logging.h>
@@ -186,6 +204,10 @@
return;
}
+ if (mLockoutTracker.checkIfLockout(cb)) {
+ return;
+ }
+
int i = 0;
do {
if (FaceHalProperties::lockout().value_or(false)) {
@@ -197,6 +219,7 @@
if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
LOG(ERROR) << "Fail: operation_authenticate_fails";
+ mLockoutTracker.addFailedAttempt(cb);
cb->onAuthenticationFailed();
return;
}
@@ -231,10 +254,12 @@
} while (!Util::hasElapsed(now, duration));
if (id > 0 && isEnrolled) {
+ mLockoutTracker.reset();
cb->onAuthenticationSucceeded(id, {} /* hat */);
return;
} else {
LOG(ERROR) << "Fail: face not enrolled";
+ mLockoutTracker.addFailedAttempt(cb);
cb->onAuthenticationFailed();
cb->onError(Error::TIMEOUT, 0 /* vendorError*/);
return;
@@ -389,6 +414,7 @@
const keymaster::HardwareAuthToken& /*hat*/) {
BEGIN_OP(0);
FaceHalProperties::lockout(false);
+ mLockoutTracker.reset();
cb->onLockoutCleared();
}
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.h b/biometrics/face/aidl/default/FakeFaceEngine.h
index 06dd396..8d9303c 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.h
+++ b/biometrics/face/aidl/default/FakeFaceEngine.h
@@ -16,18 +16,17 @@
#pragma once
-#define LOG_TAG "FaceVirtualHal"
-
#include <aidl/android/hardware/biometrics/common/SensorStrength.h>
#include <aidl/android/hardware/biometrics/face/BnSession.h>
#include <aidl/android/hardware/biometrics/face/FaceSensorType.h>
#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
-#include <random>
-
#include <future>
+#include <random>
#include <vector>
+#include "FakeLockoutTracker.h"
+
namespace aidl::android::hardware::biometrics::face {
namespace face = aidl::android::hardware::biometrics::face;
@@ -39,6 +38,7 @@
class FakeFaceEngine {
public:
FakeFaceEngine() : mRandom(std::mt19937::default_seed) {}
+ virtual ~FakeFaceEngine() {}
static face::FaceSensorType GetSensorType();
static common::SensorStrength GetSensorStrength();
@@ -61,6 +61,13 @@
void invalidateAuthenticatorIdImpl(ISessionCallback* cb);
void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/);
+ virtual std::string toString() const {
+ std::ostringstream os;
+ os << "----- FakeFaceEngine:: -----" << std::endl;
+ os << mLockoutTracker.toString();
+ return os.str();
+ }
+
std::mt19937 mRandom;
private:
@@ -68,6 +75,7 @@
static constexpr int32_t FACE_ERROR_VENDOR_BASE = 1000;
std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
std::pair<Error, int32_t> convertError(int32_t code);
+ FakeLockoutTracker mLockoutTracker;
};
} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/FakeLockoutTracker.cpp b/biometrics/face/aidl/default/FakeLockoutTracker.cpp
new file mode 100644
index 0000000..70bf08e
--- /dev/null
+++ b/biometrics/face/aidl/default/FakeLockoutTracker.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 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 "FaceVirtualHalLockoutTracker"
+
+#include "FakeLockoutTracker.h"
+#include <android-base/logging.h>
+#include <face.sysprop.h>
+#include "util/Util.h"
+
+using namespace ::android::face::virt;
+
+namespace aidl::android::hardware::biometrics::face {
+
+void FakeLockoutTracker::reset(bool dueToTimerExpire) {
+ if (!dueToTimerExpire) {
+ mFailedCount = 0;
+ mLastFailedTime = 0;
+ }
+ mTimedFailedCount = 0;
+ mCurrentMode = LockoutMode::kNone;
+ abortTimer();
+}
+
+void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
+ bool lockoutEnabled = FaceHalProperties::lockout_enable().value_or(false);
+ bool timedLockoutenabled = FaceHalProperties::lockout_timed_enable().value_or(false);
+ if (lockoutEnabled) {
+ mFailedCount++;
+ mTimedFailedCount++;
+ mLastFailedTime = Util::getSystemNanoTime();
+ int32_t lockoutTimedThreshold = FaceHalProperties::lockout_timed_threshold().value_or(3);
+ int32_t lockoutPermanetThreshold =
+ FaceHalProperties::lockout_permanent_threshold().value_or(5);
+ if (mFailedCount >= lockoutPermanetThreshold) {
+ mCurrentMode = LockoutMode::kPermanent;
+ LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
+ cb->onLockoutPermanent();
+ abortTimer();
+ } else if (timedLockoutenabled && mTimedFailedCount >= lockoutTimedThreshold) {
+ if (mCurrentMode == LockoutMode::kNone) {
+ mCurrentMode = LockoutMode::kTimed;
+ startLockoutTimer(getTimedLockoutDuration(), cb);
+ }
+ LOG(ERROR) << "FakeLockoutTracker: lockoutTimed";
+ cb->onLockoutTimed(getLockoutTimeLeft());
+ }
+ } else {
+ reset();
+ }
+}
+
+FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
+ return mCurrentMode;
+}
+
+int32_t FakeLockoutTracker::getTimedLockoutDuration() {
+ return FaceHalProperties::lockout_timed_duration().value_or(10 * 1000);
+}
+
+int64_t FakeLockoutTracker::getLockoutTimeLeft() {
+ int64_t res = 0;
+
+ if (mLastFailedTime > 0) {
+ auto now = Util::getSystemNanoTime();
+ auto elapsed = (now - mLastFailedTime) / 1000000LL;
+ res = getTimedLockoutDuration() - elapsed;
+ LOG(INFO) << "elapsed=" << elapsed << " now = " << now
+ << " mLastFailedTime=" << mLastFailedTime << " res=" << res;
+ }
+
+ return res;
+}
+
+bool FakeLockoutTracker::checkIfLockout(ISessionCallback* cb) {
+ if (mCurrentMode == LockoutMode::kPermanent) {
+ LOG(ERROR) << "Lockout permanent";
+ cb->onLockoutPermanent();
+ return true;
+ } else if (mCurrentMode == LockoutMode::kTimed) {
+ auto timeLeft = getLockoutTimeLeft();
+ LOG(ERROR) << "Lockout timed " << timeLeft;
+ cb->onLockoutTimed(timeLeft);
+ return true;
+ }
+ return false;
+}
+
+void FakeLockoutTracker::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
+ LOG(ERROR) << "startLockoutTimer: to=" << timeout;
+ if (mIsLockoutTimerStarted) return;
+ std::function<void(ISessionCallback*)> action =
+ std::bind(&FakeLockoutTracker::lockoutTimerExpired, this, std::placeholders::_1);
+ std::thread([timeout, action, cb]() {
+ std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+ action(cb);
+ }).detach();
+
+ mIsLockoutTimerStarted = true;
+}
+
+void FakeLockoutTracker::lockoutTimerExpired(ISessionCallback* cb) {
+ LOG(INFO) << "lockout timer expired";
+ mIsLockoutTimerStarted = false;
+
+ if (mIsLockoutTimerAborted) {
+ mIsLockoutTimerAborted = false;
+ return;
+ }
+
+ // if more failures seen since the timer started, need to restart timer again
+ auto deltaTime = getLockoutTimeLeft();
+ if (deltaTime <= 0) {
+ cb->onLockoutCleared();
+ reset(true);
+ } else {
+ startLockoutTimer(deltaTime, cb);
+ }
+}
+
+void FakeLockoutTracker::abortTimer() {
+ if (mIsLockoutTimerStarted) mIsLockoutTimerAborted = true;
+}
+
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/FakeLockoutTracker.h b/biometrics/face/aidl/default/FakeLockoutTracker.h
new file mode 100644
index 0000000..f2d38f3
--- /dev/null
+++ b/biometrics/face/aidl/default/FakeLockoutTracker.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
+#include <android/binder_to_string.h>
+#include <stdint.h>
+#include <string>
+
+namespace aidl::android::hardware::biometrics::face {
+
+// Lockout implementation for Face Virtual HAL
+class FakeLockoutTracker {
+ public:
+ FakeLockoutTracker()
+ : mFailedCount(0),
+ mLastFailedTime(0),
+ mIsLockoutTimerStarted(false),
+ mIsLockoutTimerAborted(false) {}
+ ~FakeLockoutTracker() {}
+
+ enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
+
+ bool checkIfLockout(ISessionCallback*);
+ void addFailedAttempt(ISessionCallback*);
+ int64_t getLockoutTimeLeft();
+ LockoutMode getMode();
+ void reset(bool dueToTimerExpire = false);
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "----- FakeLockoutTracker:: -----" << std::endl;
+ os << "mFailedCount:" << mFailedCount;
+ os << ", mCurrentMode:" << (int)mCurrentMode;
+ os << ", mLastFailedTime:" << (int)(mLastFailedTime / 1000000LL);
+ os << ", mIsLockoutTimerStarted:" << mIsLockoutTimerStarted;
+ os << ", mIsLockoutTimerAborted:" << mIsLockoutTimerAborted;
+ os << std::endl;
+ return os.str();
+ }
+
+ private:
+ void startLockoutTimer(int64_t timeout, ISessionCallback* cb);
+ void lockoutTimerExpired(ISessionCallback* cb);
+ int32_t getTimedLockoutDuration();
+ void abortTimer();
+
+ private:
+ int32_t mFailedCount;
+ int32_t mTimedFailedCount;
+ int64_t mLastFailedTime;
+ LockoutMode mCurrentMode;
+ bool mIsLockoutTimerStarted;
+ bool mIsLockoutTimerAborted;
+};
+
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/README.md b/biometrics/face/aidl/default/README.md
index 9225258..c9a8cfe 100644
--- a/biometrics/face/aidl/default/README.md
+++ b/biometrics/face/aidl/default/README.md
@@ -51,31 +51,31 @@
To authenticate successfully, the captured (hit) must match the enrollment id<br/>
set above. To trigger authentication failure, set the hit id to a different value.
-```shell
+`shell
$ adb shell setprop vendor.face.virtual.operation_authenticate_duration 800
-$ adb shell setprop vendor.face.virtual.enrollment_hit 1
-```
+$ adb shell setprop vendor.face.virtual.enrollment_hit 1`
### AcquiredInfo
+
AcquiredInfo codes can be sent during authentication by specifying the sysprop.<br/>
The codes is sent in sequence and in the interval of operation_authentication_duration/numberOfAcquiredInfoCode
-```shell
-$ adb shell setprop vendor.face.virtual.operation_authenticate_acquired 6,9,1013
-```
+`shell
+$ adb shell setprop vendor.face.virtual.operation_authenticate_acquired 6,9,1013`
Refer to [AcquiredInfo.aidl](https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:hardware/interfaces/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl) for full face acquiredInfo codes.
Note: For vendor specific acquired info, acquiredInfo = 1000 + vendorCode.
### Error Insertion
-Error can be inserted during authentction by specifying the authenticate_error sysprop.
-```shell
-$ adb shell setprop vendor.face.virtual.operation_authenticate_error 4
-```
-Refer to [Error.aidl](https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:hardware/interfaces/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl) for full face error codes
+Error can be inserted during authentction by specifying the authenticate_error
+sysprop. `shell $ adb shell setprop
+vendor.face.virtual.operation_authenticate_error 4` Refer to
+[Error.aidl](https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:hardware/interfaces/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl)
+for full face error codes
## Enrollment via Settings
-Enrollment process is specified by sysprop `next_enrollment` in the following format
+Enrollment process is specified by sysprop `next_enrollment` in the following
+format
```shell
Format: <id>:<progress_ms-[acquiredInfo,...],...:<success>
@@ -88,7 +88,40 @@
E.g.
$ adb shell setprop vendor.face.virtual.next_enrollment 1:6000-[21,8,1,1108,1,10,1113,1,1118,1124]:true
```
+
If next_enrollment prop is not set, the following default value is used:<br/>
defaultNextEnrollment="1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true"<br/>
Note: Enrollment data and configuration can be supported upon request in case of needs
+## Lockout
+
+Device lockout is based on the number of consecutive failed authentication attempts. There are a few
+flavors of lockout mechanisms that are supported by virtula HAL <br/>
+
+### Permanent Lockout
+
+There are two sysprop to control permanent lockout <br/>
+1. general lockout feature enable <br/>
+2. threshold of failed attempts <br/>
+`shell
+$ adb shell setprop persist.vendor.face.virtual.lockout_enable true
+$ adb shell setprop persist.vendor.face.virtual.lockout_permanent_threshold 3`
+
+### Temporary Lockout
+
+There are a few parameters to control temporary lockout (aka timed lockout): <br/>
+1. enable lockout (general lockout feature enable, and timed lcokout enable) <br/>
+2. threshold of failed attempts <br/>
+3. timeout in ms <br/>
+`shell
+$ adb shell setprop persist.vendor.face.virtual.lockout_enable true
+$ adb shell setprop persist.vendor.face.virtual.lockout_timed_enable true
+$ adb shell setprop persist.vendor.face.virtual.lockout_timed_threshold 5
+$ adb shell setprop persist.vendor.face.virtual.lockout_timed_duration 10000`
+
+### Forced Lockout
+
+A permanent lockout can be inserted on next authentication attempt independent of the failed <br/>
+attempt count. This is a feature purely for test purpose.
+`shell
+$ adb shell setprop persist.vendor.face.virtual.lockout true`
diff --git a/biometrics/face/aidl/default/face.sysprop b/biometrics/face/aidl/default/face.sysprop
index be32015..95b0b43 100644
--- a/biometrics/face/aidl/default/face.sysprop
+++ b/biometrics/face/aidl/default/face.sysprop
@@ -92,7 +92,7 @@
api_name: "challenge"
}
-# if locked out
+# if forced to lock out (Default to false)
prop {
prop_name: "vendor.face.virtual.lockout"
type: Boolean
@@ -176,3 +176,47 @@
api_name: "operation_authenticate_acquired"
}
+# whether support lockout based on the failed auth attempts (default: false)
+prop {
+ prop_name: "persist.vendor.face.virtual.lockout_enable"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_enable"
+}
+
+# whether support timed_lockout based on the failed auth attempts (default: false)
+prop {
+ prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_timed_enable"
+}
+
+# temperory lockout threshold in number of consecutive failed auth attempts
+prop {
+ prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_timed_threshold"
+}
+
+# temporary lockout duration in ms (default: 10000ms)
+prop {
+ prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_timed_duration"
+}
+
+# permanently lockout threshold in number of consecutive failed auth attempts
+prop {
+ prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_permanent_threshold"
+}
diff --git a/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp
new file mode 100644
index 0000000..fa07d1d
--- /dev/null
+++ b/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
+#include <android/binder_process.h>
+#include <face.sysprop.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+#include "FakeLockoutTracker.h"
+#include "util/Util.h"
+
+using namespace ::android::face::virt;
+using namespace ::aidl::android::hardware::biometrics::face;
+
+namespace aidl::android::hardware::biometrics::face {
+
+class TestSessionCallback : public BnSessionCallback {
+ public:
+ ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onError(face::Error, int32_t /*vendorCode*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
+ int32_t /*remaining*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t /*enrollmentId*/,
+ const keymaster::HardwareAuthToken&) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); };
+ ::ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); };
+ ::ndk::ScopedAStatus onEnrollmentsEnumerated(const std::vector<int32_t>&) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onEnrollmentsRemoved(
+ const std::vector<int32_t>& /*enrollmentIds*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*authenticatorId*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onEnrollmentFrame(const EnrollmentFrame&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>&) {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onFeatureSet(Feature) override { return ndk::ScopedAStatus::ok(); }
+ ::ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+ ::ndk::ScopedAStatus onAuthenticationFrame(const AuthenticationFrame&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus onLockoutTimed(int64_t timeLeft) override {
+ mLockoutTimed++;
+ mTimeLeft = timeLeft;
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onLockoutPermanent() override {
+ mLockoutPermanent++;
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onLockoutCleared() override {
+ mTimeLeft = 0;
+ mLockoutTimed = 0;
+ mLockoutPermanent = 0;
+ return ndk::ScopedAStatus::ok();
+ };
+
+ int64_t mTimeLeft = 0;
+ int mLockoutTimed = 0;
+ int mLockoutPermanent = 0;
+};
+
+class FakeLockoutTrackerTest : public ::testing::Test {
+ protected:
+ static constexpr int32_t LOCKOUT_TIMED_THRESHOLD = 3;
+ static constexpr int32_t LOCKOUT_PERMANENT_THRESHOLD = 5;
+ static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
+
+ void SetUp() override {
+ FaceHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
+ FaceHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
+ FaceHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
+ mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
+ }
+
+ void TearDown() override {
+ // reset to default
+ FaceHalProperties::lockout_timed_threshold(5);
+ FaceHalProperties::lockout_timed_duration(20);
+ FaceHalProperties::lockout_permanent_threshold(10000);
+ FaceHalProperties::lockout_enable(false);
+ FaceHalProperties::lockout(false);
+ }
+
+ FakeLockoutTracker mLockoutTracker;
+ std::shared_ptr<TestSessionCallback> mCallback;
+};
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
+ FaceHalProperties::lockout_enable(false);
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+ ASSERT_EQ(0, mCallback->mLockoutTimed);
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
+ FaceHalProperties::lockout_enable(true);
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_NE(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+ ASSERT_EQ(0, mCallback->mLockoutPermanent);
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+ ASSERT_EQ(1, mCallback->mLockoutPermanent);
+ ASSERT_TRUE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ ASSERT_EQ(2, mCallback->mLockoutPermanent);
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
+ FaceHalProperties::lockout_enable(true);
+ FaceHalProperties::lockout_timed_enable(true);
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
+ ASSERT_EQ(1, mCallback->mLockoutTimed);
+ ASSERT_TRUE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ ASSERT_EQ(2, mCallback->mLockoutTimed);
+ // time left
+ int N = 5;
+ int64_t prevTimeLeft = INT_MAX;
+ for (int i = 0; i < N; i++) {
+ SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1);
+ int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft();
+ ASSERT_TRUE(currTimeLeft < prevTimeLeft);
+ prevTimeLeft = currTimeLeft;
+ }
+ SLEEP_MS(LOCKOUT_TIMED_DURATION / N);
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
+ FaceHalProperties::lockout_enable(true);
+ FaceHalProperties::lockout_timed_enable(true);
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
+ SLEEP_MS(LOCKOUT_TIMED_DURATION + 20);
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+ for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - LOCKOUT_TIMED_THRESHOLD; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
+ FaceHalProperties::lockout_enable(true);
+ FaceHalProperties::lockout_timed_enable(true);
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ ASSERT_EQ(0, mCallback->mLockoutTimed);
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ SLEEP_MS(LOCKOUT_TIMED_DURATION / 2);
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ SLEEP_MS(LOCKOUT_TIMED_DURATION);
+ ASSERT_EQ(2, mCallback->mLockoutTimed);
+ ASSERT_TRUE(mLockoutTracker.checkIfLockout(mCallback.get()));
+ SLEEP_MS(LOCKOUT_TIMED_DURATION);
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+}
+
+TEST_F(FakeLockoutTrackerTest, resetLockout) {
+ FaceHalProperties::lockout_enable(true);
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+ for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD; i++)
+ mLockoutTracker.addFailedAttempt(mCallback.get());
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+ mLockoutTracker.reset();
+ ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
+}
+
+} // namespace aidl::android::hardware::biometrics::face
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecInfo.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecInfo.aidl
index 2ca9d96..2727d6e 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecInfo.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecInfo.aidl
@@ -49,7 +49,15 @@
int outputDataPath = 1;
boolean useControllerCodec = true;
}
+ parcelable LeAudio {
+ android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+ int[] samplingFrequencyHz;
+ int[] frameDurationUs;
+ int[] bitdepth;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
+ }
union Transport {
+ android.hardware.bluetooth.audio.CodecInfo.LeAudio leAudio;
android.hardware.bluetooth.audio.CodecInfo.A2dp a2dp;
android.hardware.bluetooth.audio.CodecInfo.Hfp hfp;
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
new file mode 100644
index 0000000..1049d98
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union CodecSpecificCapabilitiesLtv {
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv.SupportedSamplingFrequencies supportedSamplingFrequencies;
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv.SupportedFrameDurations supportedFrameDurations;
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv.SupportedAudioChannelCounts supportedAudioChannelCounts;
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv.SupportedOctetsPerCodecFrame supportedOctetsPerCodecFrame;
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv.SupportedMaxCodecFramesPerSDU supportedMaxCodecFramesPerSDU;
+ parcelable SupportedSamplingFrequencies {
+ int bitmask;
+ const int HZ8000 = 0x0001;
+ const int HZ11025 = 0x0002;
+ const int HZ16000 = 0x0004;
+ const int HZ22050 = 0x0008;
+ const int HZ24000 = 0x0010;
+ const int HZ32000 = 0x0020;
+ const int HZ44100 = 0x0040;
+ const int HZ48000 = 0x0080;
+ const int HZ88200 = 0x0100;
+ const int HZ96000 = 0x0200;
+ const int HZ176400 = 0x0400;
+ const int HZ192000 = 0x0800;
+ const int HZ384000 = 0x1000;
+ }
+ parcelable SupportedFrameDurations {
+ int bitmask;
+ const int US7500 = 0x01;
+ const int US10000 = 0x02;
+ const int US7500PREFERRED = 0x10;
+ const int US10000PREFERRED = 0x20;
+ }
+ parcelable SupportedAudioChannelCounts {
+ int bitmask;
+ const int ONE = 0x01;
+ const int TWO = 0x02;
+ const int THREE = 0x04;
+ const int FOUR = 0x08;
+ const int FIVE = 0x10;
+ const int SIX = 0x20;
+ const int SEVEN = 0x40;
+ const int EIGHT = 0x80;
+ }
+ parcelable SupportedOctetsPerCodecFrame {
+ int minimum;
+ int maximum;
+ }
+ parcelable SupportedMaxCodecFramesPerSDU {
+ int value;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
new file mode 100644
index 0000000..943d396
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union CodecSpecificConfigurationLtv {
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.CodecFrameBlocksPerSDU codecFrameBlocksPerSDU;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.SamplingFrequency samplingFrequency;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.FrameDuration frameDuration;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.AudioChannelAllocation audioChannelAllocation;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.OctetsPerCodecFrame octetsPerCodecFrame;
+ @Backing(type="byte")
+ enum SamplingFrequency {
+ HZ8000 = 0x01,
+ HZ11025 = 0x02,
+ HZ16000 = 0x03,
+ HZ22050 = 0x04,
+ HZ24000 = 0x05,
+ HZ32000 = 0x06,
+ HZ44100 = 0x07,
+ HZ48000 = 0x08,
+ HZ88200 = 0x09,
+ HZ96000 = 0x0A,
+ HZ176400 = 0x0B,
+ HZ192000 = 0x0C,
+ HZ384000 = 0x0D,
+ }
+ @Backing(type="byte")
+ enum FrameDuration {
+ US7500 = 0x00,
+ US10000 = 0x01,
+ }
+ parcelable AudioChannelAllocation {
+ int bitmask;
+ const int NOT_ALLOWED = 0x00000000;
+ const int FRONT_LEFT = 0x00000001;
+ const int FRONT_RIGHT = 0x00000002;
+ const int FRONT_CENTER = 0x00000004;
+ const int LOW_FREQUENCY_EFFECTS_1 = 0x00000008;
+ const int BACK_LEFT = 0x00000010;
+ const int BACK_RIGHT = 0x00000020;
+ const int FRONT_LEFT_OF_CENTER = 0x00000040;
+ const int FRONT_RIGHT_OF_CENTER = 0x00000080;
+ const int BACK_CENTER = 0x00000100;
+ const int LOW_FREQUENCY_EFFECTS_2 = 0x00000200;
+ const int SIDE_LEFT = 0x00000400;
+ const int SIDE_RIGHT = 0x00000800;
+ const int TOP_FRONT_LEFT = 0x00001000;
+ const int TOP_FRONT_RIGHT = 0x00002000;
+ const int TOP_FRONT_CENTER = 0x00004000;
+ const int TOP_CENTER = 0x00008000;
+ const int TOP_BACK_LEFT = 0x00010000;
+ const int TOP_BACK_RIGHT = 0x00020000;
+ const int TOP_SIDE_LEFT = 0x00040000;
+ const int TOP_SIDE_RIGHT = 0x00080000;
+ const int TOP_BACK_CENTER = 0x00100000;
+ const int BOTTOM_FRONT_CENTER = 0x00200000;
+ const int BOTTOM_FRONT_LEFT = 0x00400000;
+ const int BOTTOM_FRONT_RIGHT = 0x00800000;
+ const int FRONT_LEFT_WIDE = 0x01000000;
+ const int FRONT_RIGHT_WIDE = 0x02000000;
+ const int LEFT_SURROUND = 0x04000000;
+ const int RIGHT_SURROUND = 0x08000000;
+ }
+ parcelable OctetsPerCodecFrame {
+ int value;
+ }
+ parcelable CodecFrameBlocksPerSDU {
+ int value;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ConfigurationFlags.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ConfigurationFlags.aidl
new file mode 100644
index 0000000..baf0a4e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ConfigurationFlags.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable ConfigurationFlags {
+ int bitmask;
+ const int NONE = 0x0000;
+ const int LOSSLESS = 0x0001;
+ const int LOW_LATENCY = 0x0002;
+ const int ALLOW_ASYMMETRIC_CONFIGURATIONS = 0x0003;
+ const int SPATIAL_AUDIO = 0x0004;
+ const int PROVIDE_ASE_METADATA = 0x0005;
+ const int MONO_MIC_CONFIGURATION = 0x0006;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index ccf5524..f155634 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -42,4 +42,152 @@
void setLowLatencyModeAllowed(in boolean allowed);
android.hardware.bluetooth.audio.A2dpStatus parseA2dpConfiguration(in android.hardware.bluetooth.audio.CodecId codecId, in byte[] configuration, out android.hardware.bluetooth.audio.CodecParameters codecParameters);
@nullable android.hardware.bluetooth.audio.A2dpConfiguration getA2dpConfiguration(in List<android.hardware.bluetooth.audio.A2dpRemoteCapabilities> remoteA2dpCapabilities, in android.hardware.bluetooth.audio.A2dpConfigurationHint hint);
+ void setCodecPriority(in android.hardware.bluetooth.audio.CodecId codecId, int priority);
+ List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseConfigurationSetting> getLeAudioAseConfiguration(in @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDeviceCapabilities> remoteSinkAudioCapabilities, in @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDeviceCapabilities> remoteSourceAudioCapabilities, in List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioConfigurationRequirement> requirements);
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationPair getLeAudioAseQosConfiguration(in android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationRequirement qosRequirement);
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfigurationPair getLeAudioAseDatapathConfiguration(in android.hardware.bluetooth.audio.AudioContext context, in android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap[] streamMap);
+ void onSinkAseMetadataChanged(in android.hardware.bluetooth.audio.IBluetoothAudioProvider.AseState state, int cigId, int cisId, in @nullable android.hardware.bluetooth.audio.MetadataLtv[] metadata);
+ void onSourceAseMetadataChanged(in android.hardware.bluetooth.audio.IBluetoothAudioProvider.AseState state, int cigId, int cisId, in @nullable android.hardware.bluetooth.audio.MetadataLtv[] metadata);
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioBroadcastConfigurationSetting getLeAudioBroadcastConfiguration(in @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDeviceCapabilities> remoteSinkAudioCapabilities, in android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioBroadcastConfigurationRequirement requirement);
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration getLeAudioBroadcastDatapathConfiguration(in android.hardware.bluetooth.audio.AudioContext context, in android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration.BroadcastStreamMap[] streamMap);
+ @VintfStability
+ parcelable LeAudioDeviceCapabilities {
+ android.hardware.bluetooth.audio.CodecId codecId;
+ android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv[] codecSpecificCapabilities;
+ @nullable byte[] vendorCodecSpecificCapabilities;
+ @nullable android.hardware.bluetooth.audio.MetadataLtv[] metadata;
+ }
+ @VintfStability
+ parcelable LeAudioDataPathConfiguration {
+ int dataPathId;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration.DataPathConfiguration dataPathConfiguration;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration.IsoDataPathConfiguration isoDataPathConfiguration;
+ @VintfStability
+ parcelable IsoDataPathConfiguration {
+ android.hardware.bluetooth.audio.CodecId codecId;
+ boolean isTransparent;
+ int controllerDelayUs;
+ @nullable byte[] configuration;
+ }
+ @VintfStability
+ parcelable DataPathConfiguration {
+ @nullable byte[] configuration;
+ }
+ }
+ @VintfStability
+ parcelable LeAudioAseQosConfiguration {
+ int sduIntervalUs;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.Framing framing;
+ android.hardware.bluetooth.audio.Phy[] phy;
+ int maxTransportLatencyMs;
+ int maxSdu;
+ int retransmissionNum;
+ }
+ @Backing(type="byte") @VintfStability
+ enum Packing {
+ SEQUENTIAL = 0x00,
+ INTERLEAVED = 0x01,
+ }
+ @Backing(type="byte") @VintfStability
+ enum Framing {
+ UNFRAMED = 0x00,
+ FRAMED = 0x01,
+ }
+ @VintfStability
+ parcelable LeAudioAseConfigurationSetting {
+ android.hardware.bluetooth.audio.AudioContext audioContext;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.Packing packing;
+ @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseConfigurationSetting.AseDirectionConfiguration> sinkAseConfiguration;
+ @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseConfigurationSetting.AseDirectionConfiguration> sourceAseConfiguration;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
+ @VintfStability
+ parcelable AseDirectionConfiguration {
+ android.hardware.bluetooth.audio.LeAudioAseConfiguration aseConfiguration;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfiguration qosConfiguration;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration dataPathConfiguration;
+ }
+ }
+ @VintfStability
+ parcelable LeAudioConfigurationRequirement {
+ android.hardware.bluetooth.audio.AudioContext audioContext;
+ @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioConfigurationRequirement.AseDirectionRequirement> sinkAseRequirement;
+ @nullable List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioConfigurationRequirement.AseDirectionRequirement> sourceAseRequirement;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
+ @VintfStability
+ parcelable AseDirectionRequirement {
+ android.hardware.bluetooth.audio.LeAudioAseConfiguration aseConfiguration;
+ }
+ }
+ @VintfStability
+ parcelable LeAudioAseQosConfigurationRequirement {
+ android.hardware.bluetooth.audio.AudioContext contextType;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationRequirement.AseQosDirectionRequirement sinkAseQosRequirement;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationRequirement.AseQosDirectionRequirement sourceAseQosRequirement;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
+ @VintfStability
+ parcelable AseQosDirectionRequirement {
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.Framing framing;
+ android.hardware.bluetooth.audio.Phy[] preferredPhy;
+ int preferredRetransmissionNum;
+ int maxTransportLatencyMs;
+ int presentationDelayMinUs;
+ int presentationDelayMaxUs;
+ int preferredPresentationDelayMinUs;
+ int preferredPresentationDelayMaxUs;
+ android.hardware.bluetooth.audio.LeAudioAseConfiguration aseConfiguration;
+ }
+ }
+ @VintfStability
+ parcelable LeAudioAseQosConfigurationPair {
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfiguration sinkQosConfiguration;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfiguration sourceQosConfiguration;
+ }
+ parcelable LeAudioDataPathConfigurationPair {
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration inputConfig;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration outputConfig;
+ }
+ @Backing(type="byte") @VintfStability
+ enum AseState {
+ ENABLING = 0x00,
+ STREAMING = 0x01,
+ DISABLING = 0x02,
+ }
+ @Backing(type="byte") @VintfStability
+ enum BroadcastQuality {
+ STANDARD,
+ HIGH,
+ }
+ @VintfStability
+ parcelable LeAudioBroadcastSubgroupConfigurationRequirement {
+ android.hardware.bluetooth.audio.AudioContext context;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.BroadcastQuality quality;
+ int bisNumPerSubgroup;
+ }
+ @VintfStability
+ parcelable LeAudioBroadcastConfigurationRequirement {
+ List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioBroadcastSubgroupConfigurationRequirement> subgroupConfigurationRequirements;
+ }
+ @VintfStability
+ parcelable LeAudioSubgroupBisConfiguration {
+ int numBis;
+ android.hardware.bluetooth.audio.LeAudioBisConfiguration bisConfiguration;
+ }
+ @VintfStability
+ parcelable LeAudioBroadcastSubgroupConfiguration {
+ List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioSubgroupBisConfiguration> bisConfigurations;
+ @nullable byte[] vendorCodecConfiguration;
+ }
+ @VintfStability
+ parcelable LeAudioBroadcastConfigurationSetting {
+ int sduIntervalUs;
+ int numBis;
+ int maxSduOctets;
+ int maxTransportLatencyMs;
+ int retransmitionNum;
+ android.hardware.bluetooth.audio.Phy[] phy;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.Packing packing;
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider.Framing framing;
+ @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDataPathConfiguration dataPathConfiguration;
+ List<android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioBroadcastSubgroupConfiguration> subgroupsConfigurations;
+ }
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
index c806b0a..edb79a3 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -41,5 +41,6 @@
parcelable ProviderInfo {
String name;
android.hardware.bluetooth.audio.CodecInfo[] codecInfos;
+ boolean supportsMultidirectionalCapabilities;
}
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl
new file mode 100644
index 0000000..bffc88b
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioAseConfiguration {
+ android.hardware.bluetooth.audio.LeAudioAseConfiguration.TargetLatency targetLatency;
+ android.hardware.bluetooth.audio.Phy targetPhy;
+ @nullable android.hardware.bluetooth.audio.CodecId codecId;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv[] codecConfiguration;
+ @nullable byte[] vendorCodecConfiguration;
+ @nullable android.hardware.bluetooth.audio.MetadataLtv[] metadata;
+ @Backing(type="byte") @VintfStability
+ enum TargetLatency {
+ UNDEFINED = 0x00,
+ LOWER = 0x01,
+ BALANCED_LATENCY_RELIABILITY = 0x02,
+ HIGHER_RELIABILITY = 0x03,
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl
new file mode 100644
index 0000000..b09d34f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioBisConfiguration {
+ android.hardware.bluetooth.audio.CodecId codecId;
+ android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv[] codecConfiguration;
+ byte[] vendorCodecConfiguration;
+ @nullable android.hardware.bluetooth.audio.MetadataLtv[] metadata;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
index 2945710..efd3b02 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -42,5 +42,7 @@
int audioChannelAllocation;
android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
char pcmStreamId;
+ @nullable android.hardware.bluetooth.audio.LeAudioBisConfiguration bisConfiguration;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
}
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
index 2d9ebae..25a9797 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -44,5 +44,16 @@
char streamHandle;
int audioChannelAllocation;
boolean isStreamActive;
+ @nullable android.hardware.bluetooth.audio.LeAudioAseConfiguration aseConfiguration;
+ @nullable android.hardware.bluetooth.audio.ConfigurationFlags flags;
+ @nullable android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap.BluetoothDeviceAddress bluetoothDeviceAddress;
+ parcelable BluetoothDeviceAddress {
+ byte[6] deviceAddress;
+ android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap.BluetoothDeviceAddress.DeviceAddressType deviceAddressType;
+ enum DeviceAddressType {
+ BLE_ADDRESS_PUBLIC = 0x00,
+ BLE_ADDRESS_RANDOM = 0x01,
+ }
+ }
}
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/MetadataLtv.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/MetadataLtv.aidl
new file mode 100644
index 0000000..5e8a2ae
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/MetadataLtv.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union MetadataLtv {
+ android.hardware.bluetooth.audio.MetadataLtv.PreferredAudioContexts preferredAudioContexts;
+ android.hardware.bluetooth.audio.MetadataLtv.StreamingAudioContexts streamingAudioContexts;
+ android.hardware.bluetooth.audio.MetadataLtv.VendorSpecific vendorSpecific;
+ parcelable PreferredAudioContexts {
+ android.hardware.bluetooth.audio.AudioContext values;
+ }
+ parcelable StreamingAudioContexts {
+ android.hardware.bluetooth.audio.AudioContext values;
+ }
+ parcelable VendorSpecific {
+ int companyId;
+ byte[] opaqueValue;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Phy.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Phy.aidl
new file mode 100644
index 0000000..bfeabcd
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Phy.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum Phy {
+ UNDEFINED = 0x00,
+ ONE_M = 0x01,
+ TWO_M = 0x02,
+ CODED = 0x03,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecInfo.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecInfo.aidl
index 127cd7c..33f0c04 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecInfo.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecInfo.aidl
@@ -18,6 +18,7 @@
import android.hardware.bluetooth.audio.ChannelMode;
import android.hardware.bluetooth.audio.CodecId;
+import android.hardware.bluetooth.audio.ConfigurationFlags;
/**
* General information about a Codec
@@ -87,10 +88,46 @@
}
/**
+ * LE Audio Context
+ */
+ parcelable LeAudio {
+ /**
+ * Channel configuration: Mono, Dual-Mono or Stereo
+ */
+ ChannelMode[] channelMode;
+
+ /**
+ * Supported sampling frequencies, in Hz.
+ */
+ int[] samplingFrequencyHz;
+
+ /*
+ * FrameDuration in microseconds.
+ */
+ int[] frameDurationUs;
+
+ /**
+ * - Fixed point resolution, basically 16, 24 or 32 bits by samples.
+ * The value 32 should be used for floating point representation.
+ *
+ * When the bitdepth is not an encoding/decoding parameter (don't take
+ * part in the interoperability), the `bitdepth` list shall have a
+ * single element indicating the bitdepth selected for the platform.
+ */
+ int[] bitdepth;
+
+ /**
+ * Additional configuration flags
+ */
+ @nullable ConfigurationFlags flags;
+ }
+
+ /**
* Specific informations,
* depending on transport.
*/
union Transport {
+ LeAudio leAudio;
A2dp a2dp;
Hfp hfp;
}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
new file mode 100644
index 0000000..ceb90ba
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+/**
+ * Used to exchange generic remote device codec specific capabilities between
+ * the stack and the provider. As defined in Bluetooth Assigned Numbers,
+ * Sec. 6.12.4.
+ */
+@VintfStability
+union CodecSpecificCapabilitiesLtv {
+ parcelable SupportedSamplingFrequencies {
+ const int HZ8000 = 0x0001;
+ const int HZ11025 = 0x0002;
+ const int HZ16000 = 0x0004;
+ const int HZ22050 = 0x0008;
+ const int HZ24000 = 0x0010;
+ const int HZ32000 = 0x0020;
+ const int HZ44100 = 0x0040;
+ const int HZ48000 = 0x0080;
+ const int HZ88200 = 0x0100;
+ const int HZ96000 = 0x0200;
+ const int HZ176400 = 0x0400;
+ const int HZ192000 = 0x0800;
+ const int HZ384000 = 0x1000;
+
+ /* 16 bits wide bit mask */
+ int bitmask;
+ }
+ parcelable SupportedFrameDurations {
+ const int US7500 = 0x01;
+ const int US10000 = 0x02;
+ // Bits 2-3 are RFU
+ const int US7500PREFERRED = 0x10;
+ const int US10000PREFERRED = 0x20;
+
+ /* 8 bit wide bit mask */
+ int bitmask;
+ }
+ parcelable SupportedAudioChannelCounts {
+ const int ONE = 0x01;
+ const int TWO = 0x02;
+ const int THREE = 0x04;
+ const int FOUR = 0x08;
+ const int FIVE = 0x10;
+ const int SIX = 0x20;
+ const int SEVEN = 0x40;
+ const int EIGHT = 0x80;
+
+ /* 8 bit wide bit mask */
+ int bitmask;
+ }
+ parcelable SupportedOctetsPerCodecFrame {
+ int minimum;
+ int maximum;
+ }
+ parcelable SupportedMaxCodecFramesPerSDU {
+ int value;
+ }
+
+ SupportedSamplingFrequencies supportedSamplingFrequencies;
+ SupportedFrameDurations supportedFrameDurations;
+ SupportedAudioChannelCounts supportedAudioChannelCounts;
+ SupportedOctetsPerCodecFrame supportedOctetsPerCodecFrame;
+ SupportedMaxCodecFramesPerSDU supportedMaxCodecFramesPerSDU;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
new file mode 100644
index 0000000..c099ebe
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+/**
+ * Used to exchange generic remote device configuration between the stack and
+ * the provider. As defined in Bluetooth Assigned Numbers, Sec. 6.12.5.
+ */
+@VintfStability
+union CodecSpecificConfigurationLtv {
+ @Backing(type="byte")
+ enum SamplingFrequency {
+ HZ8000 = 0x01,
+ HZ11025 = 0x02,
+ HZ16000 = 0x03,
+ HZ22050 = 0x04,
+ HZ24000 = 0x05,
+ HZ32000 = 0x06,
+ HZ44100 = 0x07,
+ HZ48000 = 0x08,
+ HZ88200 = 0x09,
+ HZ96000 = 0x0A,
+ HZ176400 = 0x0B,
+ HZ192000 = 0x0C,
+ HZ384000 = 0x0D,
+ }
+
+ @Backing(type="byte")
+ enum FrameDuration {
+ US7500 = 0x00,
+ US10000 = 0x01,
+ }
+
+ parcelable AudioChannelAllocation {
+ const int NOT_ALLOWED = 0x00000000;
+ const int FRONT_LEFT = 0x00000001;
+ const int FRONT_RIGHT = 0x00000002;
+ const int FRONT_CENTER = 0x00000004;
+ const int LOW_FREQUENCY_EFFECTS_1 = 0x00000008;
+ const int BACK_LEFT = 0x00000010;
+ const int BACK_RIGHT = 0x00000020;
+ const int FRONT_LEFT_OF_CENTER = 0x00000040;
+ const int FRONT_RIGHT_OF_CENTER = 0x00000080;
+ const int BACK_CENTER = 0x00000100;
+ const int LOW_FREQUENCY_EFFECTS_2 = 0x00000200;
+ const int SIDE_LEFT = 0x00000400;
+ const int SIDE_RIGHT = 0x00000800;
+ const int TOP_FRONT_LEFT = 0x00001000;
+ const int TOP_FRONT_RIGHT = 0x00002000;
+ const int TOP_FRONT_CENTER = 0x00004000;
+ const int TOP_CENTER = 0x00008000;
+ const int TOP_BACK_LEFT = 0x00010000;
+ const int TOP_BACK_RIGHT = 0x00020000;
+ const int TOP_SIDE_LEFT = 0x00040000;
+ const int TOP_SIDE_RIGHT = 0x00080000;
+ const int TOP_BACK_CENTER = 0x00100000;
+ const int BOTTOM_FRONT_CENTER = 0x00200000;
+ const int BOTTOM_FRONT_LEFT = 0x00400000;
+ const int BOTTOM_FRONT_RIGHT = 0x00800000;
+ const int FRONT_LEFT_WIDE = 0x01000000;
+ const int FRONT_RIGHT_WIDE = 0x02000000;
+ const int LEFT_SURROUND = 0x04000000;
+ const int RIGHT_SURROUND = 0x08000000;
+
+ // Bit mask of Audio Locations
+ int bitmask;
+ }
+
+ parcelable OctetsPerCodecFrame {
+ int value;
+ }
+
+ parcelable CodecFrameBlocksPerSDU {
+ int value;
+ }
+
+ CodecFrameBlocksPerSDU codecFrameBlocksPerSDU;
+ SamplingFrequency samplingFrequency;
+ FrameDuration frameDuration;
+ AudioChannelAllocation audioChannelAllocation;
+ OctetsPerCodecFrame octetsPerCodecFrame;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ConfigurationFlags.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ConfigurationFlags.aidl
new file mode 100644
index 0000000..57c8be5
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ConfigurationFlags.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+/**
+ * Coding fetures
+ */
+@VintfStability
+parcelable ConfigurationFlags {
+ const int NONE = 0x0000;
+ /*
+ * Set for the lossless configurations
+ */
+ const int LOSSLESS = 0x0001;
+ /*
+ * Set for the low latency configurations
+ */
+ const int LOW_LATENCY = 0x0002;
+ /*
+ * When set, asymmetric configuration for SINK and SOURCE can be used.
+ * e.g. in GAMING mode stream for 32kHz and back channel for 16 kHz
+ */
+ const int ALLOW_ASYMMETRIC_CONFIGURATIONS = 0x0003;
+ /*
+ * Set for the spatial audio configurations
+ */
+ const int SPATIAL_AUDIO = 0x0004;
+ /*
+ * When set, BluetoothAudioProvider requests to receive ASE metadata.
+ * In such case onSinkAseMetadataChanged() and onSourceAseMetadataChanged
+ * will be called.
+ */
+ const int PROVIDE_ASE_METADATA = 0x0005;
+ /*
+ * Set for mono microphone configurations
+ */
+ const int MONO_MIC_CONFIGURATION = 0x0006;
+
+ int bitmask;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index b5c8a31..2e16f4e 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -21,11 +21,21 @@
import android.hardware.bluetooth.audio.A2dpRemoteCapabilities;
import android.hardware.bluetooth.audio.A2dpStatus;
import android.hardware.bluetooth.audio.AudioConfiguration;
+import android.hardware.bluetooth.audio.AudioContext;
import android.hardware.bluetooth.audio.BluetoothAudioStatus;
import android.hardware.bluetooth.audio.CodecId;
import android.hardware.bluetooth.audio.CodecParameters;
+import android.hardware.bluetooth.audio.CodecSpecificCapabilitiesLtv;
+import android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv;
+import android.hardware.bluetooth.audio.ConfigurationFlags;
import android.hardware.bluetooth.audio.IBluetoothAudioPort;
import android.hardware.bluetooth.audio.LatencyMode;
+import android.hardware.bluetooth.audio.LeAudioAseConfiguration;
+import android.hardware.bluetooth.audio.LeAudioBisConfiguration;
+import android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration.BroadcastStreamMap;
+import android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap;
+import android.hardware.bluetooth.audio.MetadataLtv;
+import android.hardware.bluetooth.audio.Phy;
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
@@ -124,4 +134,575 @@
*/
@nullable A2dpConfiguration getA2dpConfiguration(
in List<A2dpRemoteCapabilities> remoteA2dpCapabilities, in A2dpConfigurationHint hint);
+
+ /**
+ * Set specific codec priority
+ *
+ * It should be assumed that the external module will start with all its
+ * integrated codecs priority 0 by default.
+ *
+ * @param codecId: codecId
+ * @param priority: 0 for no priority, -1 for codec disabled,
+ * from 1 to N, where 1 is highest.
+ */
+ void setCodecPriority(in CodecId codecId, int priority);
+
+ /**
+ * LE Audio device Capabilities - as defined in Bluetooth Published Audio
+ * Capabilities Service specification, v1.0.1, Sec. 3.1: "Sink PAC", and
+ * Sec. 3.3: "Source PAC".
+ */
+ @VintfStability
+ parcelable LeAudioDeviceCapabilities {
+ /**
+ * Codec Identifier
+ */
+ CodecId codecId;
+ /**
+ * Codec capabilities, packed as LTV.
+ */
+ CodecSpecificCapabilitiesLtv[] codecSpecificCapabilities;
+ /**
+ * Vendor codec specific capabilities.
+ *
+ * This will not be parsed by the BT stack, but passed to the vendor
+ * module who can interpret this and based on that select the proper
+ * vendor specific codec configuration.
+ */
+ @nullable byte[] vendorCodecSpecificCapabilities;
+ /**
+ * Audio capabilities metadata, packed as LTV.
+ */
+ @nullable MetadataLtv[] metadata;
+ }
+
+ @VintfStability
+ parcelable LeAudioDataPathConfiguration {
+ /**
+ * Vendor specific data path identifier
+ */
+ int dataPathId;
+
+ /**
+ * Used in the HCI_LE_Setup_ISO_Data_Path (0x006E).
+ * As defined in Bluetooth Core Specification Version
+ * 5.3, Vol 4, Part E, Sec. 7.8.109: "LE Setup ISO Data Path command".
+ */
+ @VintfStability
+ parcelable IsoDataPathConfiguration {
+ /**
+ * Codec ID - Valid Codec Identifier matching the selected codec
+ */
+ CodecId codecId;
+ /**
+ * Whether the transparent air mode should be set as a coding format
+ * in the HCI_LE_Setup_ISO_Data_Path command, indicating that the
+ * codec is not in the controller.
+ *
+ * If set to true, 0x03 (transparent air mode) will be used as a
+ * Codec_ID coding format and the `byte[] configuration` field shall
+ * remain empty. Otherwise the Codec_ID field will be set to
+ * according to BT specification (0xFF coding format, company ID,
+ * codec ID for vendor codecs, or according to Codec_ID identifiers
+ * defined in the Assigned Numbers for the non-vendor codecs).
+ */
+ boolean isTransparent;
+ /**
+ * Controller delay (in microseconds)
+ */
+ int controllerDelayUs;
+ /**
+ * Codec specific LE Audio ISO data path configuration
+ * must be null when codec ID is 0x03 transparent
+ */
+ @nullable byte[] configuration;
+ }
+
+ /**
+ * Used in HCI_Configure_Data_Path (0x0083)
+ * As defined in Bluetooth Core Specification Version
+ * 5.3, Vol 4, Part E, Sec. 7.3.101: "Configure Data Path command".
+ */
+ @VintfStability
+ parcelable DataPathConfiguration {
+ /**
+ * Vendor specific data path configuration
+ */
+ @nullable byte[] configuration;
+ }
+ /**
+ * Data path configuration
+ */
+ DataPathConfiguration dataPathConfiguration;
+ /**
+ * ISO data path configuration
+ */
+ IsoDataPathConfiguration isoDataPathConfiguration;
+ }
+
+ /* All the LeAudioAseQosConfiguration parameters are defined by the
+ * Bluetooth Audio Stream Control Service specification v.1.0, Sec. 5: "ASE
+ * Control Operations".
+ */
+ @VintfStability
+ parcelable LeAudioAseQosConfiguration {
+ /**
+ * SDU Interval (in microseconds) used in Set CIG Parameters command and
+ * Configure QoS.
+ */
+ int sduIntervalUs;
+ /**
+ * Framing used in Set CIG Parameters command and Configure QoS
+ */
+ Framing framing;
+ /**
+ * Phy used in Set CIG Parameters command and Configure QoS
+ */
+ Phy[] phy;
+ /**
+ * Max transport latency (in milliseconds) used in Set CIG Parameters
+ * command and Configure QoS.
+ */
+ int maxTransportLatencyMs;
+ /**
+ * Max SDU used in Set CIG Parameters command and Configure QoS
+ */
+ int maxSdu;
+ /**
+ * Retransmission number used in Set CIG Parameters command and
+ * Configure QoS
+ */
+ int retransmissionNum;
+ }
+
+ /**
+ * Connected Isochronous Channel arrangement within the Connected
+ * Isochronous Group. As defined in Bluetooth Core Specification Version
+ * 5.3, Vol 4, Part E, Sec. 7.8.97.
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum Packing {
+ SEQUENTIAL = 0x00,
+ INTERLEAVED = 0x01,
+ }
+
+ /**
+ * Isochronous Data PDU framing parameter. As defined in Bluetooth Core
+ * Specification Version 5.3, Vol 4, Part E, Sec. 7.8.97.
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum Framing {
+ UNFRAMED = 0x00,
+ FRAMED = 0x01,
+ }
+
+ @VintfStability
+ parcelable LeAudioAseConfigurationSetting {
+ /**
+ * Audio Context that this configuration apply to
+ */
+ AudioContext audioContext;
+ /**
+ * Sequential or interleave packing used in Set CIG Parameters command
+ */
+ Packing packing;
+
+ @VintfStability
+ parcelable AseDirectionConfiguration {
+ /**
+ * ASE configuration
+ */
+ LeAudioAseConfiguration aseConfiguration;
+ /**
+ * QoS Configuration
+ */
+ @nullable LeAudioAseQosConfiguration qosConfiguration;
+ /**
+ * Data path configuration
+ * If not provided, getLeAudioAseDatapathConfiguration() will be
+ * called during the configuration, increasing the stream
+ * establishment time (not recommended).
+ */
+ @nullable LeAudioDataPathConfiguration dataPathConfiguration;
+ }
+ /**
+ * Sink ASEs configuration
+ */
+ @nullable List<AseDirectionConfiguration> sinkAseConfiguration;
+ /**
+ * Source ASEs configuration
+ */
+ @nullable List<AseDirectionConfiguration> sourceAseConfiguration;
+ /**
+ * Additional flags, used for configurations with special features
+ */
+ @nullable ConfigurationFlags flags;
+ }
+
+ /**
+ * ASE configuration requirements set by the BT stack.
+ */
+ @VintfStability
+ parcelable LeAudioConfigurationRequirement {
+ /**
+ * Audio Contect that this requirements apply to
+ */
+ AudioContext audioContext;
+
+ @VintfStability
+ parcelable AseDirectionRequirement {
+ /**
+ * Optional ASE configurations requirements
+ *
+ * Note that the Host can set as many or as little parameters in
+ * the `aseConfiguration.codecConfiguration` field as needed, to
+ * closely or loosely specify the requirements. If any parameter
+ * is not specified, the offloader can choose it freely. The
+ * offloader should put all the specified parameters into the
+ * `aseConfiguration.codecConfiguration` field of the returned
+ * configuration to let the BT stack verify if the requirements
+ * were met. The mandatory requirement set by the BT stack will be
+ * the Audio Location.
+ */
+ LeAudioAseConfiguration aseConfiguration;
+ }
+ /**
+ * Sink ASEs configuration setting
+ */
+ @nullable List<AseDirectionRequirement> sinkAseRequirement;
+ /**
+ * Source ASEs configuration setting
+ */
+ @nullable List<AseDirectionRequirement> sourceAseRequirement;
+ /**
+ * Additional flags, used to request configurations with special
+ * features
+ */
+ @nullable ConfigurationFlags flags;
+ }
+
+ /**
+ * Method that returns a proposed ASE configuration settings for each
+ * requested audio context type
+ *
+ * Note: _ENCODING session provides SINK ASE configuration
+ * and _DECODING session provides SOURCE ASE configuration unless
+ * BluetoothAudioProvider sets supportsMultidirectionalCapabilities to
+ * true in ProviderInfo.
+ * If supportsMultidirectionalCapabilities is set to true then the
+ * BluetoothStack expects to get configuration list for SINK and SOURCE
+ * on either _ENCODING or _DECODING session.
+ *
+ * @param remoteSinkAudioCapabilities List of remote sink capabilities
+ * supported by an active group devices.
+ * @param remoteSourceAudioCapabilities List of remote source capabilities
+ * supported by an active group devices.
+ * @param requirements ASE configuration requirements
+ *
+ * @return List<LeAudioAseConfigurationSetting>
+ */
+ List<LeAudioAseConfigurationSetting> getLeAudioAseConfiguration(
+ in @nullable List<LeAudioDeviceCapabilities> remoteSinkAudioCapabilities,
+ in @nullable List<LeAudioDeviceCapabilities> remoteSourceAudioCapabilities,
+ in List<LeAudioConfigurationRequirement> requirements);
+
+ @VintfStability
+ parcelable LeAudioAseQosConfigurationRequirement {
+ /**
+ * Audio Contect Type that this requirements apply to
+ */
+ AudioContext contextType;
+
+ /**
+ * QoS preferences received in Codec Configured ASE state. As defined in
+ * bluetooth service specification: Audio Stream Control Service" V1.0,
+ * Sec. 4.1 Audio Stream Endpoints, Table 4.3:"Additional_ASE_Parameters
+ * format when ASE_State = 0x01 (Codec Configured)".
+ */
+ @VintfStability
+ parcelable AseQosDirectionRequirement {
+ /**
+ * Support for unframed Isochronous Adaptation Layer PDUs.
+ * When set to FRAMED, the unframed PDUs are not supported.
+ */
+ Framing framing;
+ /**
+ * Preferred value for the PHY parameter to be written by the client
+ * for this ASE in the Config QoS operation
+ */
+ Phy[] preferredPhy;
+ /**
+ * Preferred value for the Retransmission Number parameter to be
+ * written by the client for this ASE in the Config QoS operation.
+ */
+ int preferredRetransmissionNum;
+ /**
+ * Preferred value for the Max Transport Latency parameter to be
+ * written by the client for this ASE in the Config QoS operation.
+ */
+ int maxTransportLatencyMs;
+ /**
+ * Minimum server supported Presentation Delay (in microseconds) for
+ * an ASE.
+ */
+ int presentationDelayMinUs;
+ /**
+ * Maximum server supported Presentation Delay (in microseconds) for
+ * an ASE.
+ */
+ int presentationDelayMaxUs;
+ /**
+ * Preferred minimum Presentation Delay (in microseconds) for an
+ * ASE.
+ */
+ int preferredPresentationDelayMinUs;
+ /**
+ * Preferred maximum Presentation Delay (in microseconds) for an
+ * ASE.
+ */
+ int preferredPresentationDelayMaxUs;
+
+ /**
+ * ASE configuration
+ */
+ LeAudioAseConfiguration aseConfiguration;
+ }
+ /**
+ * Sink ASEs configuration setting
+ */
+ @nullable AseQosDirectionRequirement sinkAseQosRequirement;
+ /**
+ * Source ASEs configuration setting
+ */
+ @nullable AseQosDirectionRequirement sourceAseQosRequirement;
+ /**
+ * Additional configuration flags requirements
+ */
+ @nullable ConfigurationFlags flags;
+ }
+
+ /**
+ * A directional pair for QoS configuration. Either one or both directions
+ * can be set, depending on the audio context and the requirements provided
+ * to getLeAudioAseQosConfiguration().
+ */
+ @VintfStability
+ parcelable LeAudioAseQosConfigurationPair {
+ @nullable LeAudioAseQosConfiguration sinkQosConfiguration;
+ @nullable LeAudioAseQosConfiguration sourceQosConfiguration;
+ }
+
+ /**
+ * Method that returns an ASE QoS configuration settings for the given ASE
+ * configuration,taking an ASE preferenced QoS parameters. It should be used
+ * to negotiaite the QoS parameters, when the initialy received QoS
+ * parameters are not within the boundaries received from the remote device
+ * after configuring the ASEs.
+ *
+ * @param qosRequirement ASE QoS configurations requirements
+ *
+ * @return LeAudioAseQosConfigurationPair
+ */
+ LeAudioAseQosConfigurationPair getLeAudioAseQosConfiguration(
+ in LeAudioAseQosConfigurationRequirement qosRequirement);
+
+ /**
+ * Audio data path configuration.
+ */
+ parcelable LeAudioDataPathConfigurationPair {
+ /* Host to Controller data path */
+ @nullable LeAudioDataPathConfiguration inputConfig;
+ /* Controller to Host data path */
+ @nullable LeAudioDataPathConfiguration outputConfig;
+ }
+
+ /**
+ * Used to get a data path configuration which dynamically depends on CIS
+ * connection handles in StreamMap. This is used if non-dynamic data path
+ * was not provided in LeAudioAseConfigurationSetting. Calling this during
+ * the unicast audio stream establishment might slightly delay the stream
+ * start.
+ */
+ LeAudioDataPathConfigurationPair getLeAudioAseDatapathConfiguration(
+ in AudioContext context, in StreamMap[] streamMap);
+
+ /*
+ * Audio Stream Endpoint state used to report Metadata changes on the remote
+ * device audio endpoints.
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum AseState {
+ ENABLING = 0x00,
+ STREAMING = 0x01,
+ DISABLING = 0x02,
+ }
+
+ /**
+ * Used to report metadata changes to the provider. This allows for a
+ * pseudo communication channel between the remote device and the provider,
+ * using the vendor specific metadata of the changing ASE state.
+ * It is used only when ASE is using configurations marked with the
+ * `PROVIDE_ASE_METADATA` flag.
+ */
+ void onSinkAseMetadataChanged(
+ in AseState state, int cigId, int cisId, in @nullable MetadataLtv[] metadata);
+ void onSourceAseMetadataChanged(
+ in AseState state, int cigId, int cisId, in @nullable MetadataLtv[] metadata);
+
+ /**
+ * Broadcast quality index
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum BroadcastQuality {
+ STANDARD,
+ HIGH,
+ }
+
+ /**
+ * It is used in LeAudioBroadcastConfigurationRequirement
+ */
+ @VintfStability
+ parcelable LeAudioBroadcastSubgroupConfigurationRequirement {
+ /**
+ * Streaming Audio Context for the given subgroup.
+ * This can serve as a hint for selecting the proper configuration by
+ * the offloader.
+ */
+ AudioContext context;
+ /**
+ * Streaming Broadcast Audio Quality
+ */
+ BroadcastQuality quality;
+ /**
+ * Number of BISes for the given subgroup
+ */
+ int bisNumPerSubgroup;
+ }
+
+ /**
+ * It is used in getLeAudioBroadcastConfiguration method
+ * If any group id is provided, the Provider should check Pacs capabilities
+ * of the group(s) and provide Broadcast configuration supported by the
+ * group.
+ */
+ @VintfStability
+ parcelable LeAudioBroadcastConfigurationRequirement {
+ List<LeAudioBroadcastSubgroupConfigurationRequirement> subgroupConfigurationRequirements;
+ }
+
+ /**
+ * Subgroup BIS configuration
+ *
+ */
+ @VintfStability
+ parcelable LeAudioSubgroupBisConfiguration {
+ /**
+ * The number of BISes with the given configuration
+ */
+ int numBis;
+ /**
+ * LE Audio BIS configuration for the `numBis` number of BISes
+ */
+ LeAudioBisConfiguration bisConfiguration;
+ }
+
+ /**
+ * Subgroup configuration with a list of BIS configurations
+ *
+ */
+ @VintfStability
+ parcelable LeAudioBroadcastSubgroupConfiguration {
+ List<LeAudioSubgroupBisConfiguration> bisConfigurations;
+
+ /**
+ * Vendor specific codec configuration for all the BISes inside this
+ * subgroup. Only the vendor specific part is needed, since the BT stack
+ * can derive the common subgroup configuration by intersecting the LTV
+ * formatted configuration of every BIS inside the subgroup.
+ * This will not be parsed by the BT stack but will be set as the codec
+ * specific configuration for the ongoing audio stream at the subgroup
+ * level of the audio announcement,The remote device will receive this
+ * information when being configured for receiveing a brodcast audio
+ * stream.
+ */
+ @nullable byte[] vendorCodecConfiguration;
+ }
+
+ /**
+ * LeAudioBroadcastConfigurationSetting is a result of
+ * getLeAudioBroadcastConfiguration. It is used in HCI_LE_Create_BIG command
+ * and for creating the Broadcast Announcements.
+ *
+ */
+ @VintfStability
+ parcelable LeAudioBroadcastConfigurationSetting {
+ /**
+ * SDU Interval (in microseconds) used in LE Create BIG command
+ */
+ int sduIntervalUs;
+ /**
+ * Total number of BISes in the BIG
+ */
+ int numBis;
+ /**
+ * Maximum size of an SDU in octets
+ */
+ int maxSduOctets;
+ /**
+ * Maximum transport latency (in milliseconds)
+ */
+ int maxTransportLatencyMs;
+ /**
+ * The number of times every PDU should be retransmitted
+ */
+ int retransmitionNum;
+ /**
+ * A list of PHYs used for transmission of PDUs of BISes in the BIG.
+ */
+ Phy[] phy;
+ /**
+ * The preferred method of arranging subevents of multiple BISes
+ */
+ Packing packing;
+ /**
+ * format for sending BIS Data PDUs
+ */
+ Framing framing;
+
+ /**
+ * Data path configuration
+ * If not provided, getLeAudioBroadcastDatapathConfiguration() will be
+ * called during the configuration, increasing the stream establishment
+ * time (not recommended).
+ */
+ @nullable LeAudioDataPathConfiguration dataPathConfiguration;
+
+ /**
+ * A list of subgroup configurations in the broadcast.
+ */
+ List<LeAudioBroadcastSubgroupConfiguration> subgroupsConfigurations;
+ }
+
+ /**
+ * Get Broadcast configuration. Output of this function will be used
+ * in HCI_LE_Create_BIG (0x0068) command and also to create BIG INFO
+ *
+ */
+ LeAudioBroadcastConfigurationSetting getLeAudioBroadcastConfiguration(
+ in @nullable List<LeAudioDeviceCapabilities> remoteSinkAudioCapabilities,
+ in LeAudioBroadcastConfigurationRequirement requirement);
+
+ /**
+ * Used to get a data path configuration which dynamically depends on BIS
+ * handles in BroadcastStreamMap. This is used if non-dynamic data path was
+ * not provided in LeAudioBroadcastConfigurationSetting. Calling this during
+ * the broadcast audio stream establishment might slightly delay the stream
+ * start.
+ */
+ LeAudioDataPathConfiguration getLeAudioBroadcastDatapathConfiguration(
+ in AudioContext context, in BroadcastStreamMap[] streamMap);
}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
index b9cec2d..ea9c4e1 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -69,19 +69,33 @@
* General information relative to a provider
* - An optional name
* - A list of codec information
+ * - supportsMultidirectionalCapabilities if is set to false it means each
+ * session i.e. _ENCODING and _DECODING is responsible to provide
+ * configuration for a single direction:
+ * _ENCODING for SINK ASE
+ * _DECODING for SOURCE ASE
+ *
+ * If supportsMultidirectionalCapabilities is set to true, then either
+ * _ENCODING or _DECODING session can provide the configurations for either
+ * direction.
*/
@VintfStability
parcelable ProviderInfo {
String name;
CodecInfo[] codecInfos;
+ boolean supportsMultidirectionalCapabilities;
}
/**
* Get general information relative to a provider.
*
+ * This can be called at any time, or just once during the BT stack
+ * initialization.
+ *
* @param sessionType Hardware Offload provider (*_HARDWARE_OFFLOAD_*)
* @return General information relative to the provider.
- * The `null` value can be returned when the provider is not available
+ * The `null` value can be returned when the provider is not
+ * available
*/
@nullable ProviderInfo getProviderInfo(in SessionType sessionType);
}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl
new file mode 100644
index 0000000..9fb2ecf
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.aidl
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecId;
+import android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv;
+import android.hardware.bluetooth.audio.MetadataLtv;
+import android.hardware.bluetooth.audio.Phy;
+
+/**
+ * All the LeAudioAseConfiguration parameters are defined by the Bluetooth Audio
+ * Stream Control Service specification v.1.0, Sec. 5: "ASE Control Operations".
+ */
+@VintfStability
+parcelable LeAudioAseConfiguration {
+ @VintfStability
+ @Backing(type="byte")
+ enum TargetLatency {
+ UNDEFINED = 0x00,
+ LOWER = 0x01,
+ BALANCED_LATENCY_RELIABILITY = 0x02,
+ HIGHER_RELIABILITY = 0x03,
+ }
+
+ /**
+ * Target latency used in Configure Codec command - Can be UNDEFINED when
+ * used inside the AseDirectionRequirement, but shall not be UNDEFINED when
+ * used inside LeAudioAseConfigurationSetting.
+ */
+ TargetLatency targetLatency;
+
+ /**
+ * Target PHY used in Configure Codec command - Can be UNDEFINED when used
+ * inside the AseDirectionRequirement, but shall not be UNDEFINED when used
+ * inside LeAudioAseConfigurationSetting.
+ */
+ Phy targetPhy;
+
+ /**
+ * Codec ID - Can be Null when used inside the AseDirectionRequirement, but
+ * shall not be Null when used inside LeAudioAseConfigurationSetting.
+ */
+ @nullable CodecId codecId;
+
+ /**
+ * Codec configuration for ASE represented in the LTV types defined by
+ * Bluetooth SIG. Regardless of vendor specific configuration being used or
+ * not, this shall contain Bluetooth LTV types describing the common stream
+ * parameters, at least CodecSpecificConfigurationLtv.SamplingFrequency and
+ * CodecSpecificConfigurationLtv.AudioChannelAllocation. In addition, it
+ * should match aseConfiguration provided in LeAudioConfigurationRequirement
+ * as this will also be used to verify the requirements on the known LTV
+ * types.
+ */
+ CodecSpecificConfigurationLtv[] codecConfiguration;
+
+ /**
+ * Vendor specific codec configuration for ASE.
+ *
+ * This will not be parsed by the BT stack but will be written to the remote
+ * device as the codec specific configuration as part of the codec configure
+ * control point operation. If this is populated, only the
+ * `vendorCodecConfiguration` will be used for the ASE configuration,
+ * otherwise `codecConfiguration` will be used. The BT stack will not merge
+ * it with the codecConfiguration for any purpose.
+ */
+ @nullable byte[] vendorCodecConfiguration;
+
+ /**
+ * Metadata, packed as LTV - used to enable ASE. This is optional
+ */
+ @nullable MetadataLtv[] metadata;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl
new file mode 100644
index 0000000..4d6cfde
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBisConfiguration.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecId;
+import android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv;
+import android.hardware.bluetooth.audio.MetadataLtv;
+
+/**
+ * LE Audio BIS configuration. This will be part of the streaming broadcast
+ * audio announcement advertised by the BT stack during the broadcast audio
+ * stream to inform the remote devices about the broadcast audio configuration.
+ * It will also be passed back to the vendor module as part of the currently
+ * active LeAudioBroadcastConfiguration for the encoder setup.
+ * As defined in Bluetooth Basic Audio Profile Specification, v.1.0.1,
+ * Sec. 3.7.2.2, Table 3.15, Level 3.
+ */
+@VintfStability
+parcelable LeAudioBisConfiguration {
+ /**
+ * Codec ID
+ */
+ CodecId codecId;
+
+ /**
+ * Codec configuration for BIS or group of BISes represented in the LTV
+ * types defined by Bluetooht SIG. Regardless of vendor specific
+ * configuration being used or not, this shall contain Bluetooth LTV types
+ * describing the common stream parameters, at least
+ * CodecSpecificConfigurationLtv.SamplingFrequency and
+ * CodecSpecificConfigurationLtv.AudioChannelAllocation.
+ * This will also be used to verify the requirements on the known LTV types.
+ */
+ CodecSpecificConfigurationLtv[] codecConfiguration;
+
+ /**
+ * Vendor specific codec configuration.
+ * This will not be parsed by the BT stack but will be set as the codec
+ * specific configuration for the ongoing audio stream, encoded by the
+ * vendor module. The remote device will receive this information when being
+ * configured for receiveing a brodcast audio stream. If this is populated,
+ * only the `vendorCodecConfiguration` will be used when configuring the
+ * remote device, otherwise `codecConfiguration` will be used.
+ */
+ byte[] vendorCodecConfiguration;
+
+ /**
+ * Metadata for the particular BIS or group of BISes. This is optional.
+ */
+ @nullable MetadataLtv[] metadata;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
index 16503fb..da90373 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -17,6 +17,8 @@
package android.hardware.bluetooth.audio;
import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.ConfigurationFlags;
+import android.hardware.bluetooth.audio.LeAudioBisConfiguration;
import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
@VintfStability
@@ -39,6 +41,15 @@
* Pcm stream id to identify the source for given streamHandle.
*/
char pcmStreamId;
+ /*
+ * LE Audio BIS configuration
+ */
+ @nullable LeAudioBisConfiguration bisConfiguration;
+ /*
+ * Additional flags, used to request configurations with special
+ * features
+ */
+ @nullable ConfigurationFlags flags;
}
CodecType codecType;
BroadcastStreamMap[] streamMap;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
index 7302aea..db753ad 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -17,6 +17,8 @@
package android.hardware.bluetooth.audio;
import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.ConfigurationFlags;
+import android.hardware.bluetooth.audio.LeAudioAseConfiguration;
import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
@VintfStability
@@ -29,16 +31,40 @@
*/
char streamHandle;
/*
- * Audio channel allocation is a bit field, each enabled bit means that given audio
- * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
- * least significant bit to the most significant bit. The valus follows the Bluetooth SIG
- * Audio Location assigned number.
+ * Audio channel allocation is a bit field, each enabled bit means that
+ * given audio direction, i.e. "left", or "right" is used. Ordering of
+ * audio channels comes from the least significant bit to the most
+ * significant bit. The valus follows the Bluetooth SIG Audio Location
+ * assigned number.
*/
int audioChannelAllocation;
/*
* The stream handle status
*/
boolean isStreamActive;
+ /*
+ * LE Audio device ASE configuration
+ */
+ @nullable LeAudioAseConfiguration aseConfiguration;
+ /*
+ * Additional flags, used for configurations with special features
+ */
+ @nullable ConfigurationFlags flags;
+ parcelable BluetoothDeviceAddress {
+ enum DeviceAddressType {
+ BLE_ADDRESS_PUBLIC = 0x00,
+ BLE_ADDRESS_RANDOM = 0x01,
+ }
+ /**
+ * Peer device address. It should be non zero when isStreamActive is true
+ */
+ byte[6] deviceAddress;
+ /**
+ * Peer device address type.
+ */
+ DeviceAddressType deviceAddressType;
+ }
+ @nullable BluetoothDeviceAddress bluetoothDeviceAddress;
}
CodecType codecType;
StreamMap[] streamMap;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/MetadataLtv.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/MetadataLtv.aidl
new file mode 100644
index 0000000..b0befc1
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/MetadataLtv.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioContext;
+
+/**
+ * Used to exchange generic metadata between the stack and the provider.
+ * As defined in Bluetooth Assigned Numbers, Sec. 6.12.6.
+ */
+@VintfStability
+union MetadataLtv {
+ parcelable PreferredAudioContexts {
+ AudioContext values;
+ }
+ parcelable StreamingAudioContexts {
+ AudioContext values;
+ }
+ /* This is an opaque container for passing metadata between the provider and
+ * the remote device. It must not be interpreted by the BT stack.
+ */
+ parcelable VendorSpecific {
+ int companyId;
+ byte[] opaqueValue;
+ }
+
+ PreferredAudioContexts preferredAudioContexts;
+ StreamingAudioContexts streamingAudioContexts;
+ VendorSpecific vendorSpecific;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Phy.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Phy.aidl
new file mode 100644
index 0000000..cbffdd5
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Phy.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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.bluetooth.audio;
+
+/**
+ * Used to exchange generic Phy parameter between the stack and the provider.
+ */
+@VintfStability
+@Backing(type="byte")
+enum Phy {
+ UNDEFINED = 0x00,
+ ONE_M = 0x01,
+ TWO_M = 0x02,
+ CODED = 0x03,
+}
diff --git a/bluetooth/audio/aidl/default/A2dpBits.h b/bluetooth/audio/aidl/default/A2dpBits.h
index f467c95..fb7587c 100644
--- a/bluetooth/audio/aidl/default/A2dpBits.h
+++ b/bluetooth/audio/aidl/default/A2dpBits.h
@@ -23,7 +23,8 @@
uint8_t* data_;
public:
- A2dpBits(const std::vector<uint8_t>& vector) : cdata_(vector.data()) {}
+ A2dpBits(const std::vector<uint8_t>& vector)
+ : cdata_(vector.data()), data_(nullptr) {}
A2dpBits(std::vector<uint8_t>& vector)
: cdata_(vector.data()), data_(vector.data()) {}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index b88e66a..bdba898 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -187,6 +187,120 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+ndk::ScopedAStatus BluetoothAudioProvider::setCodecPriority(
+ const ::aidl::android::hardware::bluetooth::audio::CodecId& in_codecId,
+ int32_t in_priority) {
+ /* TODO: Implement */
+ (void)in_codecId;
+ (void)in_priority;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseConfiguration(
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSinkAudioCapabilities,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSourceAudioCapabilities,
+ const std::vector<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioConfigurationRequirement>& in_requirements,
+ std::vector<::aidl::android::hardware::bluetooth::audio::
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
+ _aidl_return) {
+ /* TODO: Implement */
+ (void)in_remoteSinkAudioCapabilities;
+ (void)in_remoteSourceAudioCapabilities;
+ (void)in_requirements;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseQosConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioAseQosConfigurationRequirement& in_qosRequirement,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioAseQosConfigurationPair* _aidl_return) {
+ /* TODO: Implement */
+ (void)in_qosRequirement;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseDatapathConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::AudioContext& in_context,
+ const std::vector<::aidl::android::hardware::bluetooth::audio::
+ LeAudioConfiguration::StreamMap>& in_streamMap,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDataPathConfigurationPair* _aidl_return) {
+ /* TODO: Implement */
+ (void)in_context;
+ (void)in_streamMap;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::onSinkAseMetadataChanged(
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ AseState in_state,
+ int32_t cigId, int32_t cisId,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::MetadataLtv>>>&
+ in_metadata) {
+ /* TODO: Implement */
+ (void)in_state;
+ (void)cigId;
+ (void)cisId;
+ (void)in_metadata;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus BluetoothAudioProvider::onSourceAseMetadataChanged(
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ AseState in_state,
+ int32_t cigId, int32_t cisId,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::MetadataLtv>>>&
+ in_metadata) {
+ /* TODO: Implement */
+ (void)in_state;
+ (void)cigId;
+ (void)cisId;
+ (void)in_metadata;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioBroadcastConfiguration(
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSinkAudioCapabilities,
+ const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioBroadcastConfigurationRequirement& in_requirement,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioBroadcastConfigurationSetting* _aidl_return) {
+ /* TODO: Implement */
+ (void)in_remoteSinkAudioCapabilities;
+ (void)in_requirement;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus
+BluetoothAudioProvider::getLeAudioBroadcastDatapathConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::AudioContext& in_context,
+ const std::vector<::aidl::android::hardware::bluetooth::audio::
+ LeAudioBroadcastConfiguration::BroadcastStreamMap>&
+ in_streamMap,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDataPathConfiguration* _aidl_return) {
+ /* TODO: Implement */
+ (void)in_context;
+ (void)in_streamMap;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
} // namespace audio
} // namespace bluetooth
} // namespace hardware
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index 27ab13f..5064869 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -41,14 +41,73 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
- const std::vector<LatencyMode>& latency_modes,
- DataMQDesc* _aidl_return);
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return);
ndk::ScopedAStatus endSession();
ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
ndk::ScopedAStatus updateAudioConfiguration(
const AudioConfiguration& audio_config);
ndk::ScopedAStatus setLowLatencyModeAllowed(bool allowed);
+ ndk::ScopedAStatus setCodecPriority(
+ const ::aidl::android::hardware::bluetooth::audio::CodecId& in_codecId,
+ int32_t in_priority) override;
+ ndk::ScopedAStatus getLeAudioAseConfiguration(
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSinkAudioCapabilities,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSourceAudioCapabilities,
+ const std::vector<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioConfigurationRequirement>& in_requirements,
+ std::vector<::aidl::android::hardware::bluetooth::audio::
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
+ _aidl_return) override;
+ ndk::ScopedAStatus getLeAudioAseQosConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
+ in_qosRequirement,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioAseQosConfigurationPair* _aidl_return) override;
+ ndk::ScopedAStatus getLeAudioAseDatapathConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::AudioContext&
+ in_context,
+ const std::vector<::aidl::android::hardware::bluetooth::audio::
+ LeAudioConfiguration::StreamMap>& in_streamMap,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDataPathConfigurationPair* _aidl_return) override;
+ ndk::ScopedAStatus onSinkAseMetadataChanged(
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ AseState in_state,
+ int32_t cigId, int32_t cisId,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::MetadataLtv>>>&
+ in_metadata) override;
+ ndk::ScopedAStatus onSourceAseMetadataChanged(
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ AseState in_state,
+ int32_t cigId, int32_t cisId,
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::MetadataLtv>>>&
+ in_metadata) override;
+ ndk::ScopedAStatus getLeAudioBroadcastConfiguration(
+ const std::optional<std::vector<std::optional<
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDeviceCapabilities>>>& in_remoteSinkAudioCapabilities,
+ const ::aidl::android::hardware::bluetooth::audio::
+ IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
+ in_requirement,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioBroadcastConfigurationSetting* _aidl_return) override;
+ ndk::ScopedAStatus getLeAudioBroadcastDatapathConfiguration(
+ const ::aidl::android::hardware::bluetooth::audio::AudioContext&
+ in_context,
+ const std::vector<::aidl::android::hardware::bluetooth::audio::
+ LeAudioBroadcastConfiguration::BroadcastStreamMap>&
+ in_streamMap,
+ ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
+ LeAudioDataPathConfiguration* _aidl_return) override;
ndk::ScopedAStatus parseA2dpConfiguration(
const CodecId& codec_id, const std::vector<uint8_t>& configuration,
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index 3a64c4d..e55a434 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -37,6 +37,9 @@
namespace bluetooth {
namespace audio {
+static const std::string kLeAudioOffloadProviderName =
+ "LE_AUDIO_OFFLOAD_HARDWARE_OFFLOAD_PROVIDER";
+
BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {}
ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
@@ -151,6 +154,8 @@
SessionType session_type, std::optional<ProviderInfo>* _aidl_return) {
*_aidl_return = std::nullopt;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type);
+
if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
auto& provider_info = _aidl_return->emplace();
@@ -160,6 +165,23 @@
provider_info.codecInfos.push_back(codec->info);
}
+ if (session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ std::vector<CodecInfo> db_codec_info =
+ BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(session_type);
+ if (!db_codec_info.empty()) {
+ auto& provider_info = _aidl_return->emplace();
+ provider_info.name = kLeAudioOffloadProviderName;
+ provider_info.codecInfos = db_codec_info;
+ *_aidl_return = provider_info;
+ return ndk::ScopedAStatus::ok();
+ }
+ }
+
return ndk::ScopedAStatus::ok();
}
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 7f610ef..cff3b25 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -28,6 +28,73 @@
namespace bluetooth {
namespace audio {
+constexpr uint8_t kLeAudioDirectionSink = 0x01;
+constexpr uint8_t kLeAudioDirectionSource = 0x02;
+
+const std::map<CodecSpecificConfigurationLtv::SamplingFrequency, uint32_t>
+ freq_to_support_bitmask_map = {
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ11025},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ22050,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ22050},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ32000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ88200,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ88200},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ96000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ176400,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ176400},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ192000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ192000},
+ {CodecSpecificConfigurationLtv::SamplingFrequency::HZ384000,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ384000},
+};
+
+// Helper map from capability's tag to configuration's tag
+std::map<CodecSpecificCapabilitiesLtv::Tag, CodecSpecificConfigurationLtv::Tag>
+ cap_to_cfg_tag_map = {
+ {CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies,
+ CodecSpecificConfigurationLtv::Tag::samplingFrequency},
+ {CodecSpecificCapabilitiesLtv::Tag::supportedMaxCodecFramesPerSDU,
+ CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU},
+ {CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations,
+ CodecSpecificConfigurationLtv::Tag::frameDuration},
+ {CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts,
+ CodecSpecificConfigurationLtv::Tag::audioChannelAllocation},
+ {CodecSpecificCapabilitiesLtv::Tag::supportedOctetsPerCodecFrame,
+ CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame},
+};
+
+const std::map<CodecSpecificConfigurationLtv::FrameDuration, uint32_t>
+ fduration_to_support_fduration_map = {
+ {CodecSpecificConfigurationLtv::FrameDuration::US7500,
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500},
+ {CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000},
+};
+
+std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
+ sampling_freq_map = {
+ {16000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
+ {48000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000},
+ {96000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000},
+};
+
+std::map<int32_t, CodecSpecificConfigurationLtv::FrameDuration>
+ frame_duration_map = {
+ {7500, CodecSpecificConfigurationLtv::FrameDuration::US7500},
+ {10000, CodecSpecificConfigurationLtv::FrameDuration::US10000},
+};
+
LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
: LeAudioOffloadAudioProvider() {
session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
@@ -70,8 +137,8 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return BluetoothAudioProvider::startSession(
- host_if, audio_config, latency_modes, _aidl_return);
+ return BluetoothAudioProvider::startSession(host_if, audio_config,
+ latency_modes, _aidl_return);
}
ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
@@ -81,6 +148,644 @@
*_aidl_return = DataMQDesc();
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::setCodecPriority(
+ const CodecId& in_codecId, int32_t in_priority) {
+ codec_priority_map_[in_codecId] = in_priority;
+ return ndk::ScopedAStatus::ok();
+};
+
+bool LeAudioOffloadAudioProvider::isMatchedValidCodec(CodecId cfg_codec,
+ CodecId req_codec) {
+ auto priority = codec_priority_map_.find(cfg_codec);
+ if (priority != codec_priority_map_.end() && priority->second == -1)
+ return false;
+ return cfg_codec == req_codec;
+}
+
+bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedContext(
+ AudioContext setting_context,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
+ // If has no metadata, assume match
+ if (!capabilities.metadata.has_value()) return true;
+
+ for (auto metadata : capabilities.metadata.value()) {
+ if (!metadata.has_value()) continue;
+ if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
+ // Check all pref audio context to see if anything matched
+ auto& context = metadata.value()
+ .get<MetadataLtv::Tag::preferredAudioContexts>()
+ .values;
+ if (setting_context.bitmask & context.bitmask) return true;
+ }
+ }
+
+ return false;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedSamplingFreq(
+ CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
+ capability_freq) {
+ for (auto [freq, bitmask] : freq_to_support_bitmask_map)
+ if (cfg_freq == freq) return (capability_freq.bitmask & bitmask);
+ return false;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
+ CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
+ capability_fduration) {
+ for (auto [fduration, bitmask] : fduration_to_support_fduration_map)
+ if (cfg_fduration == fduration)
+ return (capability_fduration.bitmask & bitmask);
+ return false;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
+ CodecSpecificConfigurationLtv::AudioChannelAllocation&
+ /*cfg_channel*/,
+ CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
+ /*capability_channel*/) {
+ bool isMatched = true;
+ // TODO: how to match?
+ return isMatched;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
+ CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
+ CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
+ capability_frame_sdu) {
+ return cfg_frame_sdu.value <= capability_frame_sdu.value;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedOctetsPerCodecFrame(
+ CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
+ CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
+ capability_octets) {
+ return cfg_octets.value >= capability_octets.minimum &&
+ cfg_octets.value <= capability_octets.maximum;
+}
+
+bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
+ std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
+ std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities) {
+ // Convert all codec_cfg into a map of tags -> correct data
+ std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
+ cfg_tag_map;
+ for (auto codec_cfg_data : codec_cfg)
+ cfg_tag_map[codec_cfg_data.getTag()] = codec_cfg_data;
+
+ for (auto& codec_capability : codec_capabilities) {
+ auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
+ // Cannot find tag for the capability:
+ if (cfg == cfg_tag_map.end()) return false;
+
+ // Matching logic for sampling frequency
+ if (codec_capability.getTag() ==
+ CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies) {
+ if (!isMatchedSamplingFreq(
+ cfg->second
+ .get<CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
+ codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+ supportedSamplingFrequencies>()))
+ return false;
+ } else if (codec_capability.getTag() ==
+ CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations) {
+ if (!isMatchedFrameDuration(
+ cfg->second
+ .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
+ codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+ supportedFrameDurations>()))
+ return false;
+ } else if (codec_capability.getTag() ==
+ CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts) {
+ if (!isMatchedAudioChannel(
+ cfg->second.get<
+ CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>(),
+ codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+ supportedAudioChannelCounts>()))
+ return false;
+ } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
+ supportedMaxCodecFramesPerSDU) {
+ if (!isMatchedCodecFramesPerSDU(
+ cfg->second.get<
+ CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>(),
+ codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+ supportedMaxCodecFramesPerSDU>()))
+ return false;
+ } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
+ supportedOctetsPerCodecFrame) {
+ if (!isMatchedOctetsPerCodecFrame(
+ cfg->second.get<
+ CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
+ codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+ supportedOctetsPerCodecFrame>()))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
+ LeAudioAseConfiguration setting_cfg,
+ LeAudioAseConfiguration requirement_cfg) {
+ // Check matching for codec configuration <=> requirement ASE codec
+ // Also match if no CodecId requirement
+ if (requirement_cfg.codecId.has_value()) {
+ if (!setting_cfg.codecId.has_value()) return false;
+ if (!isMatchedValidCodec(setting_cfg.codecId.value(),
+ requirement_cfg.codecId.value()))
+ return false;
+ }
+
+ if (setting_cfg.targetLatency != requirement_cfg.targetLatency) return false;
+ // Ignore PHY requirement
+
+ // Check all codec configuration
+ std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
+ cfg_tag_map;
+ for (auto cfg : setting_cfg.codecConfiguration)
+ cfg_tag_map[cfg.getTag()] = cfg;
+
+ for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
+ // Directly compare CodecSpecificConfigurationLtv
+ auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
+ if (cfg == cfg_tag_map.end()) return false;
+
+ if (cfg->second != requirement_cfg) return false;
+ }
+ // Ignore vendor configuration and metadata requirement
+
+ return true;
+}
+
+bool LeAudioOffloadAudioProvider::isMatchedBISConfiguration(
+ LeAudioBisConfiguration bis_cfg,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
+ if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) return false;
+ if (!isCapabilitiesMatchedCodecConfiguration(
+ bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities))
+ return false;
+ return true;
+}
+
+void LeAudioOffloadAudioProvider::filterCapabilitiesAseDirectionConfiguration(
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ direction_configurations,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ valid_direction_configurations) {
+ for (auto direction_configuration : direction_configurations) {
+ if (!direction_configuration.has_value()) continue;
+ if (!direction_configuration.value().aseConfiguration.codecId.has_value())
+ continue;
+ if (!isMatchedValidCodec(
+ direction_configuration.value().aseConfiguration.codecId.value(),
+ capabilities.codecId))
+ continue;
+ // Check matching for codec configuration <=> codec capabilities
+ if (!isCapabilitiesMatchedCodecConfiguration(
+ direction_configuration.value().aseConfiguration.codecConfiguration,
+ capabilities.codecSpecificCapabilities))
+ continue;
+ valid_direction_configurations.push_back(direction_configuration);
+ }
+}
+
+void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ direction_configurations,
+ const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
+ requirements,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ valid_direction_configurations) {
+ for (auto direction_configuration : direction_configurations) {
+ if (!requirements.has_value()) {
+ // If there's no requirement, all are valid
+ valid_direction_configurations.push_back(direction_configuration);
+ continue;
+ }
+ if (!direction_configuration.has_value()) continue;
+
+ for (auto& requirement : requirements.value()) {
+ if (!requirement.has_value()) continue;
+ if (!isMatchedAseConfiguration(
+ direction_configuration.value().aseConfiguration,
+ requirement.value().aseConfiguration))
+ continue;
+ // Valid if match any requirement.
+ valid_direction_configurations.push_back(direction_configuration);
+ break;
+ }
+ }
+}
+
+/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
+ * capabilities. The new setting will have a filtered list of
+ * AseDirectionConfiguration that matched the capabilities */
+std::optional<LeAudioAseConfigurationSetting>
+LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
+ uint8_t direction) {
+ // Try to match context in metadata.
+ if (!isCapabilitiesMatchedContext(setting.audioContext, capabilities))
+ return std::nullopt;
+
+ // Get a list of all matched AseDirectionConfiguration
+ // for the input direction
+ std::vector<std::optional<AseDirectionConfiguration>>*
+ direction_configuration = nullptr;
+ if (direction == kLeAudioDirectionSink) {
+ if (!setting.sinkAseConfiguration.has_value()) return std::nullopt;
+ direction_configuration = &setting.sinkAseConfiguration.value();
+ } else {
+ if (!setting.sourceAseConfiguration.has_value()) return std::nullopt;
+ direction_configuration = &setting.sourceAseConfiguration.value();
+ }
+ std::vector<std::optional<AseDirectionConfiguration>>
+ valid_direction_configuration;
+ filterCapabilitiesAseDirectionConfiguration(
+ *direction_configuration, capabilities, valid_direction_configuration);
+ if (valid_direction_configuration.empty()) return std::nullopt;
+
+ // Create a new LeAudioAseConfigurationSetting and return
+ LeAudioAseConfigurationSetting filtered_setting;
+ filtered_setting.audioContext = setting.audioContext;
+ filtered_setting.packing = setting.packing;
+ if (direction == kLeAudioDirectionSink) {
+ filtered_setting.sinkAseConfiguration = valid_direction_configuration;
+ } else {
+ filtered_setting.sourceAseConfiguration = valid_direction_configuration;
+ }
+ filtered_setting.flags = setting.flags;
+
+ return filtered_setting;
+}
+
+/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
+ * requirement. The new setting will have a filtered list of
+ * AseDirectionConfiguration that matched the requirement */
+std::optional<LeAudioAseConfigurationSetting>
+LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
+ requirement) {
+ // Try to match context in metadata.
+ if (setting.audioContext != requirement.audioContext) return std::nullopt;
+
+ // Check requirement for the correct direction
+ const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
+ direction_requirement;
+ std::vector<std::optional<AseDirectionConfiguration>>*
+ direction_configuration;
+ if (setting.sinkAseConfiguration.has_value()) {
+ direction_configuration = &setting.sinkAseConfiguration.value();
+ direction_requirement = &requirement.sinkAseRequirement;
+ } else {
+ direction_configuration = &setting.sourceAseConfiguration.value();
+ direction_requirement = &requirement.sourceAseRequirement;
+ }
+
+ std::vector<std::optional<AseDirectionConfiguration>>
+ valid_direction_configuration;
+ filterRequirementAseDirectionConfiguration(*direction_configuration,
+ *direction_requirement,
+ valid_direction_configuration);
+ if (valid_direction_configuration.empty()) return std::nullopt;
+
+ // Create a new LeAudioAseConfigurationSetting and return
+ LeAudioAseConfigurationSetting filtered_setting;
+ filtered_setting.audioContext = setting.audioContext;
+ filtered_setting.packing = setting.packing;
+ if (setting.sinkAseConfiguration.has_value())
+ filtered_setting.sinkAseConfiguration = valid_direction_configuration;
+ else
+ filtered_setting.sourceAseConfiguration = valid_direction_configuration;
+ filtered_setting.flags = setting.flags;
+
+ return filtered_setting;
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSinkAudioCapabilities,
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSourceAudioCapabilities,
+ const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+ in_requirements,
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
+ _aidl_return) {
+ // Get all configuration settings
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ ase_configuration_settings =
+ BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
+
+ // Currently won't handle case where both sink and source capabilities
+ // are passed in. Only handle one of them.
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>*
+ in_remoteAudioCapabilities;
+ uint8_t direction = 0;
+ if (in_remoteSinkAudioCapabilities.has_value()) {
+ direction = kLeAudioDirectionSink;
+ in_remoteAudioCapabilities = &in_remoteSinkAudioCapabilities;
+ } else {
+ direction = kLeAudioDirectionSource;
+ in_remoteAudioCapabilities = &in_remoteSourceAudioCapabilities;
+ }
+
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ capability_matched_ase_configuration_settings;
+ // Matching with remote capabilities
+ for (auto& setting : ase_configuration_settings) {
+ for (auto& capability : in_remoteAudioCapabilities->value()) {
+ if (!capability.has_value()) continue;
+ auto filtered_ase_configuration_setting =
+ getCapabilitiesMatchedAseConfigurationSettings(
+ setting, capability.value(), direction);
+ if (filtered_ase_configuration_setting.has_value()) {
+ capability_matched_ase_configuration_settings.push_back(
+ filtered_ase_configuration_setting.value());
+ }
+ }
+ }
+
+ // Matching with requirements
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
+ for (auto& setting : capability_matched_ase_configuration_settings) {
+ for (auto& requirement : in_requirements) {
+ auto filtered_ase_configuration_setting =
+ getRequirementMatchedAseConfigurationSettings(setting, requirement);
+ if (filtered_ase_configuration_setting.has_value()) {
+ result.push_back(filtered_ase_configuration_setting.value());
+ }
+ }
+ }
+
+ *_aidl_return = result;
+ return ndk::ScopedAStatus::ok();
+};
+
+bool LeAudioOffloadAudioProvider::isMatchedQosRequirement(
+ LeAudioAseQosConfiguration setting_qos,
+ AseQosDirectionRequirement requirement_qos) {
+ if (setting_qos.retransmissionNum !=
+ requirement_qos.preferredRetransmissionNum)
+ return false;
+ if (setting_qos.maxTransportLatencyMs > requirement_qos.maxTransportLatencyMs)
+ return false;
+ // Ignore other parameters, as they are not populated in the setting_qos
+ return true;
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
+ const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
+ in_qosRequirement,
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+ // Get all configuration settings
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ ase_configuration_settings =
+ BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
+
+ // Direction QoS matching
+ // Only handle one direction input case
+ uint8_t direction = 0;
+ std::optional<AseQosDirectionRequirement> direction_qos_requirement =
+ std::nullopt;
+ if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
+ direction_qos_requirement = in_qosRequirement.sinkAseQosRequirement.value();
+ direction = kLeAudioDirectionSink;
+ } else if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
+ direction_qos_requirement =
+ in_qosRequirement.sourceAseQosRequirement.value();
+ direction = kLeAudioDirectionSource;
+ }
+
+ for (auto& setting : ase_configuration_settings) {
+ // Context matching
+ if (setting.audioContext != in_qosRequirement.contextType) continue;
+
+ // Match configuration flags
+ // Currently configuration flags are not populated, ignore.
+
+ // Get a list of all matched AseDirectionConfiguration
+ // for the input direction
+ std::vector<std::optional<AseDirectionConfiguration>>*
+ direction_configuration = nullptr;
+ if (direction == kLeAudioDirectionSink) {
+ if (!setting.sinkAseConfiguration.has_value()) continue;
+ direction_configuration = &setting.sinkAseConfiguration.value();
+ } else {
+ if (!setting.sourceAseConfiguration.has_value()) continue;
+ direction_configuration = &setting.sourceAseConfiguration.value();
+ }
+
+ for (auto cfg : *direction_configuration) {
+ if (!cfg.has_value()) continue;
+ // If no requirement, return the first QoS
+ if (!direction_qos_requirement.has_value()) {
+ result.sinkQosConfiguration = cfg.value().qosConfiguration;
+ result.sourceQosConfiguration = cfg.value().qosConfiguration;
+ *_aidl_return = result;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // If has requirement, return the first matched QoS
+ // Try to match the ASE configuration
+ // and QoS with requirement
+ if (!cfg.value().qosConfiguration.has_value()) continue;
+ if (isMatchedAseConfiguration(
+ cfg.value().aseConfiguration,
+ direction_qos_requirement.value().aseConfiguration) &&
+ isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
+ direction_qos_requirement.value())) {
+ if (direction == kLeAudioDirectionSink)
+ result.sinkQosConfiguration = cfg.value().qosConfiguration;
+ else
+ result.sourceQosConfiguration = cfg.value().qosConfiguration;
+ *_aidl_return = result;
+ return ndk::ScopedAStatus::ok();
+ }
+ }
+ }
+
+ // No match, return empty QoS
+ *_aidl_return = result;
+ return ndk::ScopedAStatus::ok();
+};
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSinkAseMetadataChanged(
+ IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
+ int32_t /*in_cisId*/,
+ const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
+ (void)in_state;
+ (void)in_metadata;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSourceAseMetadataChanged(
+ IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
+ int32_t /*in_cisId*/,
+ const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
+ (void)in_state;
+ (void)in_metadata;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+void LeAudioOffloadAudioProvider::getBroadcastSettings() {
+ if (!broadcast_settings.empty()) return;
+
+ LOG(INFO) << __func__ << ": Loading broadcast settings from provider info";
+
+ std::vector<CodecInfo> db_codec_info =
+ BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ broadcast_settings.clear();
+ CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
+ default_allocation.bitmask =
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
+
+ for (auto& codec_info : db_codec_info) {
+ if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
+ continue;
+ auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
+ LeAudioBroadcastConfigurationSetting setting;
+ // Default setting
+ setting.numBis = 1;
+ setting.phy = {Phy::TWO_M};
+ // Populate BIS configuration info using codec_info
+ LeAudioBisConfiguration bis_cfg;
+ bis_cfg.codecId = codec_info.id;
+
+ CodecSpecificConfigurationLtv::OctetsPerCodecFrame octets;
+ octets.value = transport.bitdepth[0];
+
+ bis_cfg.codecConfiguration = {
+ sampling_freq_map[transport.samplingFrequencyHz[0]], octets,
+ frame_duration_map[transport.frameDurationUs[0]], default_allocation};
+
+ // Add information to structure
+ IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
+ sub_bis_cfg.numBis = 1;
+ sub_bis_cfg.bisConfiguration = bis_cfg;
+ IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
+ sub_cfg.bisConfigurations = {sub_bis_cfg};
+ setting.subgroupsConfigurations = {sub_cfg};
+
+ broadcast_settings.push_back(setting);
+ }
+
+ LOG(INFO) << __func__
+ << ": Done loading broadcast settings from provider info";
+}
+
+/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
+ * capabilities. The new setting will have a filtered list of
+ * AseDirectionConfiguration that matched the capabilities */
+std::optional<LeAudioBroadcastConfigurationSetting>
+LeAudioOffloadAudioProvider::
+ getCapabilitiesMatchedBroadcastConfigurationSettings(
+ LeAudioBroadcastConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities&
+ capabilities) {
+ std::vector<IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration>
+ filter_subgroup;
+ for (auto& sub_cfg : setting.subgroupsConfigurations) {
+ std::vector<IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration>
+ filtered_bis_cfg;
+ for (auto& bis_cfg : sub_cfg.bisConfigurations)
+ if (isMatchedBISConfiguration(bis_cfg.bisConfiguration, capabilities)) {
+ filtered_bis_cfg.push_back(bis_cfg);
+ }
+ if (!filtered_bis_cfg.empty()) {
+ IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration
+ subgroup_cfg;
+ subgroup_cfg.bisConfigurations = filtered_bis_cfg;
+ filter_subgroup.push_back(subgroup_cfg);
+ }
+ }
+ if (filter_subgroup.empty()) return std::nullopt;
+
+ // Create a new LeAudioAseConfigurationSetting and return
+ LeAudioBroadcastConfigurationSetting filtered_setting(setting);
+ filtered_setting.subgroupsConfigurations = filter_subgroup;
+
+ return filtered_setting;
+}
+
+ndk::ScopedAStatus
+LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSinkAudioCapabilities,
+ const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
+ in_requirement,
+ LeAudioBroadcastConfigurationSetting* _aidl_return) {
+ getBroadcastSettings();
+ _aidl_return = nullptr;
+
+ // Match and filter capability
+ std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
+ if (!in_remoteSinkAudioCapabilities.has_value()) {
+ LOG(WARNING) << __func__ << ": Empty capability";
+ return ndk::ScopedAStatus::ok();
+ }
+ for (auto& setting : broadcast_settings) {
+ for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
+ if (!capability.has_value()) continue;
+ auto filtered_setting =
+ getCapabilitiesMatchedBroadcastConfigurationSettings(
+ setting, capability.value());
+ if (filtered_setting.has_value())
+ filtered_settings.push_back(filtered_setting.value());
+ }
+ }
+
+ if (filtered_settings.empty()) {
+ LOG(WARNING) << __func__ << ": Cannot match any remote capability";
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // Match and return the first matched requirement
+ if (in_requirement.subgroupConfigurationRequirements.empty()) {
+ LOG(INFO) << __func__ << ": Empty requirement";
+ *_aidl_return = filtered_settings[0];
+ return ndk::ScopedAStatus::ok();
+ }
+
+ for (auto& setting : filtered_settings) {
+ // Further filter out bis configuration
+ LeAudioBroadcastConfigurationSetting filtered_setting(setting);
+ filtered_setting.subgroupsConfigurations.clear();
+ for (auto& sub_cfg : setting.subgroupsConfigurations) {
+ bool isMatched = false;
+ for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
+ // Matching number of BIS
+ if (sub_req.bisNumPerSubgroup != sub_cfg.bisConfigurations.size())
+ continue;
+ // Currently will ignore quality and context hint.
+ isMatched = true;
+ break;
+ }
+ if (isMatched)
+ filtered_setting.subgroupsConfigurations.push_back(sub_cfg);
+ }
+ // Return the first match
+ if (!filtered_setting.subgroupsConfigurations.empty()) {
+ LOG(INFO) << __func__ << ": Matched requirement";
+ *_aidl_return = filtered_setting;
+ return ndk::ScopedAStatus::ok();
+ }
+ }
+
+ LOG(WARNING) << __func__ << ": Cannot match any requirement";
+ return ndk::ScopedAStatus::ok();
+};
} // namespace audio
} // namespace bluetooth
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 614c794..2785e7f 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -16,7 +16,12 @@
#pragma once
+#include <map>
+
#include "BluetoothAudioProvider.h"
+#include "aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.h"
+#include "aidl/android/hardware/bluetooth/audio/MetadataLtv.h"
+#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
namespace aidl {
namespace android {
@@ -24,6 +29,19 @@
namespace bluetooth {
namespace audio {
+using LeAudioAseConfigurationSetting =
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting;
+using AseDirectionRequirement = IBluetoothAudioProvider::
+ LeAudioConfigurationRequirement::AseDirectionRequirement;
+using AseDirectionConfiguration = IBluetoothAudioProvider::
+ LeAudioAseConfigurationSetting::AseDirectionConfiguration;
+using AseQosDirectionRequirement = IBluetoothAudioProvider::
+ LeAudioAseQosConfigurationRequirement::AseQosDirectionRequirement;
+using LeAudioAseQosConfiguration =
+ IBluetoothAudioProvider::LeAudioAseQosConfiguration;
+using LeAudioBroadcastConfigurationSetting =
+ IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting;
+
class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
public:
LeAudioOffloadAudioProvider();
@@ -33,11 +51,112 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
- const std::vector<LatencyMode>& latency_modes,
- DataMQDesc* _aidl_return);
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return);
+ ndk::ScopedAStatus setCodecPriority(const CodecId& in_codecId,
+ int32_t in_priority) override;
+ ndk::ScopedAStatus getLeAudioAseConfiguration(
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSinkAudioCapabilities,
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSourceAudioCapabilities,
+ const std::vector<
+ IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+ in_requirements,
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
+ _aidl_return) override;
+ ndk::ScopedAStatus getLeAudioAseQosConfiguration(
+ const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
+ in_qosRequirement,
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return)
+ override;
+ ndk::ScopedAStatus onSourceAseMetadataChanged(
+ IBluetoothAudioProvider::AseState in_state, int32_t in_cigId,
+ int32_t in_cisId,
+ const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata)
+ override;
+ ndk::ScopedAStatus onSinkAseMetadataChanged(
+ IBluetoothAudioProvider::AseState in_state, int32_t in_cigId,
+ int32_t in_cisId,
+ const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata)
+ override;
+ ndk::ScopedAStatus getLeAudioBroadcastConfiguration(
+ const std::optional<std::vector<
+ std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
+ in_remoteSinkAudioCapabilities,
+ const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
+ in_requirement,
+ LeAudioBroadcastConfigurationSetting* _aidl_return) override;
private:
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+ std::map<CodecId, uint32_t> codec_priority_map_;
+ std::vector<LeAudioBroadcastConfigurationSetting> broadcast_settings;
+
+ // Private matching function definitions
+ bool isMatchedValidCodec(CodecId cfg_codec, CodecId req_codec);
+ bool isCapabilitiesMatchedContext(
+ AudioContext setting_context,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
+ bool isMatchedSamplingFreq(
+ CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
+ capability_freq);
+ bool isMatchedFrameDuration(
+ CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
+ capability_fduration);
+ bool isMatchedAudioChannel(
+ CodecSpecificConfigurationLtv::AudioChannelAllocation& cfg_channel,
+ CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
+ capability_channel);
+ bool isMatchedCodecFramesPerSDU(
+ CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
+ CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
+ capability_frame_sdu);
+ bool isMatchedOctetsPerCodecFrame(
+ CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
+ CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
+ capability_octets);
+ bool isCapabilitiesMatchedCodecConfiguration(
+ std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
+ std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities);
+ bool isMatchedAseConfiguration(LeAudioAseConfiguration setting_cfg,
+ LeAudioAseConfiguration requirement_cfg);
+ bool isMatchedBISConfiguration(
+ LeAudioBisConfiguration bis_cfg,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
+ void filterCapabilitiesAseDirectionConfiguration(
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ direction_configurations,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ valid_direction_configurations);
+ void filterRequirementAseDirectionConfiguration(
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ direction_configurations,
+ const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
+ requirements,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ valid_direction_configurations);
+ std::optional<LeAudioAseConfigurationSetting>
+ getCapabilitiesMatchedAseConfigurationSettings(
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
+ uint8_t direction);
+ std::optional<LeAudioAseConfigurationSetting>
+ getRequirementMatchedAseConfigurationSettings(
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
+ requirement);
+ bool isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,
+ AseQosDirectionRequirement requirement_qos);
+ std::optional<LeAudioBroadcastConfigurationSetting>
+ getCapabilitiesMatchedBroadcastConfigurationSettings(
+ LeAudioBroadcastConfigurationSetting& setting,
+ const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
+ void getBroadcastSettings();
};
class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index 17be7be..88f2f97 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -46,6 +46,7 @@
using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::AudioContext;
using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
using aidl::android::hardware::bluetooth::audio::ChannelMode;
@@ -54,6 +55,8 @@
using aidl::android::hardware::bluetooth::audio::CodecId;
using aidl::android::hardware::bluetooth::audio::CodecInfo;
using aidl::android::hardware::bluetooth::audio::CodecParameters;
+using aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv;
+using aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv;
using aidl::android::hardware::bluetooth::audio::CodecType;
using aidl::android::hardware::bluetooth::audio::HfpConfiguration;
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
@@ -64,11 +67,13 @@
using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration;
using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
using aidl::android::hardware::bluetooth::audio::
LeAudioCodecCapabilitiesSetting;
using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::MetadataLtv;
using aidl::android::hardware::bluetooth::audio::OpusCapabilities;
using aidl::android::hardware::bluetooth::audio::OpusConfiguration;
using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
@@ -92,6 +97,21 @@
using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+using LeAudioAseConfigurationSetting =
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting;
+using AseDirectionRequirement = IBluetoothAudioProvider::
+ LeAudioConfigurationRequirement::AseDirectionRequirement;
+using AseDirectionConfiguration = IBluetoothAudioProvider::
+ LeAudioAseConfigurationSetting::AseDirectionConfiguration;
+using AseQosDirectionRequirement = IBluetoothAudioProvider::
+ LeAudioAseQosConfigurationRequirement::AseQosDirectionRequirement;
+using LeAudioAseQosConfiguration =
+ IBluetoothAudioProvider::LeAudioAseQosConfiguration;
+using LeAudioDeviceCapabilities =
+ IBluetoothAudioProvider::LeAudioDeviceCapabilities;
+using LeAudioConfigurationRequirement =
+ IBluetoothAudioProvider::LeAudioConfigurationRequirement;
+
// Constants
static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
@@ -197,6 +217,13 @@
virtual void TearDown() override { provider_factory_ = nullptr; }
+ void GetProviderInfoHelper(const SessionType& session_type) {
+ temp_provider_info_ = std::nullopt;
+ auto aidl_reval =
+ provider_factory_->getProviderInfo(session_type, &temp_provider_info_);
+ ASSERT_TRUE(aidl_reval.isOk());
+ }
+
void GetProviderCapabilitiesHelper(const SessionType& session_type) {
temp_provider_capabilities_.clear();
auto aidl_retval = provider_factory_->getProviderCapabilities(
@@ -576,6 +603,8 @@
std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
std::shared_ptr<IBluetoothAudioPort> audio_port_;
std::vector<AudioCapabilities> temp_provider_capabilities_;
+ std::optional<IBluetoothAudioProviderFactory::ProviderInfo>
+ temp_provider_info_;
// temp storage saves the specified codec capability by
// GetOffloadCodecCapabilityHelper()
@@ -1486,7 +1515,7 @@
}
bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
- ChannelMode channel_mode, int32_t data_interval_us) {
+ ChannelMode channel_mode, int32_t data_interval_us) {
PcmConfiguration pcm_config{
.sampleRateHz = sample_rate,
.channelMode = channel_mode,
@@ -1523,9 +1552,9 @@
for (auto sample_rate : hfp_sample_rates_) {
for (auto bits_per_sample : hfp_bits_per_samples_) {
for (auto channel_mode : hfp_channel_modes_) {
- for (auto data_interval_us: hfp_data_interval_us_) {
- EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample,
- channel_mode, data_interval_us));
+ for (auto data_interval_us : hfp_data_interval_us_) {
+ EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample, channel_mode,
+ data_interval_us));
EXPECT_TRUE(audio_provider_->endSession().isOk());
}
}
@@ -1553,7 +1582,7 @@
}
bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
- ChannelMode channel_mode, int32_t data_interval_us) {
+ ChannelMode channel_mode, int32_t data_interval_us) {
PcmConfiguration pcm_config{
.sampleRateHz = sample_rate,
.channelMode = channel_mode,
@@ -1587,10 +1616,10 @@
for (auto sample_rate : hfp_sample_rates_) {
for (auto bits_per_sample : hfp_bits_per_samples_) {
for (auto channel_mode : hfp_channel_modes_) {
- for (auto data_interval_us: hfp_data_interval_us_) {
- EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample,
- channel_mode, data_interval_us));
- EXPECT_TRUE(audio_provider_->endSession().isOk());
+ for (auto data_interval_us : hfp_data_interval_us_) {
+ EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample, channel_mode,
+ data_interval_us));
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
}
}
}
@@ -1870,7 +1899,7 @@
}
bool OpenSession(CodecId codec_id, int connection_handle, bool nrec,
- bool controller_codec) {
+ bool controller_codec) {
// Check if can open session with a Hfp configuration
HfpConfiguration hfp_configuration{
.codecId = codec_id,
@@ -2126,6 +2155,8 @@
BluetoothAudioProviderFactoryAidl::SetUp();
GetProviderCapabilitiesHelper(
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ GetProviderInfoHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
OpenProviderHelper(
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
@@ -2152,6 +2183,99 @@
return false;
}
+ bool IsOffloadOutputProviderInfoSupported() {
+ if (!temp_provider_info_.has_value()) return false;
+ if (temp_provider_info_.value().codecInfos.empty()) return false;
+ // Check if all codec info is of LeAudio type
+ for (auto& codec_info : temp_provider_info_.value().codecInfos) {
+ if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
+ return false;
+ }
+ return true;
+ }
+
+ std::vector<Lc3Configuration> GetUnicastLc3SupportedListFromProviderInfo() {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ for (auto& codec_info : temp_provider_info_.value().codecInfos) {
+ // Only gets LC3 codec information
+ if (codec_info.id != CodecId::Core::LC3) continue;
+ // Combine those parameters into one list of Lc3Configuration
+ auto& transport =
+ codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ for (int32_t samplingFrequencyHz : transport.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : transport.frameDurationUs) {
+ for (int32_t octetsPerFrame : transport.bitdepth) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
+ AudioContext GetAudioContext(int32_t bitmask) {
+ AudioContext media_audio_context;
+ media_audio_context.bitmask = bitmask;
+ return media_audio_context;
+ }
+
+ LeAudioDeviceCapabilities GetDefaultRemoteCapability() {
+ // Create a capability
+ LeAudioDeviceCapabilities capability;
+
+ capability.codecId = CodecId::Core::LC3;
+
+ auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
+ pref_context_metadata.values = GetAudioContext(AudioContext::MEDIA);
+ capability.metadata = {pref_context_metadata};
+
+ auto sampling_rate =
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
+ sampling_rate.bitmask =
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000;
+ auto frame_duration =
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
+ frame_duration.bitmask =
+ CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500;
+ auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
+ octets.minimum = 0;
+ octets.maximum = 60;
+ auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
+ frames.value = 2;
+ capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
+ octets, frames};
+ return capability;
+ }
+
+ LeAudioConfigurationRequirement GetDefaultRequirement(
+ bool is_source_requriement) {
+ // Create a requirements
+ LeAudioConfigurationRequirement requirement;
+ requirement.audioContext = GetAudioContext(AudioContext::MEDIA);
+
+ auto direction_ase_requriement = AseDirectionRequirement();
+ direction_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
+ direction_ase_requriement.aseConfiguration.targetLatency =
+ LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
+
+ // Mismatch sampling frequency
+ direction_ase_requriement.aseConfiguration.codecConfiguration = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025,
+ CodecSpecificConfigurationLtv::FrameDuration::US7500,
+ };
+ if (is_source_requriement)
+ requirement.sourceAseRequirement = {direction_ase_requriement};
+ else
+ requirement.sinkAseRequirement = {direction_ase_requriement};
+ return requirement;
+ }
+
std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
bool supported) {
std::vector<Lc3Configuration> le_audio_codec_configs;
@@ -2269,6 +2393,14 @@
}
LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+ std::vector<int32_t> all_context_bitmasks = {
+ AudioContext::UNSPECIFIED, AudioContext::CONVERSATIONAL,
+ AudioContext::MEDIA, AudioContext::GAME,
+ AudioContext::INSTRUCTIONAL, AudioContext::VOICE_ASSISTANTS,
+ AudioContext::LIVE_AUDIO, AudioContext::SOUND_EFFECTS,
+ AudioContext::NOTIFICATIONS, AudioContext::RINGTONE_ALERTS,
+ AudioContext::ALERTS, AudioContext::EMERGENCY_ALARM,
+ };
};
/**
@@ -2282,6 +2414,101 @@
/**
* Test whether each provider of type
* SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config taken from provider info
+ */
+TEST_P(
+ BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossibleUnicastConfigFromProviderInfo) {
+ if (!IsOffloadOutputProviderInfoSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetUnicastLc3SupportedListFromProviderInfo();
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ GetEmptyAseConfigurationEmptyCapability) {
+ std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+ std::vector<LeAudioConfigurationRequirement> empty_requirement;
+ std::vector<LeAudioAseConfigurationSetting> configurations;
+
+ // Check empty capability for source direction
+ auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+ std::nullopt, empty_capability, empty_requirement, &configurations);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ ASSERT_TRUE(configurations.empty());
+
+ // Check empty capability for sink direction
+ aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+ empty_capability, std::nullopt, empty_requirement, &configurations);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ ASSERT_TRUE(configurations.empty());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ GetEmptyAseConfigurationMismatchedRequirement) {
+ std::vector<std::optional<LeAudioDeviceCapabilities>> capabilities = {
+ GetDefaultRemoteCapability()};
+
+ // Check empty capability for source direction
+ std::vector<LeAudioAseConfigurationSetting> configurations;
+ std::vector<LeAudioConfigurationRequirement> source_requirements = {
+ GetDefaultRequirement(true)};
+ auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+ std::nullopt, capabilities, source_requirements, &configurations);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ ASSERT_TRUE(configurations.empty());
+
+ // Check empty capability for sink direction
+ std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+ GetDefaultRequirement(false)};
+ aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+ capabilities, std::nullopt, source_requirements, &configurations);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ ASSERT_TRUE(configurations.empty());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl, GetQoSConfiguration) {
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement requirement;
+ std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
+ QoSConfigurations;
+ for (auto bitmask : all_context_bitmasks) {
+ requirement.contextType = GetAudioContext(bitmask);
+ IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+ auto aidl_retval =
+ audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
+ ASSERT_TRUE(aidl_retval.isOk());
+ if (result.sinkQosConfiguration.has_value())
+ QoSConfigurations.push_back(result.sinkQosConfiguration.value());
+ if (result.sourceQosConfiguration.has_value())
+ QoSConfigurations.push_back(result.sourceQosConfiguration.value());
+ }
+ // QoS Configurations should not be empty, as we searched for all contexts
+ ASSERT_FALSE(QoSConfigurations.empty());
+}
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
* stopped with Unicast hardware encoding config
*/
TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
@@ -2435,6 +2662,8 @@
BluetoothAudioProviderFactoryAidl::SetUp();
GetProviderCapabilitiesHelper(
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ GetProviderInfoHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
OpenProviderHelper(
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
@@ -2464,7 +2693,7 @@
/**
* Test whether each provider of type
- * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
* stopped
*/
TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
@@ -2472,7 +2701,38 @@
/**
* Test whether each provider of type
- * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config taken from provider info
+ */
+TEST_P(
+ BluetoothAudioProviderLeAudioInputHardwareAidl,
+ StartAndEndLeAudioInputSessionWithPossibleUnicastConfigFromProviderInfo) {
+ if (!IsOffloadOutputProviderInfoSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetUnicastLc3SupportedListFromProviderInfo();
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
* stopped with Unicast hardware encoding config
*/
TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
@@ -2503,7 +2763,7 @@
/**
* Test whether each provider of type
- * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
* stopped with Unicast hardware encoding config
*
* Disabled since offload codec checking is not ready
@@ -2621,6 +2881,8 @@
BluetoothAudioProviderFactoryAidl::SetUp();
GetProviderCapabilitiesHelper(
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ GetProviderInfoHelper(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
OpenProviderHelper(
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
@@ -2647,6 +2909,42 @@
return false;
}
+ bool IsBroadcastOffloadProviderInfoSupported() {
+ if (!temp_provider_info_.has_value()) return false;
+ if (temp_provider_info_.value().codecInfos.empty()) return false;
+ // Check if all codec info is of LeAudio type
+ for (auto& codec_info : temp_provider_info_.value().codecInfos) {
+ if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
+ return false;
+ }
+ return true;
+ }
+
+ std::vector<Lc3Configuration> GetBroadcastLc3SupportedListFromProviderInfo() {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ for (auto& codec_info : temp_provider_info_.value().codecInfos) {
+ // Only gets LC3 codec information
+ if (codec_info.id != CodecId::Core::LC3) continue;
+ // Combine those parameters into one list of Lc3Configuration
+ auto& transport =
+ codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ for (int32_t samplingFrequencyHz : transport.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : transport.frameDurationUs) {
+ for (int32_t octetsPerFrame : transport.bitdepth) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
std::vector<Lc3Configuration> le_audio_codec_configs;
if (!supported) {
@@ -2708,6 +3006,60 @@
/**
* Test whether each provider of type
* SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with broadcast hardware encoding config taken from
+ * provider info
+ */
+TEST_P(
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ StartAndEndLeAudioBroadcastSessionWithPossibleUnicastConfigFromProviderInfo) {
+ if (!IsBroadcastOffloadProviderInfoSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetBroadcastLc3SupportedListFromProviderInfo();
+ LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+ .codecType = CodecType::LC3,
+ .streamMap = {},
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_broadcast_config.streamMap.resize(1);
+ le_audio_broadcast_config.streamMap[0]
+ .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+ lc3_config);
+ le_audio_broadcast_config.streamMap[0].streamHandle = 0x0;
+ le_audio_broadcast_config.streamMap[0].pcmStreamId = 0x0;
+ le_audio_broadcast_config.streamMap[0].audioChannelAllocation = 0x1 << 0;
+
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_broadcast_config),
+ latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ GetEmptyBroadcastConfigurationEmptyCapability) {
+ std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+ IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
+ empty_requirement;
+
+ IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting* configuration =
+ new IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting();
+
+ // Check empty capability for source direction
+ auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
+ empty_capability, empty_requirement, configuration);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
* started and stopped with broadcast hardware encoding config
*/
TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
diff --git a/bluetooth/audio/flags/Android.bp b/bluetooth/audio/flags/Android.bp
new file mode 100644
index 0000000..0d18a4d
--- /dev/null
+++ b/bluetooth/audio/flags/Android.bp
@@ -0,0 +1,12 @@
+aconfig_declarations {
+ name: "btaudiohal_flags",
+ package: "com.android.btaudio.hal.flags",
+ srcs: ["btaudiohal.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "btaudiohal_flags_c_lib",
+ aconfig_declarations: "btaudiohal_flags",
+ vendor: true,
+ host_supported: true,
+}
diff --git a/bluetooth/audio/flags/btaudiohal.aconfig b/bluetooth/audio/flags/btaudiohal.aconfig
new file mode 100644
index 0000000..763777e
--- /dev/null
+++ b/bluetooth/audio/flags/btaudiohal.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.btaudio.hal.flags"
+
+flag {
+ name: "dsa_lea"
+ namespace: "pixel_bluetooth"
+ description: "Flag for DSA Over LEA"
+ bug: "270987427"
+}
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index e7659a4..c0817f5 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -42,6 +42,7 @@
"aidl_session/BluetoothAudioSession.cpp",
"aidl_session/HidlToAidlMiddleware.cpp",
"aidl_session/BluetoothLeAudioCodecsProvider.cpp",
+ "aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp",
],
export_include_dirs: ["aidl_session/"],
header_libs: [
@@ -61,9 +62,23 @@
"liblog",
"libhidlbase",
"libxml2",
+ "libflatbuffers-cpp",
+ "server_configurable_flags",
+ ],
+ static_libs: [
+ "btaudiohal_flags_c_lib",
],
generated_sources: ["le_audio_codec_capabilities"],
- generated_headers: ["le_audio_codec_capabilities"],
+ generated_headers: [
+ "le_audio_codec_capabilities",
+ "AIDLLeAudioSetConfigSchemas_h",
+ ],
+ required: [
+ "aidl_audio_set_configurations_bfbs",
+ "aidl_audio_set_configurations_json",
+ "aidl_audio_set_scenarios_bfbs",
+ "aidl_audio_set_scenarios_json",
+ ],
}
cc_test {
@@ -98,3 +113,81 @@
api_dir: "le_audio_codec_capabilities/schema",
root_elements: ["leAudioOffloadSetting"],
}
+
+genrule {
+ name: "AIDLLeAudioSetConfigSchemas_h",
+ tools: [
+ "flatc",
+ ],
+ cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -o $(genDir) --cpp $(in) ",
+ srcs: [
+ "le_audio_configuration_set/audio_set_configurations.fbs",
+ "le_audio_configuration_set/audio_set_scenarios.fbs",
+ ],
+ out: [
+ "audio_set_configurations_generated.h",
+ "audio_set_scenarios_generated.h",
+ ],
+}
+
+// Binary generation
+genrule {
+ name: "AIDLLeAudioSetScenariosSchema_bfbs",
+ tools: [
+ "flatc",
+ ],
+ cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ",
+ srcs: [
+ "le_audio_configuration_set/audio_set_scenarios.fbs",
+ ],
+ out: [
+ "audio_set_scenarios.bfbs",
+ ],
+}
+
+genrule {
+ name: "AIDLLeAudioSetConfigsSchema_bfbs",
+ tools: [
+ "flatc",
+ ],
+ cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ",
+ srcs: [
+ "le_audio_configuration_set/audio_set_configurations.fbs",
+ ],
+ out: [
+ "audio_set_configurations.bfbs",
+ ],
+}
+
+// Add to prebuilt etc
+prebuilt_etc {
+ name: "aidl_audio_set_scenarios_bfbs",
+ src: ":AIDLLeAudioSetScenariosSchema_bfbs",
+ filename: "aidl_audio_set_scenarios.bfbs",
+ sub_dir: "aidl/le_audio",
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "aidl_audio_set_scenarios_json",
+ src: "le_audio_configuration_set/audio_set_scenarios.json",
+ filename: "aidl_audio_set_scenarios.json",
+ sub_dir: "aidl/le_audio",
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "aidl_audio_set_configurations_bfbs",
+ src: ":AIDLLeAudioSetConfigsSchema_bfbs",
+ filename: "aidl_audio_set_configurations.bfbs",
+ sub_dir: "aidl/le_audio",
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "aidl_audio_set_configurations_json",
+ src: "le_audio_configuration_set/audio_set_configurations.json",
+ filename: "aidl_audio_set_configurations.json",
+ sub_dir: "aidl/le_audio",
+ vendor: true,
+}
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index 6e15b3b..216e169 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -32,6 +32,7 @@
#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
#include <android-base/logging.h>
+#include "BluetoothLeAudioAseConfigurationSettingProvider.h"
#include "BluetoothLeAudioCodecsProvider.h"
namespace aidl {
@@ -97,6 +98,8 @@
{.codecType = CodecType::OPUS, .capabilities = {}}};
std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
+std::unordered_map<SessionType, std::vector<CodecInfo>>
+ kDefaultOffloadLeAudioCodecInfoMap;
template <class T>
bool BluetoothAudioCodecs::ContainedInVector(
@@ -411,6 +414,37 @@
return kDefaultOffloadLeAudioCapabilities;
}
+std::vector<CodecInfo> BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
+ const SessionType& session_type) {
+ if (session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return std::vector<CodecInfo>();
+ }
+
+ if (kDefaultOffloadLeAudioCodecInfoMap.empty()) {
+ auto le_audio_offload_setting =
+ BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile();
+ auto kDefaultOffloadLeAudioCodecInfoMap =
+ BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
+ le_audio_offload_setting);
+ }
+ auto codec_info_map_iter =
+ kDefaultOffloadLeAudioCodecInfoMap.find(session_type);
+ if (codec_info_map_iter == kDefaultOffloadLeAudioCodecInfoMap.end())
+ return std::vector<CodecInfo>();
+ return codec_info_map_iter->second;
+}
+
+std::vector<LeAudioAseConfigurationSetting>
+BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings() {
+ return AudioSetConfigurationProviderJson::
+ GetLeAudioAseConfigurationSettings();
+}
+
} // namespace audio
} // namespace bluetooth
} // namespace hardware
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
index e3d657b..057b9a7 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -18,6 +18,8 @@
#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h>
#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecInfo.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
#include <aidl/android/hardware/bluetooth/audio/OpusConfiguration.h>
@@ -33,6 +35,9 @@
namespace bluetooth {
namespace audio {
+using LeAudioAseConfigurationSetting =
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting;
+
class BluetoothAudioCodecs {
public:
static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities();
@@ -46,6 +51,11 @@
static std::vector<LeAudioCodecCapabilitiesSetting>
GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
+ static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo(
+ const SessionType& session_type);
+
+ static std::vector<LeAudioAseConfigurationSetting>
+ GetLeAudioAseConfigurationSettings();
private:
template <typename T>
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 3519ace..67ba93c 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -20,6 +20,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android/binder_manager.h>
+#include <com_android_btaudio_hal_flags.h>
#include <hardware/audio.h>
#include "BluetoothAudioSession.h"
@@ -36,6 +37,14 @@
static constexpr int kWritePollMs = 1; // polled non-blocking interval
static constexpr int kReadPollMs = 1; // polled non-blocking interval
+static std::string toString(const std::vector<LatencyMode>& latencies) {
+ std::stringstream latencyModesStr;
+ for (LatencyMode mode : latencies) {
+ latencyModesStr << " " << toString(mode);
+ }
+ return latencyModesStr.str();
+}
+
BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
: session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
@@ -65,6 +74,7 @@
stack_iface_ = stack_iface;
latency_modes_ = latency_modes;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " - All LatencyModes=" << toString(latency_modes)
<< ", AudioConfiguration=" << audio_config.toString();
ReportSessionStatus();
}
@@ -490,14 +500,12 @@
<< " has NO session";
return false;
}
- bool retval = false;
-
if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
<< toString(session_type_) << " failed";
return false;
}
- return retval;
+ return true;
}
void BluetoothAudioSession::UpdateSourceMetadata(
@@ -604,31 +612,46 @@
return std::vector<LatencyMode>();
}
- std::vector<LatencyMode> supported_latency_modes;
- if (session_type_ ==
- SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
- for (LatencyMode mode : latency_modes_) {
- if (mode == LatencyMode::LOW_LATENCY) {
- // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
- continue;
+ if (com::android::btaudio::hal::flags::dsa_lea()) {
+ std::vector<LatencyMode> supported_latency_modes;
+ if (session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY) {
+ // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
}
- supported_latency_modes.push_back(mode);
+ } else {
+ for (LatencyMode mode : latency_modes_) {
+ if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
+ // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
+ continue;
+ }
+ if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
+ mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
+ // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC
+ // sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
+ }
}
- } else {
- for (LatencyMode mode : latency_modes_) {
- if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
- // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
- continue;
- }
- if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
- mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
- // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC sessions
- continue;
- }
- supported_latency_modes.push_back(mode);
- }
+ LOG(DEBUG) << __func__ << " - Supported LatencyMode="
+ << toString(supported_latency_modes);
+ return supported_latency_modes;
}
- return supported_latency_modes;
+
+ if (low_latency_allowed_) return latency_modes_;
+ std::vector<LatencyMode> modes;
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY)
+ // ignore those low latency mode if Bluetooth stack doesn't allow
+ continue;
+ modes.push_back(mode);
+ }
+ return modes;
}
void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
new file mode 100644
index 0000000..5429a8f
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -0,0 +1,760 @@
+/*
+ * Copyright (C) 2023 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 STREAM_TO_UINT8(u8, p) \
+ { \
+ (u8) = (uint8_t)(*(p)); \
+ (p) += 1; \
+ }
+#define STREAM_TO_UINT16(u16, p) \
+ { \
+ (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+ (p) += 2; \
+ }
+#define STREAM_TO_UINT32(u32, p) \
+ { \
+ (u32) = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + \
+ ((((uint32_t)(*((p) + 2)))) << 16) + \
+ ((((uint32_t)(*((p) + 3)))) << 24)); \
+ (p) += 4; \
+ }
+
+#define LOG_TAG "BTAudioAseConfigAidl"
+
+#include "BluetoothLeAudioAseConfigurationSettingProvider.h"
+
+#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/AudioContext.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecId.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h>
+#include <aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/Phy.h>
+#include <android-base/logging.h>
+
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+/* Internal structure definition */
+std::map<std::string,
+ std::tuple<std::vector<std::optional<AseDirectionConfiguration>>,
+ std::vector<std::optional<AseDirectionConfiguration>>,
+ ConfigurationFlags>>
+ configurations_;
+
+std::vector<LeAudioAseConfigurationSetting> ase_configuration_settings_;
+
+constexpr uint8_t kIsoDataPathHci = 0x00;
+constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
+constexpr uint8_t kIsoDataPathDisabled = 0xFF;
+
+constexpr uint8_t kLeAudioDirectionSink = 0x01;
+constexpr uint8_t kLeAudioDirectionSource = 0x02;
+constexpr uint8_t kLeAudioDirectionBoth =
+ kLeAudioDirectionSink | kLeAudioDirectionSource;
+
+/* Sampling Frequencies */
+constexpr uint8_t kLeAudioSamplingFreq8000Hz = 0x01;
+constexpr uint8_t kLeAudioSamplingFreq11025Hz = 0x02;
+constexpr uint8_t kLeAudioSamplingFreq16000Hz = 0x03;
+constexpr uint8_t kLeAudioSamplingFreq22050Hz = 0x04;
+constexpr uint8_t kLeAudioSamplingFreq24000Hz = 0x05;
+constexpr uint8_t kLeAudioSamplingFreq32000Hz = 0x06;
+constexpr uint8_t kLeAudioSamplingFreq44100Hz = 0x07;
+constexpr uint8_t kLeAudioSamplingFreq48000Hz = 0x08;
+constexpr uint8_t kLeAudioSamplingFreq88200Hz = 0x09;
+constexpr uint8_t kLeAudioSamplingFreq96000Hz = 0x0A;
+constexpr uint8_t kLeAudioSamplingFreq176400Hz = 0x0B;
+constexpr uint8_t kLeAudioSamplingFreq192000Hz = 0x0C;
+constexpr uint8_t kLeAudioSamplingFreq384000Hz = 0x0D;
+
+/* Frame Durations */
+constexpr uint8_t kLeAudioCodecFrameDur7500us = 0x00;
+constexpr uint8_t kLeAudioCodecFrameDur10000us = 0x01;
+
+/* Audio Allocations */
+constexpr uint32_t kLeAudioLocationNotAllowed = 0x00000000;
+constexpr uint32_t kLeAudioLocationFrontLeft = 0x00000001;
+constexpr uint32_t kLeAudioLocationFrontRight = 0x00000002;
+constexpr uint32_t kLeAudioLocationFrontCenter = 0x00000004;
+constexpr uint32_t kLeAudioLocationLowFreqEffects1 = 0x00000008;
+constexpr uint32_t kLeAudioLocationBackLeft = 0x00000010;
+constexpr uint32_t kLeAudioLocationBackRight = 0x00000020;
+constexpr uint32_t kLeAudioLocationFrontLeftOfCenter = 0x00000040;
+constexpr uint32_t kLeAudioLocationFrontRightOfCenter = 0x00000080;
+constexpr uint32_t kLeAudioLocationBackCenter = 0x00000100;
+constexpr uint32_t kLeAudioLocationLowFreqEffects2 = 0x00000200;
+constexpr uint32_t kLeAudioLocationSideLeft = 0x00000400;
+constexpr uint32_t kLeAudioLocationSideRight = 0x00000800;
+constexpr uint32_t kLeAudioLocationTopFrontLeft = 0x00001000;
+constexpr uint32_t kLeAudioLocationTopFrontRight = 0x00002000;
+constexpr uint32_t kLeAudioLocationTopFrontCenter = 0x00004000;
+constexpr uint32_t kLeAudioLocationTopCenter = 0x00008000;
+constexpr uint32_t kLeAudioLocationTopBackLeft = 0x00010000;
+constexpr uint32_t kLeAudioLocationTopBackRight = 0x00020000;
+constexpr uint32_t kLeAudioLocationTopSideLeft = 0x00040000;
+constexpr uint32_t kLeAudioLocationTopSideRight = 0x00080000;
+constexpr uint32_t kLeAudioLocationTopBackCenter = 0x00100000;
+constexpr uint32_t kLeAudioLocationBottomFrontCenter = 0x00200000;
+constexpr uint32_t kLeAudioLocationBottomFrontLeft = 0x00400000;
+constexpr uint32_t kLeAudioLocationBottomFrontRight = 0x00800000;
+constexpr uint32_t kLeAudioLocationFrontLeftWide = 0x01000000;
+constexpr uint32_t kLeAudioLocationFrontRightWide = 0x02000000;
+constexpr uint32_t kLeAudioLocationLeftSurround = 0x04000000;
+constexpr uint32_t kLeAudioLocationRightSurround = 0x08000000;
+
+constexpr uint32_t kLeAudioLocationAnyLeft =
+ kLeAudioLocationFrontLeft | kLeAudioLocationBackLeft |
+ kLeAudioLocationFrontLeftOfCenter | kLeAudioLocationSideLeft |
+ kLeAudioLocationTopFrontLeft | kLeAudioLocationTopBackLeft |
+ kLeAudioLocationTopSideLeft | kLeAudioLocationBottomFrontLeft |
+ kLeAudioLocationFrontLeftWide | kLeAudioLocationLeftSurround;
+
+constexpr uint32_t kLeAudioLocationAnyRight =
+ kLeAudioLocationFrontRight | kLeAudioLocationBackRight |
+ kLeAudioLocationFrontRightOfCenter | kLeAudioLocationSideRight |
+ kLeAudioLocationTopFrontRight | kLeAudioLocationTopBackRight |
+ kLeAudioLocationTopSideRight | kLeAudioLocationBottomFrontRight |
+ kLeAudioLocationFrontRightWide | kLeAudioLocationRightSurround;
+
+constexpr uint32_t kLeAudioLocationStereo =
+ kLeAudioLocationFrontLeft | kLeAudioLocationFrontRight;
+
+/* Octets Per Frame */
+constexpr uint16_t kLeAudioCodecFrameLen30 = 30;
+constexpr uint16_t kLeAudioCodecFrameLen40 = 40;
+constexpr uint16_t kLeAudioCodecFrameLen60 = 60;
+constexpr uint16_t kLeAudioCodecFrameLen80 = 80;
+constexpr uint16_t kLeAudioCodecFrameLen100 = 100;
+constexpr uint16_t kLeAudioCodecFrameLen120 = 120;
+
+/* Helper map for matching various sampling frequency notations */
+const std::map<uint8_t, CodecSpecificConfigurationLtv::SamplingFrequency>
+ sampling_freq_map = {
+ {kLeAudioSamplingFreq8000Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000},
+ {kLeAudioSamplingFreq16000Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
+ {kLeAudioSamplingFreq24000Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
+ {kLeAudioSamplingFreq32000Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000},
+ {kLeAudioSamplingFreq44100Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ44100},
+ {kLeAudioSamplingFreq48000Hz,
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000}};
+
+/* Helper map for matching various frame durations notations */
+const std::map<uint8_t, CodecSpecificConfigurationLtv::FrameDuration>
+ frame_duration_map = {
+ {kLeAudioCodecFrameDur7500us,
+ CodecSpecificConfigurationLtv::FrameDuration::US7500},
+ {kLeAudioCodecFrameDur10000us,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000}};
+
+/* Helper map for matching various audio channel allocation notations */
+std::map<uint32_t, uint32_t> audio_channel_allocation_map = {
+ {kLeAudioLocationNotAllowed,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::NOT_ALLOWED},
+ {kLeAudioLocationFrontLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT},
+ {kLeAudioLocationFrontRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT},
+ {kLeAudioLocationFrontCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER},
+ {kLeAudioLocationLowFreqEffects1,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::
+ LOW_FREQUENCY_EFFECTS_1},
+ {kLeAudioLocationBackLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_LEFT},
+ {kLeAudioLocationBackRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_RIGHT},
+ {kLeAudioLocationFrontLeftOfCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::
+ FRONT_LEFT_OF_CENTER},
+ {kLeAudioLocationFrontRightOfCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::
+ FRONT_RIGHT_OF_CENTER},
+ {kLeAudioLocationBackCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_CENTER},
+ {kLeAudioLocationLowFreqEffects2,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::
+ LOW_FREQUENCY_EFFECTS_2},
+ {kLeAudioLocationSideLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_LEFT},
+ {kLeAudioLocationSideRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_RIGHT},
+ {kLeAudioLocationTopFrontLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_LEFT},
+ {kLeAudioLocationTopFrontRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_RIGHT},
+ {kLeAudioLocationTopFrontCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_CENTER},
+ {kLeAudioLocationTopCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_CENTER},
+ {kLeAudioLocationTopBackLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_LEFT},
+ {kLeAudioLocationTopBackRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_RIGHT},
+ {kLeAudioLocationTopSideLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_LEFT},
+ {kLeAudioLocationTopSideRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_RIGHT},
+ {kLeAudioLocationTopBackCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_CENTER},
+ {kLeAudioLocationBottomFrontCenter,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::
+ BOTTOM_FRONT_CENTER},
+ {kLeAudioLocationBottomFrontLeft,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_LEFT},
+ {kLeAudioLocationBottomFrontRight,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_RIGHT},
+ {kLeAudioLocationFrontLeftWide,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT_WIDE},
+ {kLeAudioLocationFrontRightWide,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT_WIDE},
+ {kLeAudioLocationLeftSurround,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::LEFT_SURROUND},
+ {kLeAudioLocationRightSurround,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::RIGHT_SURROUND},
+};
+
+static const std::vector<
+ std::pair<const char* /*schema*/, const char* /*content*/>>
+ kLeAudioSetConfigs = {{"/vendor/etc/aidl/le_audio/"
+ "aidl_audio_set_configurations.bfbs",
+ "/vendor/etc/aidl/le_audio/"
+ "aidl_audio_set_configurations.json"}};
+static const std::vector<
+ std::pair<const char* /*schema*/, const char* /*content*/>>
+ kLeAudioSetScenarios = {{"/vendor/etc/aidl/le_audio/"
+ "aidl_audio_set_scenarios.bfbs",
+ "/vendor/etc/aidl/le_audio/"
+ "aidl_audio_set_scenarios.json"}};
+
+/* Implementation */
+
+std::vector<LeAudioAseConfigurationSetting>
+AudioSetConfigurationProviderJson::GetLeAudioAseConfigurationSettings() {
+ AudioSetConfigurationProviderJson::LoadAudioSetConfigurationProviderJson();
+ return ase_configuration_settings_;
+}
+
+void AudioSetConfigurationProviderJson::
+ LoadAudioSetConfigurationProviderJson() {
+ if (configurations_.empty() || ase_configuration_settings_.empty()) {
+ ase_configuration_settings_.clear();
+ configurations_.clear();
+ auto loaded = LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios,
+ CodecLocation::HOST);
+ if (!loaded)
+ LOG(ERROR) << ": Unable to load le audio set configuration files.";
+ } else
+ LOG(INFO) << ": Reusing loaded le audio set configuration";
+}
+
+const le_audio::CodecSpecificConfiguration*
+AudioSetConfigurationProviderJson::LookupCodecSpecificParam(
+ const flatbuffers::Vector<flatbuffers::Offset<
+ le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params,
+ le_audio::CodecSpecificLtvGenericTypes type) {
+ auto it = std::find_if(
+ flat_codec_specific_params->cbegin(), flat_codec_specific_params->cend(),
+ [&type](const auto& csc) { return (csc->type() == type); });
+ return (it != flat_codec_specific_params->cend()) ? *it : nullptr;
+}
+
+void AudioSetConfigurationProviderJson::populateAudioChannelAllocation(
+ CodecSpecificConfigurationLtv::AudioChannelAllocation&
+ audio_channel_allocation,
+ uint32_t audio_location) {
+ audio_channel_allocation.bitmask = 0;
+ for (auto [allocation, bitmask] : audio_channel_allocation_map) {
+ if (audio_location & allocation)
+ audio_channel_allocation.bitmask |= bitmask;
+ }
+}
+
+void AudioSetConfigurationProviderJson::populateConfigurationData(
+ LeAudioAseConfiguration& ase,
+ const flatbuffers::Vector<
+ flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>*
+ flat_codec_specific_params) {
+ uint8_t sampling_frequency = 0;
+ uint8_t frame_duration = 0;
+ uint32_t audio_channel_allocation = 0;
+ uint16_t octets_per_codec_frame = 0;
+ uint8_t codec_frames_blocks_per_sdu = 0;
+
+ auto param = LookupCodecSpecificParam(
+ flat_codec_specific_params,
+ le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_SAMPLING_FREQUENCY);
+ if (param) {
+ auto ptr = param->compound_value()->value()->data();
+ STREAM_TO_UINT8(sampling_frequency, ptr);
+ }
+
+ param = LookupCodecSpecificParam(
+ flat_codec_specific_params,
+ le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_FRAME_DURATION);
+ if (param) {
+ auto ptr = param->compound_value()->value()->data();
+ STREAM_TO_UINT8(frame_duration, ptr);
+ }
+
+ param = LookupCodecSpecificParam(
+ flat_codec_specific_params,
+ le_audio::
+ CodecSpecificLtvGenericTypes_SUPPORTED_AUDIO_CHANNEL_ALLOCATION);
+ if (param) {
+ auto ptr = param->compound_value()->value()->data();
+ STREAM_TO_UINT32(audio_channel_allocation, ptr);
+ }
+
+ param = LookupCodecSpecificParam(
+ flat_codec_specific_params,
+ le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_OCTETS_PER_CODEC_FRAME);
+ if (param) {
+ auto ptr = param->compound_value()->value()->data();
+ STREAM_TO_UINT16(octets_per_codec_frame, ptr);
+ }
+
+ param = LookupCodecSpecificParam(
+ flat_codec_specific_params,
+ le_audio::
+ CodecSpecificLtvGenericTypes_SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU);
+ if (param) {
+ auto ptr = param->compound_value()->value()->data();
+ STREAM_TO_UINT8(codec_frames_blocks_per_sdu, ptr);
+ }
+
+ // Make the correct value
+ ase.codecConfiguration = std::vector<CodecSpecificConfigurationLtv>();
+
+ auto sampling_freq_it = sampling_freq_map.find(sampling_frequency);
+ if (sampling_freq_it != sampling_freq_map.end())
+ ase.codecConfiguration.push_back(sampling_freq_it->second);
+ auto frame_duration_it = frame_duration_map.find(frame_duration);
+ if (frame_duration_it != frame_duration_map.end())
+ ase.codecConfiguration.push_back(frame_duration_it->second);
+
+ CodecSpecificConfigurationLtv::AudioChannelAllocation channel_allocation;
+ populateAudioChannelAllocation(channel_allocation, audio_channel_allocation);
+ ase.codecConfiguration.push_back(channel_allocation);
+
+ auto octet_structure = CodecSpecificConfigurationLtv::OctetsPerCodecFrame();
+ octet_structure.value = octets_per_codec_frame;
+ ase.codecConfiguration.push_back(octet_structure);
+
+ auto frame_sdu_structure =
+ CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU();
+ frame_sdu_structure.value = codec_frames_blocks_per_sdu;
+ ase.codecConfiguration.push_back(frame_sdu_structure);
+ // TODO: Channel count
+}
+
+void AudioSetConfigurationProviderJson::populateAseConfiguration(
+ LeAudioAseConfiguration& ase,
+ const le_audio::AudioSetSubConfiguration* flat_subconfig,
+ const le_audio::QosConfiguration* qos_cfg) {
+ // Target latency
+ switch (qos_cfg->target_latency()) {
+ case le_audio::AudioSetConfigurationTargetLatency::
+ AudioSetConfigurationTargetLatency_BALANCED_RELIABILITY:
+ ase.targetLatency =
+ LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
+ break;
+ case le_audio::AudioSetConfigurationTargetLatency::
+ AudioSetConfigurationTargetLatency_HIGH_RELIABILITY:
+ ase.targetLatency =
+ LeAudioAseConfiguration::TargetLatency::HIGHER_RELIABILITY;
+ break;
+ case le_audio::AudioSetConfigurationTargetLatency::
+ AudioSetConfigurationTargetLatency_LOW:
+ ase.targetLatency = LeAudioAseConfiguration::TargetLatency::LOWER;
+ break;
+ default:
+ ase.targetLatency = LeAudioAseConfiguration::TargetLatency::UNDEFINED;
+ break;
+ };
+
+ ase.targetPhy = Phy::TWO_M;
+ // Making CodecId
+ if (flat_subconfig->codec_id()->coding_format() ==
+ (uint8_t)CodecId::Core::LC3) {
+ ase.codecId = CodecId::Core::LC3;
+ } else {
+ auto vendorC = CodecId::Vendor();
+ vendorC.codecId = flat_subconfig->codec_id()->vendor_codec_id();
+ vendorC.id = flat_subconfig->codec_id()->vendor_company_id();
+ ase.codecId = vendorC;
+ }
+ // Codec configuration data
+ populateConfigurationData(ase, flat_subconfig->codec_configuration());
+}
+
+void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
+ LeAudioAseQosConfiguration& qos,
+ const le_audio::QosConfiguration* qos_cfg) {
+ qos.maxTransportLatencyMs = qos_cfg->max_transport_latency();
+ qos.retransmissionNum = qos_cfg->retransmission_number();
+}
+
+// Parse into AseDirectionConfiguration
+AseDirectionConfiguration
+AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
+ const le_audio::AudioSetSubConfiguration* flat_subconfig,
+ const le_audio::QosConfiguration* qos_cfg, CodecLocation location) {
+ AseDirectionConfiguration direction_conf;
+
+ LeAudioAseConfiguration ase;
+ LeAudioAseQosConfiguration qos;
+ LeAudioDataPathConfiguration path;
+
+ // Translate into LeAudioAseConfiguration
+ populateAseConfiguration(ase, flat_subconfig, qos_cfg);
+
+ // Translate into LeAudioAseQosConfiguration
+ populateAseQosConfiguration(qos, qos_cfg);
+
+ // Translate location to data path id
+ switch (location) {
+ case CodecLocation::ADSP:
+ path.isoDataPathConfiguration.isTransparent = true;
+ path.dataPathId = kIsoDataPathPlatformDefault;
+ break;
+ case CodecLocation::HOST:
+ path.isoDataPathConfiguration.isTransparent = true;
+ path.dataPathId = kIsoDataPathHci;
+ break;
+ case CodecLocation::CONTROLLER:
+ path.isoDataPathConfiguration.isTransparent = false;
+ path.dataPathId = kIsoDataPathPlatformDefault;
+ break;
+ }
+
+ direction_conf.aseConfiguration = ase;
+ direction_conf.qosConfiguration = qos;
+ direction_conf.dataPathConfiguration = path;
+
+ return direction_conf;
+}
+
+// Parse into AseDirectionConfiguration and the ConfigurationFlags
+// and put them in the given list.
+void AudioSetConfigurationProviderJson::processSubconfig(
+ const le_audio::AudioSetSubConfiguration* subconfig,
+ const le_audio::QosConfiguration* qos_cfg,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ directionAseConfiguration,
+ CodecLocation location) {
+ directionAseConfiguration.push_back(
+ SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location));
+}
+
+void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
+ const le_audio::AudioSetConfiguration* flat_cfg,
+ std::vector<const le_audio::CodecConfiguration*>* codec_cfgs,
+ std::vector<const le_audio::QosConfiguration*>* qos_cfgs,
+ CodecLocation location,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ sourceAseConfiguration,
+ std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration,
+ ConfigurationFlags& /*configurationFlags*/) {
+ if (flat_cfg == nullptr) {
+ LOG(ERROR) << "flat_cfg cannot be null";
+ return;
+ }
+ std::string codec_config_key = flat_cfg->codec_config_name()->str();
+ auto* qos_config_key_array = flat_cfg->qos_config_name();
+
+ constexpr std::string_view default_qos = "QoS_Config_Balanced_Reliability";
+
+ std::string qos_sink_key(default_qos);
+ std::string qos_source_key(default_qos);
+
+ /* We expect maximum two QoS settings. First for Sink and second for Source
+ */
+ if (qos_config_key_array->size() > 0) {
+ qos_sink_key = qos_config_key_array->Get(0)->str();
+ if (qos_config_key_array->size() > 1) {
+ qos_source_key = qos_config_key_array->Get(1)->str();
+ } else {
+ qos_source_key = qos_sink_key;
+ }
+ }
+
+ LOG(INFO) << "Audio set config " << flat_cfg->name()->c_str()
+ << ": codec config " << codec_config_key.c_str() << ", qos_sink "
+ << qos_sink_key.c_str() << ", qos_source "
+ << qos_source_key.c_str();
+
+ // Find the first qos config that match the name
+ const le_audio::QosConfiguration* qos_sink_cfg = nullptr;
+ for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
+ if ((*i)->name()->str() == qos_sink_key) {
+ qos_sink_cfg = *i;
+ break;
+ }
+ }
+
+ const le_audio::QosConfiguration* qos_source_cfg = nullptr;
+ for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
+ if ((*i)->name()->str() == qos_source_key) {
+ qos_source_cfg = *i;
+ break;
+ }
+ }
+
+ // First codec_cfg with the same name
+ const le_audio::CodecConfiguration* codec_cfg = nullptr;
+ for (auto i = codec_cfgs->begin(); i != codec_cfgs->end(); ++i) {
+ if ((*i)->name()->str() == codec_config_key) {
+ codec_cfg = *i;
+ break;
+ }
+ }
+
+ // Process each subconfig and put it into the correct list
+ if (codec_cfg != nullptr && codec_cfg->subconfigurations()) {
+ /* Load subconfigurations */
+ for (auto subconfig : *codec_cfg->subconfigurations()) {
+ if (subconfig->direction() == kLeAudioDirectionSink) {
+ processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
+ location);
+ } else {
+ processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
+ location);
+ }
+ }
+ } else {
+ if (codec_cfg == nullptr) {
+ LOG(ERROR) << "No codec config matching key " << codec_config_key.c_str()
+ << " found";
+ } else {
+ LOG(ERROR) << "Configuration '" << flat_cfg->name()->c_str()
+ << "' has no valid subconfigurations.";
+ }
+ }
+
+ // TODO: Populate information for ConfigurationFlags
+}
+
+bool AudioSetConfigurationProviderJson::LoadConfigurationsFromFiles(
+ const char* schema_file, const char* content_file, CodecLocation location) {
+ flatbuffers::Parser configurations_parser_;
+ std::string configurations_schema_binary_content;
+ bool ok = flatbuffers::LoadFile(schema_file, true,
+ &configurations_schema_binary_content);
+ LOG(INFO) << __func__ << ": Loading file " << schema_file;
+ if (!ok) return ok;
+
+ /* Load the binary schema */
+ ok = configurations_parser_.Deserialize(
+ (uint8_t*)configurations_schema_binary_content.c_str(),
+ configurations_schema_binary_content.length());
+ if (!ok) return ok;
+
+ /* Load the content from JSON */
+ std::string configurations_json_content;
+ LOG(INFO) << __func__ << ": Loading file " << content_file;
+ ok = flatbuffers::LoadFile(content_file, false, &configurations_json_content);
+ if (!ok) return ok;
+
+ /* Parse */
+ LOG(INFO) << __func__ << ": Parse JSON content";
+ ok = configurations_parser_.Parse(configurations_json_content.c_str());
+ if (!ok) return ok;
+
+ /* Import from flatbuffers */
+ LOG(INFO) << __func__ << ": Build flat buffer structure";
+ auto configurations_root = le_audio::GetAudioSetConfigurations(
+ configurations_parser_.builder_.GetBufferPointer());
+ if (!configurations_root) return false;
+
+ auto flat_qos_configs = configurations_root->qos_configurations();
+ if ((flat_qos_configs == nullptr) || (flat_qos_configs->size() == 0))
+ return false;
+
+ LOG(DEBUG) << ": Updating " << flat_qos_configs->size()
+ << " qos config entries.";
+ std::vector<const le_audio::QosConfiguration*> qos_cfgs;
+ for (auto const& flat_qos_cfg : *flat_qos_configs) {
+ qos_cfgs.push_back(flat_qos_cfg);
+ }
+
+ auto flat_codec_configs = configurations_root->codec_configurations();
+ if ((flat_codec_configs == nullptr) || (flat_codec_configs->size() == 0))
+ return false;
+
+ LOG(DEBUG) << ": Updating " << flat_codec_configs->size()
+ << " codec config entries.";
+ std::vector<const le_audio::CodecConfiguration*> codec_cfgs;
+ for (auto const& flat_codec_cfg : *flat_codec_configs) {
+ codec_cfgs.push_back(flat_codec_cfg);
+ }
+
+ auto flat_configs = configurations_root->configurations();
+ if ((flat_configs == nullptr) || (flat_configs->size() == 0)) return false;
+
+ LOG(DEBUG) << ": Updating " << flat_configs->size() << " config entries.";
+ for (auto const& flat_cfg : *flat_configs) {
+ // Create 3 vector to use
+ std::vector<std::optional<AseDirectionConfiguration>>
+ sourceAseConfiguration;
+ std::vector<std::optional<AseDirectionConfiguration>> sinkAseConfiguration;
+ ConfigurationFlags configurationFlags;
+ PopulateAseConfigurationFromFlat(flat_cfg, &codec_cfgs, &qos_cfgs, location,
+ sourceAseConfiguration,
+ sinkAseConfiguration, configurationFlags);
+ if (sourceAseConfiguration.empty() && sinkAseConfiguration.empty())
+ continue;
+ configurations_[flat_cfg->name()->str()] = std::make_tuple(
+ sourceAseConfiguration, sinkAseConfiguration, configurationFlags);
+ }
+
+ return true;
+}
+
+bool AudioSetConfigurationProviderJson::LoadScenariosFromFiles(
+ const char* schema_file, const char* content_file) {
+ flatbuffers::Parser scenarios_parser_;
+ std::string scenarios_schema_binary_content;
+ bool ok = flatbuffers::LoadFile(schema_file, true,
+ &scenarios_schema_binary_content);
+ LOG(INFO) << __func__ << ": Loading file " << schema_file;
+ if (!ok) return ok;
+
+ /* Load the binary schema */
+ ok = scenarios_parser_.Deserialize(
+ (uint8_t*)scenarios_schema_binary_content.c_str(),
+ scenarios_schema_binary_content.length());
+ if (!ok) return ok;
+
+ /* Load the content from JSON */
+ LOG(INFO) << __func__ << ": Loading file " << content_file;
+ std::string scenarios_json_content;
+ ok = flatbuffers::LoadFile(content_file, false, &scenarios_json_content);
+ if (!ok) return ok;
+
+ /* Parse */
+ LOG(INFO) << __func__ << ": Parse json content";
+ ok = scenarios_parser_.Parse(scenarios_json_content.c_str());
+ if (!ok) return ok;
+
+ /* Import from flatbuffers */
+ LOG(INFO) << __func__ << ": Build flat buffer structure";
+ auto scenarios_root = le_audio::GetAudioSetScenarios(
+ scenarios_parser_.builder_.GetBufferPointer());
+ if (!scenarios_root) return false;
+
+ auto flat_scenarios = scenarios_root->scenarios();
+ if ((flat_scenarios == nullptr) || (flat_scenarios->size() == 0))
+ return false;
+
+ LOG(INFO) << __func__ << ": Turn flat buffer into structure";
+ AudioContext media_context = AudioContext();
+ media_context.bitmask =
+ (AudioContext::ALERTS | AudioContext::INSTRUCTIONAL |
+ AudioContext::NOTIFICATIONS | AudioContext::EMERGENCY_ALARM |
+ AudioContext::UNSPECIFIED | AudioContext::MEDIA);
+
+ AudioContext conversational_context = AudioContext();
+ conversational_context.bitmask =
+ (AudioContext::RINGTONE_ALERTS | AudioContext::CONVERSATIONAL);
+
+ AudioContext live_context = AudioContext();
+ live_context.bitmask = AudioContext::LIVE_AUDIO;
+
+ AudioContext game_context = AudioContext();
+ game_context.bitmask = AudioContext::GAME;
+
+ AudioContext voice_assistants_context = AudioContext();
+ voice_assistants_context.bitmask = AudioContext::VOICE_ASSISTANTS;
+
+ LOG(DEBUG) << "Updating " << flat_scenarios->size() << " scenarios.";
+ for (auto const& scenario : *flat_scenarios) {
+ LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
+ << " configs: " << scenario->configurations()->size();
+
+ if (!scenario->configurations()) continue;
+ std::string scenario_name = scenario->name()->c_str();
+ AudioContext context;
+ if (scenario_name == "Media")
+ context = AudioContext(media_context);
+ else if (scenario_name == "Conversational")
+ context = AudioContext(conversational_context);
+ else if (scenario_name == "Live")
+ context = AudioContext(live_context);
+ else if (scenario_name == "Game")
+ context = AudioContext(game_context);
+ else if (scenario_name == "VoiceAssistants")
+ context = AudioContext(voice_assistants_context);
+
+ for (auto it = scenario->configurations()->begin();
+ it != scenario->configurations()->end(); ++it) {
+ auto config_name = it->str();
+ auto configuration = configurations_.find(config_name);
+ if (configuration == configurations_.end()) continue;
+ LOG(DEBUG) << "Getting configuration with name: " << config_name;
+ auto [source, sink, flags] = configuration->second;
+ // Each configuration will create a LeAudioAseConfigurationSetting
+ // with the same {context, packing}
+ // and different data
+ LeAudioAseConfigurationSetting setting;
+ setting.audioContext = context;
+ // TODO: Packing
+ setting.sourceAseConfiguration = source;
+ setting.sinkAseConfiguration = sink;
+ setting.flags = flags;
+ // Add to list of setting
+ LOG(DEBUG) << "Pushing configuration to list: " << config_name;
+ ase_configuration_settings_.push_back(setting);
+ }
+ }
+
+ return true;
+}
+
+bool AudioSetConfigurationProviderJson::LoadContent(
+ std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+ config_files,
+ std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+ scenario_files,
+ CodecLocation location) {
+ for (auto [schema, content] : config_files) {
+ if (!LoadConfigurationsFromFiles(schema, content, location)) return false;
+ }
+
+ for (auto [schema, content] : scenario_files) {
+ if (!LoadScenariosFromFiles(schema, content)) return false;
+ }
+ return true;
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
new file mode 100644
index 0000000..ce91fca
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
@@ -0,0 +1,125 @@
+
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
+
+#include <map>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <tuple>
+
+#include "audio_set_configurations_generated.h"
+#include "audio_set_scenarios_generated.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using LeAudioAseConfigurationSetting =
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting;
+using AseDirectionConfiguration = IBluetoothAudioProvider::
+ LeAudioAseConfigurationSetting::AseDirectionConfiguration;
+using LeAudioAseQosConfiguration =
+ IBluetoothAudioProvider::LeAudioAseQosConfiguration;
+using LeAudioDataPathConfiguration =
+ IBluetoothAudioProvider::LeAudioDataPathConfiguration;
+
+enum class CodecLocation {
+ HOST,
+ ADSP,
+ CONTROLLER,
+};
+
+class AudioSetConfigurationProviderJson {
+ public:
+ static std::vector<LeAudioAseConfigurationSetting>
+ GetLeAudioAseConfigurationSettings();
+
+ private:
+ static void LoadAudioSetConfigurationProviderJson();
+
+ static const le_audio::CodecSpecificConfiguration* LookupCodecSpecificParam(
+ const flatbuffers::Vector<flatbuffers::Offset<
+ le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params,
+ le_audio::CodecSpecificLtvGenericTypes type);
+
+ static void populateAudioChannelAllocation(
+ CodecSpecificConfigurationLtv::AudioChannelAllocation&
+ audio_channel_allocation,
+ uint32_t audio_location);
+
+ static void populateConfigurationData(
+ LeAudioAseConfiguration& ase,
+ const flatbuffers::Vector<
+ flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>*
+ flat_codec_specific_params);
+
+ static void populateAseConfiguration(
+ LeAudioAseConfiguration& ase,
+ const le_audio::AudioSetSubConfiguration* flat_subconfig,
+ const le_audio::QosConfiguration* qos_cfg);
+
+ static void populateAseQosConfiguration(
+ LeAudioAseQosConfiguration& qos,
+ const le_audio::QosConfiguration* qos_cfg);
+
+ static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
+ const le_audio::AudioSetSubConfiguration* flat_subconfig,
+ const le_audio::QosConfiguration* qos_cfg, CodecLocation location);
+
+ static void processSubconfig(
+ const le_audio::AudioSetSubConfiguration* subconfig,
+ const le_audio::QosConfiguration* qos_cfg,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ directionAseConfiguration,
+ CodecLocation location);
+
+ static void PopulateAseConfigurationFromFlat(
+ const le_audio::AudioSetConfiguration* flat_cfg,
+ std::vector<const le_audio::CodecConfiguration*>* codec_cfgs,
+ std::vector<const le_audio::QosConfiguration*>* qos_cfgs,
+ CodecLocation location,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ sourceAseConfiguration,
+ std::vector<std::optional<AseDirectionConfiguration>>&
+ sinkAseConfiguration,
+ ConfigurationFlags& configurationFlags);
+
+ static bool LoadConfigurationsFromFiles(const char* schema_file,
+ const char* content_file,
+ CodecLocation location);
+
+ static bool LoadScenariosFromFiles(const char* schema_file,
+ const char* content_file);
+
+ static bool LoadContent(
+ std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+ config_files,
+ std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+ scenario_files,
+ CodecLocation location);
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 26da5fb..b6df67e 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+#include <set>
+
+#include "aidl/android/hardware/bluetooth/audio/ChannelMode.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecId.h"
+#include "aidl_android_hardware_bluetooth_audio_setting_enums.h"
#define LOG_TAG "BTAudioCodecsProviderAidl"
#include "BluetoothLeAudioCodecsProvider.h"
@@ -50,6 +55,123 @@
return le_audio_offload_setting;
}
+std::unordered_map<SessionType, std::vector<CodecInfo>>
+BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
+ const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting) {
+ // Load from previous storage if present
+ if (!session_codecs_map_.empty()) return session_codecs_map_;
+
+ isInvalidFileContent = true;
+ if (!le_audio_offload_setting.has_value()) return {};
+
+ // Load scenario, configuration, codec configuration and strategy
+ LoadConfigurationToMap(le_audio_offload_setting);
+ if (supported_scenarios_.empty() || configuration_map_.empty() ||
+ codec_configuration_map_.empty() || strategy_configuration_map_.empty())
+ return {};
+
+ // Map each configuration into a CodecInfo
+ std::unordered_map<std::string, CodecInfo> config_codec_info_map_;
+
+ for (auto& p : configuration_map_) {
+ // Initialize new CodecInfo for the config
+ auto config_name = p.first;
+ if (config_codec_info_map_.count(config_name) == 0)
+ config_codec_info_map_[config_name] = CodecInfo();
+
+ // Getting informations from codecConfig and strategyConfig
+ const auto codec_config_name = p.second.getCodecConfiguration();
+ const auto strategy_config_name = p.second.getStrategyConfiguration();
+ const auto codec_configuration_map_iter =
+ codec_configuration_map_.find(codec_config_name);
+ if (codec_configuration_map_iter == codec_configuration_map_.end())
+ continue;
+ const auto strategy_configuration_map_iter =
+ strategy_configuration_map_.find(strategy_config_name);
+ if (strategy_configuration_map_iter == strategy_configuration_map_.end())
+ continue;
+
+ const auto& codec_config = codec_configuration_map_iter->second;
+ const auto codec = codec_config.getCodec();
+ const auto& strategy_config = strategy_configuration_map_iter->second;
+ const auto strategy_config_channel_count =
+ strategy_config.getChannelCount();
+
+ // Initiate information
+ auto& codec_info = config_codec_info_map_[config_name];
+ switch (codec) {
+ case setting::CodecType::LC3:
+ codec_info.name = "LC3";
+ codec_info.id = CodecId::Core::LC3;
+ break;
+ default:
+ codec_info.name = "UNDEFINE";
+ codec_info.id = CodecId::Vendor();
+ break;
+ }
+ codec_info.transport =
+ CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
+
+ // Mapping codec configuration information
+ auto& transport =
+ codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ transport.samplingFrequencyHz.push_back(
+ codec_config.getSamplingFrequency());
+ // Mapping octetsPerCodecFrame to bitdepth for easier comparison.
+ transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
+ transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
+ switch (strategy_config.getAudioLocation()) {
+ case setting::AudioLocation::MONO:
+ if (strategy_config_channel_count == 1)
+ transport.channelMode.push_back(ChannelMode::MONO);
+ else
+ transport.channelMode.push_back(ChannelMode::DUALMONO);
+ break;
+ case setting::AudioLocation::STEREO:
+ transport.channelMode.push_back(ChannelMode::STEREO);
+ break;
+ default:
+ transport.channelMode.push_back(ChannelMode::UNKNOWN);
+ break;
+ }
+ }
+
+ // Goes through every scenario, deduplicate configuration
+ std::set<std::string> encoding_config, decoding_config, broadcast_config;
+ for (auto& s : supported_scenarios_) {
+ if (s.hasEncode()) encoding_config.insert(s.getEncode());
+ if (s.hasDecode()) decoding_config.insert(s.getDecode());
+ if (s.hasBroadcast()) broadcast_config.insert(s.getBroadcast());
+ }
+
+ // Split by session types and add results
+ const auto encoding_path =
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+ const auto decoding_path =
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+ const auto broadcast_path =
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+ session_codecs_map_ =
+ std::unordered_map<SessionType, std::vector<CodecInfo>>();
+ session_codecs_map_[encoding_path] = std::vector<CodecInfo>();
+ session_codecs_map_[decoding_path] = std::vector<CodecInfo>();
+ session_codecs_map_[broadcast_path] = std::vector<CodecInfo>();
+ session_codecs_map_[encoding_path].reserve(encoding_config.size());
+ session_codecs_map_[decoding_path].reserve(decoding_config.size());
+ session_codecs_map_[broadcast_path].reserve(broadcast_config.size());
+ for (auto& c : encoding_config)
+ session_codecs_map_[encoding_path].push_back(config_codec_info_map_[c]);
+ for (auto& c : decoding_config)
+ session_codecs_map_[decoding_path].push_back(config_codec_info_map_[c]);
+ for (auto& c : broadcast_config)
+ session_codecs_map_[broadcast_path].push_back(config_codec_info_map_[c]);
+
+ isInvalidFileContent = session_codecs_map_.empty();
+
+ return session_codecs_map_;
+}
+
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
const std::optional<setting::LeAudioOffloadSetting>&
@@ -58,6 +180,8 @@
return leAudioCodecCapabilities;
}
+ isInvalidFileContent = true;
+
if (!le_audio_offload_setting.has_value()) {
LOG(ERROR)
<< __func__
@@ -65,40 +189,13 @@
return {};
}
- ClearLeAudioCodecCapabilities();
- isInvalidFileContent = true;
-
- std::vector<setting::Scenario> supported_scenarios =
- GetScenarios(le_audio_offload_setting);
- if (supported_scenarios.empty()) {
- LOG(ERROR) << __func__ << ": No scenarios in "
- << kLeAudioCodecCapabilitiesFile;
+ LoadConfigurationToMap(le_audio_offload_setting);
+ if (supported_scenarios_.empty() || configuration_map_.empty() ||
+ codec_configuration_map_.empty() || strategy_configuration_map_.empty())
return {};
- }
-
- UpdateConfigurationsToMap(le_audio_offload_setting);
- if (configuration_map_.empty()) {
- LOG(ERROR) << __func__ << ": No configurations in "
- << kLeAudioCodecCapabilitiesFile;
- return {};
- }
-
- UpdateCodecConfigurationsToMap(le_audio_offload_setting);
- if (codec_configuration_map_.empty()) {
- LOG(ERROR) << __func__ << ": No codec configurations in "
- << kLeAudioCodecCapabilitiesFile;
- return {};
- }
-
- UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
- if (strategy_configuration_map_.empty()) {
- LOG(ERROR) << __func__ << ": No strategy configurations in "
- << kLeAudioCodecCapabilitiesFile;
- return {};
- }
leAudioCodecCapabilities =
- ComposeLeAudioCodecCapabilities(supported_scenarios);
+ ComposeLeAudioCodecCapabilities(supported_scenarios_);
isInvalidFileContent = leAudioCodecCapabilities.empty();
return leAudioCodecCapabilities;
@@ -109,6 +206,8 @@
configuration_map_.clear();
codec_configuration_map_.clear();
strategy_configuration_map_.clear();
+ session_codecs_map_.clear();
+ supported_scenarios_.clear();
}
std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
@@ -191,6 +290,40 @@
}
}
+void BluetoothLeAudioCodecsProvider::LoadConfigurationToMap(
+ const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting) {
+ ClearLeAudioCodecCapabilities();
+
+ supported_scenarios_ = GetScenarios(le_audio_offload_setting);
+ if (supported_scenarios_.empty()) {
+ LOG(ERROR) << __func__ << ": No scenarios in "
+ << kLeAudioCodecCapabilitiesFile;
+ return;
+ }
+
+ UpdateConfigurationsToMap(le_audio_offload_setting);
+ if (configuration_map_.empty()) {
+ LOG(ERROR) << __func__ << ": No configurations in "
+ << kLeAudioCodecCapabilitiesFile;
+ return;
+ }
+
+ UpdateCodecConfigurationsToMap(le_audio_offload_setting);
+ if (codec_configuration_map_.empty()) {
+ LOG(ERROR) << __func__ << ": No codec configurations in "
+ << kLeAudioCodecCapabilitiesFile;
+ return;
+ }
+
+ UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
+ if (strategy_configuration_map_.empty()) {
+ LOG(ERROR) << __func__ << ": No strategy configurations in "
+ << kLeAudioCodecCapabilitiesFile;
+ return;
+ }
+}
+
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
const std::vector<setting::Scenario>& supported_scenarios) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index 654e70c..5bf67e2 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -22,6 +22,8 @@
#include <unordered_map>
#include <vector>
+#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
#include "aidl_android_hardware_bluetooth_audio_setting.h"
namespace aidl {
@@ -39,14 +41,20 @@
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
static void ClearLeAudioCodecCapabilities();
+ static std::unordered_map<SessionType, std::vector<CodecInfo>>
+ GetLeAudioCodecInfo(const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting);
private:
+ static inline std::vector<setting::Scenario> supported_scenarios_;
static inline std::unordered_map<std::string, setting::Configuration>
configuration_map_;
static inline std::unordered_map<std::string, setting::CodecConfiguration>
codec_configuration_map_;
static inline std::unordered_map<std::string, setting::StrategyConfiguration>
strategy_configuration_map_;
+ static inline std::unordered_map<SessionType, std::vector<CodecInfo>>
+ session_codecs_map_;
static std::vector<setting::Scenario> GetScenarios(
const std::optional<setting::LeAudioOffloadSetting>&
@@ -60,6 +68,9 @@
static void UpdateStrategyConfigurationsToMap(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
+ static void LoadConfigurationToMap(
+ const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting);
static std::vector<LeAudioCodecCapabilitiesSetting>
ComposeLeAudioCodecCapabilities(
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs
new file mode 100644
index 0000000..bde467d
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+namespace aidl.android.hardware.bluetooth.audio.le_audio;
+enum CodecSpecificLtvGenericTypes : byte {
+ SUPPORTED_SAMPLING_FREQUENCY = 0x01,
+ SUPPORTED_FRAME_DURATION = 0x02,
+ SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 0x03,
+ SUPPORTED_OCTETS_PER_CODEC_FRAME = 0x04,
+ SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 0x05,
+}
+/// Note: Holds either a single value (when `value_width == 0`) or multiple
+/// values if `value.length()` is no-remainder divisible by the non-zero
+/// `value_width`.
+/// Note: Consider extending it with `flags` field, to hold additional info like
+/// IsBitfield, IsRange, etc. if we need these type-specific validations.
+table CompoundValue {
+ value: [ubyte] (required);
+ value_width: ubyte = 0;
+}
+table CodecSpecificConfiguration {
+ name: string;
+ type: ubyte (key);
+ compound_value: CompoundValue;
+}
+struct CodecId {
+ coding_format: ubyte;
+ vendor_company_id : ushort;
+ vendor_codec_id : ushort;
+}
+enum AudioSetConfigurationStrategy : byte {
+ MONO_ONE_CIS_PER_DEVICE = 0x00,
+ STEREO_TWO_CISES_PER_DEVICE = 0x01,
+ STEREO_ONE_CIS_PER_DEVICE = 0x02,
+}
+enum AudioSetConfigurationDirection : byte {
+ SINK = 0x01,
+ SOURCE = 0x02,
+}
+enum AudioSetConfigurationTargetLatency : byte {
+ LOW = 0x01,
+ BALANCED_RELIABILITY = 0x02,
+ HIGH_RELIABILITY = 0x03,
+}
+table AudioSetSubConfiguration {
+ device_cnt: ubyte;
+ ase_cnt: ubyte;
+ direction: AudioSetConfigurationDirection = SINK;
+ configuration_strategy: AudioSetConfigurationStrategy;
+ codec_id : CodecId (required);
+ codec_configuration: [CodecSpecificConfiguration] (required);
+}
+table CodecConfiguration {
+ name: string (key, required);
+ subconfigurations: [AudioSetSubConfiguration] (required);
+}
+table QosConfiguration {
+ name: string (key, required);
+ target_latency: AudioSetConfigurationTargetLatency = BALANCED_RELIABILITY;
+ retransmission_number: ubyte;
+ max_transport_latency : ushort;
+}
+/// Each set configration can contain multiple logical subconfigurations, which
+/// all must be configurable with the current set of audio devices. For example,
+/// one can define multiple output stream configurations with different
+/// qualities, or assign different configurations to each stream direction.
+table AudioSetConfiguration {
+ name: string (key, required);
+ codec_config_name: string (required);
+ qos_config_name: [string] (required);
+}
+table AudioSetConfigurations {
+ _comments_: [string];
+ configurations: [AudioSetConfiguration] (required);
+ codec_configurations: [CodecConfiguration] (required);
+ qos_configurations: [QosConfiguration] (required);
+}
+root_type AudioSetConfigurations;
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json
new file mode 100644
index 0000000..404a48a
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json
@@ -0,0 +1,11382 @@
+{
+ "_comments_": [
+ " == Audio Set Configurations == ",
+ " Contains: ",
+ " 1. configurations : ",
+ " Maps configuration name with codec and qos config to be used",
+ " 2. codec_configurations : ",
+ " Array of codec specific configurations",
+ " 3. qos_configurations : ",
+ " Array of QoS specific configurations",
+ " QoS configuration values are as per BAP spec 1.0",
+ " Example values which can be used as 'codec_configuration.type'",
+ " Codec Configuration parameter types:",
+ " SUPPORTED_SAMPLING_FREQUENCY = 1",
+ " SUPPORTED_FRAME_DURATION = 2",
+ " SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 3",
+ " SUPPORTED_OCTETS_PER_CODEC_FRAME = 4",
+ " SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 5",
+ " Example values which can be used as 'codec_configuration.compound_value'",
+ " Codec Coding formats:",
+ " LC3 = 6",
+ " ASE Configuration strategies:",
+ " MONO_ONE_CIS_PER_DEVICE = 0",
+ " STEREO_TWO_CISES_PER_DEVICE = 1",
+ " STEREO_ONE_CIS_PER_DEVICE = 2",
+ " Sampling Frequencies: ",
+ " 8000Hz = 1",
+ " 11025Hz = 2",
+ " 16000Hz = 3",
+ " 22050Hz = 4",
+ " 24000Hz = 5",
+ " 32000Hz = 6",
+ " 44100Hz = 7",
+ " 48000Hz = 8",
+ " 88200Hz = 9",
+ " 96000Hz = 10",
+ " 176400Hz = 11",
+ " 192000Hz = 12",
+ " 384000Hz = 13",
+ " Frame Durations:",
+ " 7500us = 0",
+ " 10000us = 1"
+ ],
+ "configurations": [
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_32_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_1_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_32_1",
+ "qos_config_name": [
+ "QoS_Config_32_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanMonoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_48_4",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_48_3",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_48_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_48_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_32_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_24_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": [
+ "QoS_Config_16_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_16_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_24_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_24_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_24_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_24_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_24_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_24_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_24_2",
+ "qos_config_name": [
+ "QoS_Config_24_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_32_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_32_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_32_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_32_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_32_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_32_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_32_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_32_2_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_32_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_32_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_High_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_1"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_3_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_3_High_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_3_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_48_3_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_2_High_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_48_2_2"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_1_High_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_48_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_3_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_3_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_3_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_48_3_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_2_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_2_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_48_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_1_Low_Latency",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_1_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_1_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_48_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_1"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_3_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_3_High_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_3_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_48_3_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_2_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_2_High_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_48_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_1_Low_Latency",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_1_High_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_48_1_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_1"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": [
+ "QoS_Config_48_4_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_3_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_3_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_3",
+ "qos_config_name": [
+ "QoS_Config_48_3_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_2_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_2",
+ "qos_config_name": [
+ "QoS_Config_48_2_2"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_1_High_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_1_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_1",
+ "qos_config_name": [
+ "QoS_Config_48_1_2"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_Low_Latency_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60oct_R3_L22_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R3_L22"
+ ]
+ },
+ {
+ "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "codec_config_name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
+ "codec_config_name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R15_L70"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "codec_config_name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
+ "codec_config_name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R15_L70"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R15_L70"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1",
+ "qos_config_name": [
+ "QoS_Config_High_Reliability"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R5_L12"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_24_2_1_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+ "qos_config_name": [
+ "QoS_Config_Low_Latency"
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R11_L40"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1",
+ "qos_config_name": [
+ "VND_QoS_Config_R5_L12",
+ "VND_QoS_Config_R3_L12"
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1",
+ "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1",
+ "qos_config_name": [
+ "QoS_Config_Balanced_Reliability"
+ ]
+ }
+ ],
+ "codec_configurations": [
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_32_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_32_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanMonoSnk_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_4",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_3",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 90,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_32_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_24_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 45,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 40,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSrc_16_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_3",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 90,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_3",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 90,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_3",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 90,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_3",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 90,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 120,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 100,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 8
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 75,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 3
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 30,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_24_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 45,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_24_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 45,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_24_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 45,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_24_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 5
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 2,
+ "ase_cnt": 4,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SOURCE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_32_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 1,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 3,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_32_2",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 80,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_32_1",
+ "subconfigurations": [
+ {
+ "device_cnt": 1,
+ "ase_cnt": 2,
+ "direction": "SINK",
+ "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
+ "codec_id": {
+ "coding_format": 6,
+ "vendor_company_id": 0,
+ "vendor_codec_id": 0
+ },
+ "codec_configuration": [
+ {
+ "name": "sampling_frequency",
+ "type": 1,
+ "compound_value": {
+ "value": [
+ 6
+ ]
+ }
+ },
+ {
+ "name": "frame_duration",
+ "type": 2,
+ "compound_value": {
+ "value": [
+ 0
+ ]
+ }
+ },
+ {
+ "name": "audio_channel_allocation",
+ "type": 3,
+ "compound_value": {
+ "value": [
+ 1,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "octets_per_codec_frame",
+ "type": 4,
+ "compound_value": {
+ "value": [
+ 60,
+ 0
+ ]
+ }
+ },
+ {
+ "name": "codec_frame_blocks_per_sdu",
+ "type": 5,
+ "compound_value": {
+ "value": [
+ 1
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "qos_configurations": [
+ {
+ "name": "QoS_Config_16_1_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 8
+ },
+ {
+ "name": "QoS_Config_16_1_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_16_2_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 10
+ },
+ {
+ "name": "QoS_Config_16_2_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 95
+ },
+ {
+ "name": "QoS_Config_24_1_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 8
+ },
+ {
+ "name": "QoS_Config_24_1_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_24_2_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 10
+ },
+ {
+ "name": "QoS_Config_24_2_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 95
+ },
+ {
+ "name": "QoS_Config_32_1_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 8
+ },
+ {
+ "name": "QoS_Config_32_1_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_32_2_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 10
+ },
+ {
+ "name": "QoS_Config_32_2_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 95
+ },
+ {
+ "name": "QoS_Config_48_1_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_48_2_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 95
+ },
+ {
+ "name": "QoS_Config_48_3_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_48_4_1",
+ "retransmission_number": 5,
+ "max_transport_latency": 20
+ },
+ {
+ "name": "QoS_Config_48_4_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 100
+ },
+ {
+ "name": "VND_QoS_Config_R3_L22",
+ "retransmission_number": 3,
+ "max_transport_latency": 22
+ },
+ {
+ "name": "VND_QoS_Config_R15_L70",
+ "retransmission_number": 15,
+ "max_transport_latency": 70
+ },
+ {
+ "name": "VND_QoS_Config_R5_L12",
+ "retransmission_number": 5,
+ "max_transport_latency": 12
+ },
+ {
+ "name": "VND_QoS_Config_R11_L40",
+ "retransmission_number": 11,
+ "max_transport_latency": 40
+ },
+ {
+ "name": "VND_QoS_Config_R3_L12",
+ "retransmission_number": 3,
+ "max_transport_latency": 12
+ },
+ {
+ "name": "QoS_Config_Low_Latency",
+ "target_latency": "LOW",
+ "retransmission_number": 0,
+ "max_transport_latency": 0
+ },
+ {
+ "name": "QoS_Config_Balanced_Reliability",
+ "target_latency": "BALANCED_RELIABILITY",
+ "retransmission_number": 0,
+ "max_transport_latency": 0
+ },
+ {
+ "name": "QoS_Config_High_Reliability",
+ "target_latency": "HIGH_RELIABILITY",
+ "retransmission_number": 0,
+ "max_transport_latency": 0
+ }
+
+ ]
+}
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.fbs b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.fbs
new file mode 100644
index 0000000..e898bdc
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.fbs
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+namespace aidl.android.hardware.bluetooth.audio.le_audio;
+/// Scenario represents the use case such as "Media", "Conversation", etc.
+/// Each scenario can list any number of codec configurations by their names in
+/// the order of preference. That means if the first entry does not meet all
+/// the current requirements (such as peer device capabilities etc.) next
+/// configurations are being checked.
+///
+/// The referenced codec configurations are defined by the
+/// audio_set_configurations.fbs schema and loaded from a different source file.
+/// Multiple scenarios can reference same codec configurations.
+table AudioSetScenario {
+ _comments_: [string];
+ name: string (key, required);
+ configurations: [string] (required);
+}
+table AudioSetScenarios {
+ _comments_: [string];
+ scenarios: [AudioSetScenario] (required);
+}
+root_type AudioSetScenarios;
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json
new file mode 100644
index 0000000..a28c6cd
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json
@@ -0,0 +1,304 @@
+{
+ "_comments_": [
+ "== Audio Set Scenarios ==",
+ " Each defined scenario references externally defined audio set",
+ " configurations, listed in the order of priority."
+ ],
+ "scenarios": [
+ {
+ "name": "Conversational",
+ "configurations": [
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
+ "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability",
+ "VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_Server_Prefered_1",
+ "VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_60oct_R3_L22_1",
+ "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "Media",
+ "configurations": [
+ "DualDev_OneChanStereoSnk_48_4_High_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_2",
+ "DualDev_OneChanStereoSnk_48_2_High_Reliability",
+ "DualDev_OneChanStereoSnk_48_2_2",
+ "DualDev_OneChanStereoSnk_48_3_High_Reliability",
+ "DualDev_OneChanStereoSnk_48_3_2",
+ "DualDev_OneChanStereoSnk_48_1_High_Reliability",
+ "DualDev_OneChanStereoSnk_48_1_2",
+ "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_24_2_2",
+ "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_16_2_2",
+ "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_16_1_2",
+ "SingleDev_OneChanStereoSnk_48_4_High_Reliability",
+ "SingleDev_OneChanStereoSnk_48_4_2",
+ "SingleDev_OneChanStereoSnk_48_2_High_Reliability",
+ "SingleDev_OneChanStereoSnk_48_2_2",
+ "SingleDev_OneChanStereoSnk_48_3_High_Reliability",
+ "SingleDev_OneChanStereoSnk_48_3_2",
+ "SingleDev_OneChanStereoSnk_48_1_High_Reliability",
+ "SingleDev_OneChanStereoSnk_48_1_2",
+ "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_24_2_2",
+ "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_16_2_2",
+ "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_16_1_2",
+ "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_2",
+ "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_2",
+ "SingleDev_TwoChanStereoSnk_48_2_High_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_2_2",
+ "SingleDev_TwoChanStereoSnk_48_3_High_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_3_2",
+ "SingleDev_TwoChanStereoSnk_48_1_High_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_1_2",
+ "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_24_2_2",
+ "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_16_2_2",
+ "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_16_1_2",
+ "SingleDev_OneChanMonoSnk_48_4_High_Reliability",
+ "SingleDev_OneChanMonoSnk_48_4_2",
+ "SingleDev_OneChanMonoSnk_48_2_High_Reliability",
+ "SingleDev_OneChanMonoSnk_48_2_2",
+ "SingleDev_OneChanMonoSnk_48_3_High_Reliability",
+ "SingleDev_OneChanMonoSnk_48_3_2",
+ "SingleDev_OneChanMonoSnk_48_1_High_Reliability",
+ "SingleDev_OneChanMonoSnk_48_1_2",
+ "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_32_2_2",
+ "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_32_1_2",
+ "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_24_2_2",
+ "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_16_2_2",
+ "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_16_1_2",
+ "VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1",
+ "VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
+ "VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
+ "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "Game",
+ "configurations": [
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1",
+ "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_48_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_48_3_Low_Latency",
+ "DualDev_OneChanStereoSnk_48_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_32_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_24_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_24_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_48_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_48_3_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_48_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_32_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_24_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_24_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_16_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_48_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_48_3_Low_Latency",
+ "SingleDev_OneChanStereoSnk_48_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_32_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_32_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_24_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_24_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_16_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_16_1_Low_Latency"
+ ]
+ },
+ {
+ "name": "VoiceAssistants",
+ "configurations": [
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
+ "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability"
+ ]
+ },
+ {
+ "name": "Live",
+ "configurations": [
+ "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1",
+ "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
+ "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
+ "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability"
+ ]
+ }
+ ]
+}
diff --git a/bluetooth/lmp_event/aidl/Android.bp b/bluetooth/lmp_event/aidl/Android.bp
new file mode 100644
index 0000000..6c2f278
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/Android.bp
@@ -0,0 +1,33 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.bluetooth.lmp_event",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["android/hardware/bluetooth/lmp_event/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ enabled: true,
+ platform_apis: true,
+ },
+ cpp: {
+ enabled: true,
+ },
+ ndk: {
+ enabled: true,
+ min_sdk_version: "33",
+ },
+ rust: {
+ enabled: true,
+ min_sdk_version: "33",
+ },
+ },
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/AddressType.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/AddressType.aidl
new file mode 100644
index 0000000..0f239e8
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/AddressType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@Backing(type="byte") @VintfStability
+enum AddressType {
+ PUBLIC = 0x00,
+ RANDOM = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Direction.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Direction.aidl
new file mode 100644
index 0000000..6f807cc
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Direction.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@Backing(type="byte") @VintfStability
+enum Direction {
+ TX = 0x00,
+ RX = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl
new file mode 100644
index 0000000..3431010
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@VintfStability
+interface IBluetoothLmpEvent {
+ void registerForLmpEvents(in android.hardware.bluetooth.lmp_event.IBluetoothLmpEventCallback callback, in android.hardware.bluetooth.lmp_event.AddressType addressType, in byte[6] address, in android.hardware.bluetooth.lmp_event.LmpEventId[] lmpEventIds);
+ void unregisterLmpEvents(in android.hardware.bluetooth.lmp_event.AddressType addressType, in byte[6] address);
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl
new file mode 100644
index 0000000..fc6758c
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@VintfStability
+interface IBluetoothLmpEventCallback {
+ void onEventGenerated(in android.hardware.bluetooth.lmp_event.Timestamp timestamp, in android.hardware.bluetooth.lmp_event.AddressType addressType, in byte[6] address, in android.hardware.bluetooth.lmp_event.Direction direction, in android.hardware.bluetooth.lmp_event.LmpEventId lmpEventId, in char connEventCounter);
+ void onRegistered(in boolean status);
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/LmpEventId.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/LmpEventId.aidl
new file mode 100644
index 0000000..4ee95d1
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/LmpEventId.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@Backing(type="byte") @VintfStability
+enum LmpEventId {
+ CONNECT_IND = 0x00,
+ LL_PHY_UPDATE_IND = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Timestamp.aidl b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Timestamp.aidl
new file mode 100644
index 0000000..5ef32ba
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/aidl_api/android.hardware.bluetooth.lmp_event/current/android/hardware/bluetooth/lmp_event/Timestamp.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.lmp_event;
+@VintfStability
+parcelable Timestamp {
+ long systemTimeUs;
+ long bluetoothTimeUs;
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/AddressType.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/AddressType.aidl
new file mode 100644
index 0000000..6bfc7c7
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/AddressType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+/**
+ * Type of Address
+ */
+@VintfStability
+@Backing(type="byte")
+enum AddressType {
+ PUBLIC = 0x00,
+ RANDOM = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Direction.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Direction.aidl
new file mode 100644
index 0000000..884c2bb
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Direction.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+/**
+ * Direction of the LMP event
+ */
+@VintfStability
+@Backing(type="byte")
+enum Direction {
+ TX = 0x00,
+ RX = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl
new file mode 100644
index 0000000..3828af6
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEvent.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+import android.hardware.bluetooth.lmp_event.IBluetoothLmpEventCallback;
+import android.hardware.bluetooth.lmp_event.AddressType;
+import android.hardware.bluetooth.lmp_event.LmpEventId;
+
+@VintfStability
+interface IBluetoothLmpEvent {
+ /**
+ * API to monitor specific LMP event timestamp for given Bluetooth device.
+ *
+ * @param callback An instance of the |IBluetoothLmpEventCallback| AIDL interface object.
+ * @param addressType Type of bluetooth address.
+ * @param address Bluetooth address to monitor.
+ * @param lmpEventIds LMP events to monitor.
+ */
+ void registerForLmpEvents(in IBluetoothLmpEventCallback callback,
+ in AddressType addressType,
+ in byte[6] address,
+ in LmpEventId[] lmpEventIds);
+
+ /**
+ * API to stop monitoring a given Bluetooth device.
+ *
+ * @param addressType Type of Bluetooth address.
+ * @param address Bluetooth device to stop monitoring.
+ */
+ void unregisterLmpEvents(in AddressType addressType, in byte[6] address);
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl
new file mode 100644
index 0000000..3295ef0
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/IBluetoothLmpEventCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+import android.hardware.bluetooth.lmp_event.Direction;
+import android.hardware.bluetooth.lmp_event.AddressType;
+import android.hardware.bluetooth.lmp_event.LmpEventId;
+import android.hardware.bluetooth.lmp_event.Timestamp;
+
+@VintfStability
+interface IBluetoothLmpEventCallback {
+ /**
+ * Callback when monitored LMP event invoked.
+ *
+ * @param timestamp Timestamp when the LMP event invoked
+ * @param addressType Type of Bluetooth address.
+ * @param address Remote bluetooth address that invoke LMP event
+ * @param direction Direction of the invoked LMP event
+ * @param lmpEventId LMP event id that bluetooth chip invoked
+ * @param connEventCounter counter incremented by one for each new connection event
+ */
+ void onEventGenerated(in Timestamp timestamp,
+ in AddressType addressType,
+ in byte[6] address,
+ in Direction direction,
+ in LmpEventId lmpEventId,
+ in char connEventCounter);
+
+ /**
+ * Callback when registration done.
+ */
+ void onRegistered(in boolean status);
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/LmpEventId.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/LmpEventId.aidl
new file mode 100644
index 0000000..3584b0c
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/LmpEventId.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+/**
+ * LMP event id to be monitored
+ * CONNECT_IND indicator for initiating connection
+ * LL_PHY_UPDATE_IND indicator for PHY update
+ */
+@VintfStability
+@Backing(type="byte")
+enum LmpEventId {
+ CONNECT_IND = 0x00,
+ LL_PHY_UPDATE_IND = 0x01,
+}
diff --git a/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Timestamp.aidl b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Timestamp.aidl
new file mode 100644
index 0000000..e3c991d
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/android/hardware/bluetooth/lmp_event/Timestamp.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.bluetooth.lmp_event;
+
+/**
+ * Generic structure to return the timestamp
+ */
+@VintfStability
+parcelable Timestamp {
+ /**
+ * Timestamp in microsecond since system boot.
+ * if systemTimeUs is set to 0, its value is to be ignored
+ */
+ long systemTimeUs;
+ /**
+ * Timestamp in microsecond since Bluetooth controller power up.
+ */
+ long bluetoothTimeUs;
+}
diff --git a/bluetooth/lmp_event/aidl/default/Android.bp b/bluetooth/lmp_event/aidl/default/Android.bp
new file mode 100644
index 0000000..f8ca5e6
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/default/Android.bp
@@ -0,0 +1,28 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+rust_binary {
+ name: "android.hardware.bluetooth.lmp_event-service.default",
+ relative_install_path: "hw",
+ init_rc: ["lmp_event-default.rc"],
+ vintf_fragments: [":manifest_android.hardware.bluetooth.lmp_event-service.default.xml"],
+ vendor: true,
+ rustlibs: [
+ "liblogger",
+ "liblog_rust",
+ "libbinder_rs",
+ "android.hardware.bluetooth.lmp_event-V1-rust",
+ ],
+ srcs: [ "src/main.rs" ],
+}
+
+filegroup {
+ name: "manifest_android.hardware.bluetooth.lmp_event-service.default.xml",
+ srcs: [ "lmp_event-default.xml" ],
+}
diff --git a/bluetooth/lmp_event/aidl/default/lmp_event-default.rc b/bluetooth/lmp_event/aidl/default/lmp_event-default.rc
new file mode 100644
index 0000000..845e04d
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/default/lmp_event-default.rc
@@ -0,0 +1,6 @@
+service vendor.bluetooth.lmp_event-default /vendor/bin/hw/android.hardware.bluetooth.lmp_event-service.default
+ class hal
+ capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
+ user bluetooth
+ group bluetooth
+ task_profiles HighPerformance
diff --git a/bluetooth/lmp_event/aidl/default/lmp_event-default.xml b/bluetooth/lmp_event/aidl/default/lmp_event-default.xml
new file mode 100644
index 0000000..24d93f8
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/default/lmp_event-default.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.bluetooth.lmp_event</name>
+ <version>1</version>
+ <interface>
+ <name>IBluetoothLmpEvent</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/bluetooth/lmp_event/aidl/default/src/lmp_event.rs b/bluetooth/lmp_event/aidl/default/src/lmp_event.rs
new file mode 100644
index 0000000..f016c3f
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/default/src/lmp_event.rs
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+//! Implements LMP Event AIDL Interface.
+
+use android_hardware_bluetooth_lmp_event::aidl::android::hardware::bluetooth::lmp_event::{
+ Direction::Direction, AddressType::AddressType, IBluetoothLmpEvent::IBluetoothLmpEvent,
+ IBluetoothLmpEventCallback::IBluetoothLmpEventCallback, LmpEventId::LmpEventId,
+ Timestamp::Timestamp,
+};
+
+use binder::{Interface, Result, Strong};
+
+use log::info;
+use std::thread;
+use std::time;
+
+
+pub struct LmpEvent;
+
+impl LmpEvent {
+ pub fn new() -> Self {
+ Self
+ }
+}
+
+impl Interface for LmpEvent {}
+
+impl IBluetoothLmpEvent for LmpEvent {
+ fn registerForLmpEvents(&self,
+ callback: &Strong<dyn IBluetoothLmpEventCallback>,
+ address_type: AddressType,
+ address: &[u8; 6],
+ lmp_event_ids: &[LmpEventId]
+ ) -> Result<()> {
+ info!("registerForLmpEvents");
+
+ let cb = callback.clone();
+ let addr_type = address_type;
+ let addr = address.clone();
+ let lmp_event = lmp_event_ids.to_vec();
+
+ let thread_handle = thread::spawn(move || {
+ let ts = Timestamp {
+ bluetoothTimeUs: 1000000,
+ systemTimeUs: 2000000,
+ };
+
+ info!("sleep for 1000 ms");
+ thread::sleep(time::Duration::from_millis(1000));
+
+ info!("callback event");
+ cb.onEventGenerated(&ts, addr_type, &addr, Direction::RX, lmp_event[0], 1)
+ .expect("onEventGenerated failed");
+ });
+
+ info!("callback register");
+ callback.onRegistered(true)?;
+
+ thread_handle.join().expect("join failed");
+ Ok(())
+ }
+ fn unregisterLmpEvents(&self, _address_type: AddressType, _address: &[u8; 6]) -> Result<()> {
+ info!("unregisterLmpEvents");
+
+ Ok(())
+ }
+}
diff --git a/bluetooth/lmp_event/aidl/default/src/main.rs b/bluetooth/lmp_event/aidl/default/src/main.rs
new file mode 100644
index 0000000..cbdd4d1
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/default/src/main.rs
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+//! Implements LMP Event Example Service.
+
+
+use android_hardware_bluetooth_lmp_event::aidl::android::hardware::bluetooth::lmp_event::IBluetoothLmpEvent::{
+ IBluetoothLmpEvent, BnBluetoothLmpEvent
+};
+
+use binder::BinderFeatures;
+use log::{info, Level};
+
+mod lmp_event;
+
+const LOG_TAG: &str = "lmp_event_service_example";
+
+fn main() {
+ info!("{LOG_TAG}: starting service");
+ let logger_success = logger::init(
+ logger::Config::default().with_tag_on_device(LOG_TAG).with_min_level(Level::Trace)
+ );
+ if !logger_success {
+ panic!("{LOG_TAG}: Failed to start logger");
+ }
+
+ binder::ProcessState::set_thread_pool_max_thread_count(0);
+
+ let lmp_event_service = lmp_event::LmpEvent::new();
+ let lmp_event_service_binder = BnBluetoothLmpEvent::new_binder(lmp_event_service, BinderFeatures::default());
+
+ binder::add_service(
+ &format!("{}/default", lmp_event::LmpEvent::get_descriptor()),
+ lmp_event_service_binder.as_binder(),
+ ).expect("Failed to register service");
+
+ binder::ProcessState::join_thread_pool()
+}
diff --git a/bluetooth/lmp_event/aidl/vts/Android.bp b/bluetooth/lmp_event/aidl/vts/Android.bp
new file mode 100644
index 0000000..b89351e
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/vts/Android.bp
@@ -0,0 +1,20 @@
+cc_test {
+ name: "VtsHalLmpEventTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalLmpEventTargetTest.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk"
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.lmp_event-V1-ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ]
+}
+
diff --git a/bluetooth/lmp_event/aidl/vts/VtsHalLmpEventTargetTest.cpp b/bluetooth/lmp_event/aidl/vts/VtsHalLmpEventTargetTest.cpp
new file mode 100644
index 0000000..c49f60b
--- /dev/null
+++ b/bluetooth/lmp_event/aidl/vts/VtsHalLmpEventTargetTest.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 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 std::shared_ptrecific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "lmp_event_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/bluetooth/lmp_event/BnBluetoothLmpEvent.h>
+#include <aidl/android/hardware/bluetooth/lmp_event/BnBluetoothLmpEventCallback.h>
+#include <aidl/android/hardware/bluetooth/lmp_event/Direction.h>
+#include <aidl/android/hardware/bluetooth/lmp_event/AddressType.h>
+#include <aidl/android/hardware/bluetooth/lmp_event/LmpEventId.h>
+#include <aidl/android/hardware/bluetooth/lmp_event/Timestamp.h>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <log/log.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <cinttypes>
+#include <thread>
+
+using ::aidl::android::hardware::bluetooth::lmp_event::BnBluetoothLmpEventCallback;
+using ::aidl::android::hardware::bluetooth::lmp_event::IBluetoothLmpEvent;
+using ::aidl::android::hardware::bluetooth::lmp_event::IBluetoothLmpEventCallback;
+using ::aidl::android::hardware::bluetooth::lmp_event::Direction;
+using ::aidl::android::hardware::bluetooth::lmp_event::AddressType;
+using ::aidl::android::hardware::bluetooth::lmp_event::LmpEventId;
+using ::aidl::android::hardware::bluetooth::lmp_event::Timestamp;
+
+using ::android::ProcessState;
+using ::ndk::SpAIBinder;
+
+namespace {
+ static constexpr std::chrono::milliseconds kEventTimeoutMs(10000);
+}
+
+class BluetoothLmpEventTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ ALOGI("%s", __func__);
+
+ ibt_lmp_event_ = IBluetoothLmpEvent::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(ibt_lmp_event_, nullptr);
+
+ ibt_lmp_event_cb_ = ndk::SharedRefBase::make<BluetoothLmpEventCallback>(*this);
+ ASSERT_NE(ibt_lmp_event_cb_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ ALOGI("%s", __func__);
+ ibt_lmp_event_->unregisterLmpEvents(address_type, address);
+
+ ibt_lmp_event_cb_ = nullptr;
+ }
+
+ class BluetoothLmpEventCallback : public BnBluetoothLmpEventCallback {
+ public:
+ BluetoothLmpEventTest& parent_;
+ BluetoothLmpEventCallback(BluetoothLmpEventTest& parent)
+ : parent_(parent) {}
+ ~BluetoothLmpEventCallback() = default;
+
+ ::ndk::ScopedAStatus onEventGenerated(const Timestamp& timestamp, AddressType address_type,
+ const std::array<uint8_t, 6>& address, Direction direction,
+ LmpEventId lmp_event_id, char16_t conn_event_counter) override {
+ for (auto t: address) {
+ ALOGD("%s: 0x%02x", __func__, t);
+ }
+ if (direction == Direction::TX) {
+ ALOGD("%s: Transmitting", __func__);
+ } else if (direction == Direction::RX) {
+ ALOGD("%s: Receiving", __func__);
+ }
+ if (address_type == AddressType::PUBLIC) {
+ ALOGD("%s: Public address", __func__);
+ } else if (address_type == AddressType::RANDOM) {
+ ALOGD("%s: Random address", __func__);
+ }
+ if (lmp_event_id == LmpEventId::CONNECT_IND) {
+ ALOGD("%s: initiating connection", __func__);
+ } else if (lmp_event_id == LmpEventId::LL_PHY_UPDATE_IND) {
+ ALOGD("%s: PHY update indication", __func__);
+ }
+
+ ALOGD("%s: time: %" PRId64 "counter value: %x", __func__, timestamp.bluetoothTimeUs, conn_event_counter);
+
+ parent_.event_recv = true;
+ parent_.notify();
+
+ return ::ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onRegistered(bool status) override {
+ ALOGD("%s: status: %d", __func__, status);
+ parent_.status_recv = status;
+ parent_.notify();
+ return ::ndk::ScopedAStatus::ok();
+ }
+ };
+
+ inline void notify() {
+ std::unique_lock<std::mutex> lock(lmp_event_mtx);
+ lmp_event_cv.notify_one();
+ }
+
+ inline void wait(bool is_register_event) {
+ std::unique_lock<std::mutex> lock(lmp_event_mtx);
+
+
+ if (is_register_event) {
+ lmp_event_cv.wait(lock, [&]() { return status_recv == true; });
+ } else {
+ lmp_event_cv.wait_for(lock, kEventTimeoutMs,
+ [&](){ return event_recv == true; });
+ }
+
+ }
+
+ std::shared_ptr<IBluetoothLmpEvent> ibt_lmp_event_;
+ std::shared_ptr<IBluetoothLmpEventCallback> ibt_lmp_event_cb_;
+
+ AddressType address_type;
+ std::array<uint8_t, 6> address;
+
+ std::atomic<bool> event_recv;
+ bool status_recv;
+
+ std::mutex lmp_event_mtx;
+ std::condition_variable lmp_event_cv;
+};
+
+TEST_P(BluetoothLmpEventTest, RegisterAndReceive) {
+ address = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ address_type = AddressType::RANDOM;
+ std::vector<LmpEventId> lmp_event_ids{LmpEventId::CONNECT_IND, LmpEventId::LL_PHY_UPDATE_IND};
+
+ ibt_lmp_event_->registerForLmpEvents(ibt_lmp_event_cb_, address_type, address, lmp_event_ids);
+ wait(true);
+ EXPECT_EQ(true, status_recv);
+
+ /* Wait for event generated here */
+ wait(false);
+ EXPECT_EQ(true, event_recv);
+
+ ibt_lmp_event_->unregisterLmpEvents(address_type, address);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothLmpEventTest);
+INSTANTIATE_TEST_SUITE_P(BluetoothLmpEvent, BluetoothLmpEventTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IBluetoothLmpEvent::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
+
diff --git a/bluetooth/ranging/OWNERS b/bluetooth/ranging/OWNERS
new file mode 100644
index 0000000..3d95624
--- /dev/null
+++ b/bluetooth/ranging/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 27441
+
+include platform/packages/modules/Bluetooth:/OWNERS
+
+chienyuanhuang@google.com
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index e7fad4d..8fc77ae 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -35,6 +35,7 @@
@VintfStability
parcelable ChannelSoudingRawData {
int procedureCounter;
+ int[] frequencyCompensation;
boolean aborted;
android.hardware.bluetooth.ranging.ChannelSoundingSingleSideData initiatorData;
android.hardware.bluetooth.ranging.ChannelSoundingSingleSideData reflectorData;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 9fe85da..ddaba72 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -38,6 +38,7 @@
@nullable byte[] packetQuality;
@nullable byte[] packetRssiDbm;
@nullable android.hardware.bluetooth.ranging.Nadm[] packetNadm;
+ @nullable int[] measuredFreqOffset;
@nullable List<android.hardware.bluetooth.ranging.ComplexNumber> packetPct1;
@nullable List<android.hardware.bluetooth.ranging.ComplexNumber> packetPct2;
byte referencePowerDbm;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
index a51ba37..4125748 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -36,6 +36,7 @@
parcelable StepTonePct {
List<android.hardware.bluetooth.ranging.ComplexNumber> tonePcts;
byte[] toneQualityIndicator;
+ byte toneExtensionAntennaIndex;
const int TONE_QUALITY_GOOD = 0;
const int TONE_QUALITY_MEDIUM = 1;
const int TONE_QUALITY_LOW = 2;
@@ -44,4 +45,9 @@
const int EXTENSION_SLOT_TONE_NOT_EXPECTED_TO_BE_PRESENT = 1;
const int EXTENSION_SLOT_TONE_EXPECTED_TO_BE_PRESENT = 2;
const int EXTENSION_SLOT_SHIFT_AMOUNT = 4;
+ const byte TONE_EXTENSION_ANTENNA_1 = 0x0;
+ const byte TONE_EXTENSION_ANTENNA_2 = 0x1;
+ const byte TONE_EXTENSION_ANTENNA_3 = 0x2;
+ const byte TONE_EXTENSION_ANTENNA_4 = 0x3;
+ const byte TONE_EXTENSION_UNUSED = 0xFFu8;
}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index 3c8a62f..0106865 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -29,6 +29,11 @@
*/
int procedureCounter;
/**
+ * Frequency Compensation indicates fractional frequency
+ * offset (FFO) value of initiator, in 0.01ppm
+ */
+ int[] frequencyCompensation;
+ /**
* Indicate if the procedure aborted.
*/
boolean aborted;
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 2c3f201..942fc0d 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -42,6 +42,10 @@
*/
@nullable Nadm[] packetNadm;
/**
+ * Measured Frequency Offset from mode 0, relative to the remote device, in 0.01ppm
+ */
+ @nullable int[] measuredFreqOffset;
+ /**
* Packet_PCT1 or packet_PCT2 of mode-1 or mode-3, if sounding sequence is used and sounding
* phase-based ranging is supported.
*/
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
index 99c6d65..4650861 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -23,6 +23,10 @@
*/
@VintfStability
parcelable StepTonePct {
+ /**
+ * PCT measured from mode-2 or mode-3 steps
+ * (in ascending order of antenna position with tone extension data at the end).
+ */
List<ComplexNumber> tonePcts;
const int TONE_QUALITY_GOOD = 0;
const int TONE_QUALITY_MEDIUM = 1;
@@ -52,4 +56,20 @@
* See: https://bluetooth.com/specifications/specs/channel-sounding-cr-pr/
*/
byte[] toneQualityIndicator;
+
+ const byte TONE_EXTENSION_ANTENNA_1 = 0x0;
+ const byte TONE_EXTENSION_ANTENNA_2 = 0x1;
+ const byte TONE_EXTENSION_ANTENNA_3 = 0x2;
+ const byte TONE_EXTENSION_ANTENNA_4 = 0x3;
+ const byte TONE_EXTENSION_UNUSED = 0xFFu8;
+ /**
+ * Tone Extension Antenna Index indicates the Antenna position used in tone extension slot
+ *
+ * 0x00 = A1
+ * 0x01 = A2
+ * 0x02 = A3
+ * 0x03 = A4
+ * 0xFF = Tone extension not used
+ */
+ byte toneExtensionAntennaIndex;
}
diff --git a/bluetooth/ranging/aidl/vts/Android.bp b/bluetooth/ranging/aidl/vts/Android.bp
new file mode 100644
index 0000000..ead9992
--- /dev/null
+++ b/bluetooth/ranging/aidl/vts/Android.bp
@@ -0,0 +1,27 @@
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalBluetoothRangingTargetTest",
+ defaults: [
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalBluetoothRangingTargetTest.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.ranging-V1-ndk",
+ "libbluetooth-types",
+ ],
+ test_config: "VtsHalBluetoothRangingTargetTest.xml",
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp
new file mode 100644
index 0000000..702df95
--- /dev/null
+++ b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2023 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/bluetooth/ranging/BnBluetoothChannelSoundingSessionCallback.h>
+#include <aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.h>
+#include <aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSessionCallback.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+using aidl::android::hardware::bluetooth::ranging::
+ BluetoothChannelSoundingParameters;
+using aidl::android::hardware::bluetooth::ranging::
+ BnBluetoothChannelSoundingSessionCallback;
+using aidl::android::hardware::bluetooth::ranging::ChannelSoudingRawData;
+using aidl::android::hardware::bluetooth::ranging::CsSecurityLevel;
+using aidl::android::hardware::bluetooth::ranging::IBluetoothChannelSounding;
+using aidl::android::hardware::bluetooth::ranging::
+ IBluetoothChannelSoundingSession;
+using aidl::android::hardware::bluetooth::ranging::
+ IBluetoothChannelSoundingSessionCallback;
+using aidl::android::hardware::bluetooth::ranging::RangingResult;
+using aidl::android::hardware::bluetooth::ranging::Reason;
+using aidl::android::hardware::bluetooth::ranging::ResultType;
+using aidl::android::hardware::bluetooth::ranging::SessionType;
+using aidl::android::hardware::bluetooth::ranging::VendorSpecificData;
+using ndk::ScopedAStatus;
+
+class BluetoothChannelSoundingSessionCallback
+ : public BnBluetoothChannelSoundingSessionCallback {
+ public:
+ ScopedAStatus onOpened(Reason reason) override;
+ ScopedAStatus onOpenFailed(Reason reason) override;
+ ScopedAStatus onResult(const RangingResult& in_result) override;
+ ScopedAStatus onClose(Reason reason) override;
+ ScopedAStatus onCloseFailed(Reason reason) override;
+};
+
+ScopedAStatus BluetoothChannelSoundingSessionCallback::onOpened(
+ Reason /*reason*/) {
+ return ::ndk::ScopedAStatus::ok();
+}
+ScopedAStatus BluetoothChannelSoundingSessionCallback::onOpenFailed(
+ Reason /*reason*/) {
+ return ::ndk::ScopedAStatus::ok();
+}
+ScopedAStatus BluetoothChannelSoundingSessionCallback::onResult(
+ const RangingResult& /*in_result*/) {
+ return ::ndk::ScopedAStatus::ok();
+}
+ScopedAStatus BluetoothChannelSoundingSessionCallback::onClose(
+ Reason /*reason*/) {
+ return ::ndk::ScopedAStatus::ok();
+}
+ScopedAStatus BluetoothChannelSoundingSessionCallback::onCloseFailed(
+ Reason /*reason*/) {
+ return ::ndk::ScopedAStatus::ok();
+}
+
+class BluetoothRangingTest : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ ALOGI("SetUp Ranging Test");
+ bluetooth_channel_sounding_ = IBluetoothChannelSounding::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(bluetooth_channel_sounding_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ ALOGI("TearDown Ranging Test");
+ bluetooth_channel_sounding_ = nullptr;
+ ASSERT_EQ(bluetooth_channel_sounding_, nullptr);
+ }
+
+ ScopedAStatus getVendorSpecificData(
+ std::optional<std::vector<std::optional<VendorSpecificData>>>*
+ _aidl_return);
+ ScopedAStatus getSupportedSessionTypes(
+ std::optional<std::vector<SessionType>>* _aidl_return);
+ ScopedAStatus getMaxSupportedCsSecurityLevel(CsSecurityLevel* _aidl_return);
+ ScopedAStatus openSession(
+ const BluetoothChannelSoundingParameters& in_params,
+ const std::shared_ptr<IBluetoothChannelSoundingSessionCallback>&
+ in_callback,
+ std::shared_ptr<IBluetoothChannelSoundingSession>* _aidl_return);
+
+ ScopedAStatus initBluetoothChannelSoundingSession(
+ std::shared_ptr<IBluetoothChannelSoundingSession>* session) {
+ BluetoothChannelSoundingParameters params;
+ std::shared_ptr<BluetoothChannelSoundingSessionCallback> callback = nullptr;
+ callback =
+ ndk::SharedRefBase::make<BluetoothChannelSoundingSessionCallback>();
+ ScopedAStatus status = openSession(params, callback, session);
+ return status;
+ }
+
+ private:
+ std::shared_ptr<IBluetoothChannelSounding> bluetooth_channel_sounding_;
+};
+
+ScopedAStatus BluetoothRangingTest::getVendorSpecificData(
+ std::optional<std::vector<std::optional<VendorSpecificData>>>*
+ _aidl_return) {
+ return bluetooth_channel_sounding_->getVendorSpecificData(_aidl_return);
+}
+ScopedAStatus BluetoothRangingTest::getSupportedSessionTypes(
+ std::optional<std::vector<SessionType>>* _aidl_return) {
+ return bluetooth_channel_sounding_->getSupportedSessionTypes(_aidl_return);
+}
+
+ScopedAStatus BluetoothRangingTest::getMaxSupportedCsSecurityLevel(
+ CsSecurityLevel* _aidl_return) {
+ return bluetooth_channel_sounding_->getMaxSupportedCsSecurityLevel(
+ _aidl_return);
+}
+ScopedAStatus BluetoothRangingTest::openSession(
+ const BluetoothChannelSoundingParameters& in_params,
+ const std::shared_ptr<IBluetoothChannelSoundingSessionCallback>&
+ in_callback,
+ std::shared_ptr<IBluetoothChannelSoundingSession>* _aidl_return) {
+ return bluetooth_channel_sounding_->openSession(in_params, in_callback,
+ _aidl_return);
+}
+
+TEST_P(BluetoothRangingTest, SetupAndTearDown) {}
+
+TEST_P(BluetoothRangingTest, GetVendorSpecificData) {
+ std::optional<std::vector<std::optional<VendorSpecificData>>>
+ vendor_specific_data;
+ ScopedAStatus status = getVendorSpecificData(&vendor_specific_data);
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(BluetoothRangingTest, GetSupportedSessionTypes) {
+ std::optional<std::vector<SessionType>> supported_session_types;
+ ScopedAStatus status = getSupportedSessionTypes(&supported_session_types);
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(BluetoothRangingTest, GetMaxSupportedCsSecurityLevel) {
+ CsSecurityLevel security_level;
+ ScopedAStatus status = getMaxSupportedCsSecurityLevel(&security_level);
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(BluetoothRangingTest, OpenSession) {
+ BluetoothChannelSoundingParameters params;
+ std::shared_ptr<BluetoothChannelSoundingSessionCallback> callback = nullptr;
+ callback =
+ ndk::SharedRefBase::make<BluetoothChannelSoundingSessionCallback>();
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ ScopedAStatus status = openSession(params, callback, &session);
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(BluetoothRangingTest, GetVendorSpecificReplies) {
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ auto status = initBluetoothChannelSoundingSession(&session);
+ ASSERT_TRUE(status.isOk());
+ if (session != nullptr) {
+ std::optional<std::vector<std::optional<VendorSpecificData>>>
+ vendor_specific_data;
+ status = session->getVendorSpecificReplies(&vendor_specific_data);
+ ASSERT_TRUE(status.isOk());
+ }
+}
+
+TEST_P(BluetoothRangingTest, GetSupportedResultTypes) {
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ auto status = initBluetoothChannelSoundingSession(&session);
+ ASSERT_TRUE(status.isOk());
+ if (session != nullptr) {
+ std::vector<ResultType> supported_result_types;
+ status = session->getSupportedResultTypes(&supported_result_types);
+ ASSERT_TRUE(status.isOk());
+ }
+}
+
+TEST_P(BluetoothRangingTest, IsAbortedProcedureRequired) {
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ auto status = initBluetoothChannelSoundingSession(&session);
+ ASSERT_TRUE(status.isOk());
+ if (session != nullptr) {
+ bool is_abort_procedure_required = true;
+ status = session->isAbortedProcedureRequired(&is_abort_procedure_required);
+ ASSERT_TRUE(status.isOk());
+ }
+}
+
+TEST_P(BluetoothRangingTest, WriteRawData) {
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ auto status = initBluetoothChannelSoundingSession(&session);
+ ASSERT_TRUE(status.isOk());
+ if (session != nullptr) {
+ ChannelSoudingRawData raw_data;
+ status = session->writeRawData(raw_data);
+ ASSERT_TRUE(status.isOk());
+ }
+}
+
+TEST_P(BluetoothRangingTest, CloseSession) {
+ std::shared_ptr<IBluetoothChannelSoundingSession> session;
+ auto status = initBluetoothChannelSoundingSession(&session);
+ ASSERT_TRUE(status.isOk());
+ if (session != nullptr) {
+ status = session->close(Reason::LOCAL_STACK_REQUEST);
+ ASSERT_TRUE(status.isOk());
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothRangingTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothRangingTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothChannelSounding::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
+}
\ No newline at end of file
diff --git a/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.xml b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.xml
new file mode 100644
index 0000000..624b77e
--- /dev/null
+++ b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright (C) 2023 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 VtsHalBluetoothRangingTargetTest.">
+ <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="VtsHalBluetoothRangingTargetTest->/data/local/tmp/VtsHalBluetoothRangingTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalBluetoothRangingTargetTest" />
+ </test>
+</configuration>
diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
index 79d3e60..754b05b 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -35,6 +35,7 @@
#include <broadcastradio-utils-aidl/UtilsV2.h>
#include <cutils/bitops.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <chrono>
#include <condition_variable>
@@ -76,12 +77,6 @@
constexpr int32_t kAidlVersion1 = 1;
constexpr int32_t kAidlVersion2 = 2;
-void printSkipped(const std::string& msg) {
- const auto testInfo = testing::UnitTest::GetInstance()->current_test_info();
- LOG(INFO) << "[ SKIPPED ] " << testInfo->test_case_name() << "." << testInfo->name()
- << " with message: " << msg;
-}
-
bool isValidAmFmFreq(int64_t freq, int aidlVersion) {
ProgramIdentifier id = bcutils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, freq);
if (aidlVersion == kAidlVersion1) {
@@ -385,7 +380,7 @@
auto startResult = mModule->startProgramListUpdates(filter);
if (startResult.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
- printSkipped("Program list not supported");
+ LOG(WARNING) << "Program list not supported";
return std::nullopt;
}
EXPECT_TRUE(startResult.isOk());
@@ -430,8 +425,7 @@
bool supported = getAmFmRegionConfig(/* full= */ false, &config);
if (!supported) {
- printSkipped("AM/FM not supported");
- return;
+ GTEST_SKIP() << "AM/FM not supported";
}
EXPECT_LE(popcountll(static_cast<unsigned long long>(config.fmDeemphasis)), 1);
@@ -459,8 +453,7 @@
bool supported = getAmFmRegionConfig(/* full= */ false, &config);
if (!supported) {
- printSkipped("AM/FM not supported");
- return;
+ GTEST_SKIP() << "AM/FM not supported";
}
EXPECT_GT(config.ranges.size(), 0u);
@@ -488,7 +481,7 @@
if (supported && supportsFM(config)) {
EXPECT_GE(popcountll(static_cast<unsigned long long>(config.fmDeemphasis)), 1);
} else {
- printSkipped("FM not supported");
+ GTEST_SKIP() << "FM not supported";
}
}
@@ -509,8 +502,7 @@
bool supported = getAmFmRegionConfig(/* full= */ true, &config);
if (!supported) {
- printSkipped("AM/FM not supported");
- return;
+ GTEST_SKIP() << "AM/FM not supported";
}
EXPECT_GT(config.ranges.size(), 0u);
@@ -536,8 +528,7 @@
auto halResult = mModule->getDabRegionConfig(&config);
if (halResult.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
- printSkipped("DAB not supported");
- return;
+ GTEST_SKIP() << "DAB not supported";
}
ASSERT_TRUE(halResult.isOk());
@@ -671,7 +662,7 @@
* - if it is supported, the method succeeds;
* - after a successful tune call, onCurrentProgramInfoChanged callback is
* invoked carrying a proper selector;
- * - program changes exactly to what was requested.
+ * - program changes to a program info with the program selector requested.
*/
TEST_P(BroadcastRadioHalTest, FmTune) {
LOG(DEBUG) << "FmTune Test";
@@ -715,8 +706,7 @@
LOG(DEBUG) << "HdTune Test";
auto programList = getProgramList();
if (!programList) {
- printSkipped("Empty station list, tune cannot be performed");
- return;
+ GTEST_SKIP() << "Empty station list, tune cannot be performed";
}
ProgramSelector hdSel = {};
ProgramIdentifier physicallyTunedToExpected = {};
@@ -732,8 +722,7 @@
break;
}
if (!hdStationPresent) {
- printSkipped("No HD stations in the list, tune cannot be performed");
- return;
+ GTEST_SKIP() << "No HD stations in the list, tune cannot be performed";
}
// try tuning
@@ -750,7 +739,7 @@
ProgramInfo infoCb = mCallback->getCurrentProgramInfo();
LOG(DEBUG) << "Current program info: " << infoCb.toString();
// it should tune exactly to what was requested
- EXPECT_EQ(infoCb.selector, hdSel);
+ EXPECT_EQ(infoCb.selector.primaryId, hdSel.primaryId);
EXPECT_EQ(infoCb.physicallyTunedTo, physicallyTunedToExpected);
}
@@ -762,7 +751,7 @@
* - if it is supported, the method succeeds;
* - after a successful tune call, onCurrentProgramInfoChanged callback is
* invoked carrying a proper selector;
- * - program changes exactly to what was requested.
+ * - program changes to a program info with the program selector requested.
*/
TEST_P(BroadcastRadioHalTest, DabTune) {
LOG(DEBUG) << "DabTune Test";
@@ -771,8 +760,7 @@
auto halResult = mModule->getDabRegionConfig(&config);
if (halResult.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
- printSkipped("DAB not supported");
- return;
+ GTEST_SKIP() << "DAB not supported";
}
ASSERT_TRUE(halResult.isOk());
ASSERT_NE(config.size(), 0U);
@@ -780,8 +768,7 @@
auto programList = getProgramList();
if (!programList) {
- printSkipped("Empty DAB station list, tune cannot be performed");
- return;
+ GTEST_SKIP() << "Empty DAB station list, tune cannot be performed";
}
ProgramSelector sel = {};
@@ -811,8 +798,7 @@
}
if (!dabStationPresent) {
- printSkipped("No DAB stations in the list, tune cannot be performed");
- return;
+ GTEST_SKIP() << "No DAB stations in the list, tune cannot be performed";
}
// try tuning
@@ -844,7 +830,7 @@
* Verifies that:
* - the method succeeds;
* - the program info is changed within kTuneTimeoutMs;
- * - works both directions and with or without skipping sub-channel.
+ * - works both directions and with or without ing sub-channel.
*/
TEST_P(BroadcastRadioHalTest, Seek) {
LOG(DEBUG) << "Seek Test";
@@ -854,8 +840,7 @@
auto result = mModule->seek(/* in_directionUp= */ true, /* in_skipSubChannel= */ true);
if (result.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
- printSkipped("Seek not supported");
- return;
+ GTEST_SKIP() << "Seek not supported";
}
EXPECT_TRUE(result.isOk());
@@ -905,8 +890,7 @@
auto result = mModule->step(/* in_directionUp= */ true);
if (result.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
- printSkipped("Step not supported");
- return;
+ GTEST_SKIP() << "Step not supported";
}
EXPECT_TRUE(result.isOk());
EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
@@ -957,8 +941,7 @@
auto result = mModule->seek(/* in_directionUp= */ true, /* in_skipSubChannel= */ true);
if (result.getServiceSpecificError() == notSupportedError) {
- printSkipped("Cancel is skipped because of seek not supported");
- return;
+ GTEST_SKIP() << "Cancel is skipped because of seek not supported";
}
EXPECT_TRUE(result.isOk());
@@ -1152,8 +1135,7 @@
std::optional<bcutils::ProgramInfoSet> completeList = getProgramList();
if (!completeList) {
- printSkipped("No program list available");
- return;
+ GTEST_SKIP() << "No program list available";
}
ProgramFilter amfmFilter = {};
@@ -1178,8 +1160,7 @@
}
if (expectedResultSize == 0) {
- printSkipped("No Am/FM programs available");
- return;
+ GTEST_SKIP() << "No Am/FM programs available";
}
std::optional<bcutils::ProgramInfoSet> amfmList = getProgramList(amfmFilter);
ASSERT_EQ(amfmList->size(), expectedResultSize) << "amfm filter result size is wrong";
@@ -1200,8 +1181,7 @@
std::optional<bcutils::ProgramInfoSet> completeList = getProgramList();
if (!completeList) {
- printSkipped("No program list available");
- return;
+ GTEST_SKIP() << "No program list available";
}
ProgramFilter dabFilter = {};
@@ -1225,8 +1205,7 @@
}
if (expectedResultSize == 0) {
- printSkipped("No DAB programs available");
- return;
+ GTEST_SKIP() << "No DAB programs available";
}
std::optional<bcutils::ProgramInfoSet> dabList = getProgramList(dabFilter);
ASSERT_EQ(dabList->size(), expectedResultSize) << "dab filter result size is wrong";
@@ -1245,8 +1224,7 @@
std::optional<bcutils::ProgramInfoSet> list = getProgramList();
if (!list) {
- printSkipped("No program list");
- return;
+ GTEST_SKIP() << "No program list";
}
for (const auto& program : *list) {
@@ -1297,8 +1275,7 @@
if (halResult.getServiceSpecificError() == resultToInt(Result::NOT_SUPPORTED)) {
ASSERT_EQ(closeHandle.get(), nullptr);
- printSkipped("Announcements not supported");
- return;
+ GTEST_SKIP() << "Announcements not supported";
}
ASSERT_TRUE(halResult.isOk());
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
index 3a1d762..01009ad 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
@@ -444,6 +444,7 @@
*
* For Android 15, the characteristics which need to be set are:
* - ANDROID_CONTROL_ZOOM_RATIO_RANGE
+ * - SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
*
* A service specific error will be returned on the following conditions
* INTERNAL_ERROR:
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index e335853..489bdc9 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -283,6 +283,64 @@
}
}
+TEST_P(CameraAidlTest, getSessionCharacteristics) {
+ if (flags::feature_combination_query()) {
+ std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+ for (const auto& name : cameraDeviceNames) {
+ std::shared_ptr<ICameraDevice> device;
+ ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
+ ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
+ ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
+ ret.getServiceSpecificError());
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_NE(device, nullptr);
+
+ CameraMetadata meta;
+ openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
+ &device /*out*/);
+
+ std::vector<AvailableStream> outputStreams;
+ camera_metadata_t* staticMeta =
+ reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ AvailableStream sampleStream = outputStreams[0];
+
+ int32_t streamId = 0;
+ Stream stream = {streamId,
+ StreamType::OUTPUT,
+ sampleStream.width,
+ sampleStream.height,
+ static_cast<PixelFormat>(sampleStream.format),
+ static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+ GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
+ Dataspace::UNKNOWN,
+ StreamRotation::ROTATION_0,
+ std::string(),
+ /*bufferSize*/ 0,
+ /*groupId*/ -1,
+ {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
+ RequestAvailableDynamicRangeProfilesMap::
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+
+ std::vector<Stream> streams = {stream};
+ StreamConfiguration config;
+ createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
+
+ CameraMetadata chars;
+ ret = device->getSessionCharacteristics(config, &chars);
+ ASSERT_TRUE(ret.isOk());
+ verifySessionCharacteristics(chars);
+ }
+ } else {
+ ALOGI("getSessionCharacteristics: Test skipped.\n");
+ GTEST_SKIP();
+ }
+}
+
// Verify that the torch strength level can be set and retrieved successfully.
TEST_P(CameraAidlTest, turnOnTorchWithStrengthLevel) {
std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -531,11 +589,7 @@
}
if (ret.isOk()) {
- const camera_metadata_t* metadata = (camera_metadata_t*)rawMetadata.metadata.data();
- size_t expectedSize = rawMetadata.metadata.size();
- int result = validate_camera_metadata_structure(metadata, &expectedSize);
- ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
- verifyRequestTemplate(metadata, reqTemplate);
+ validateDefaultRequestMetadata(reqTemplate, rawMetadata);
} else {
ASSERT_EQ(0u, rawMetadata.metadata.size());
}
@@ -546,24 +600,12 @@
ndk::ScopedAStatus ret2 =
device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
- // TODO: Do not allow OPERATION_NOT_SUPPORTED once HAL
- // implementation is in place.
- if (static_cast<Status>(ret2.getServiceSpecificError()) !=
- Status::OPERATION_NOT_SUPPORTED) {
- ASSERT_EQ(ret.isOk(), ret2.isOk());
- ASSERT_EQ(ret.getStatus(), ret2.getStatus());
+ ASSERT_EQ(ret.isOk(), ret2.isOk());
+ ASSERT_EQ(ret.getStatus(), ret2.getStatus());
- ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
- if (ret2.isOk()) {
- const camera_metadata_t* metadata =
- (camera_metadata_t*)rawMetadata2.metadata.data();
- size_t expectedSize = rawMetadata2.metadata.size();
- int result =
- validate_camera_metadata_structure(metadata, &expectedSize);
- ASSERT_TRUE((result == 0) ||
- (result == CAMERA_METADATA_VALIDATION_SHIFTED));
- verifyRequestTemplate(metadata, reqTemplate);
- }
+ ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
+ if (ret2.isOk()) {
+ validateDefaultRequestMetadata(reqTemplate, rawMetadata2);
}
}
}
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 8e72b3f..6a08f58 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1931,6 +1931,55 @@
}
}
+void CameraAidlTest::verifySessionCharacteristics(const CameraMetadata& chars) {
+ if (flags::feature_combination_query()) {
+ const camera_metadata_t* metadata =
+ reinterpret_cast<const camera_metadata_t*>(chars.metadata.data());
+
+ size_t expectedSize = chars.metadata.size();
+ int result = validate_camera_metadata_structure(metadata, &expectedSize);
+ ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+ size_t entryCount = get_camera_metadata_entry_count(metadata);
+ ASSERT_GT(entryCount, 0u);
+
+ camera_metadata_ro_entry entry;
+ int retcode = 0;
+ float maxDigitalZoom = 1.0;
+
+ retcode = find_camera_metadata_ro_entry(metadata, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ &entry);
+ // ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM should always be present.
+ if ((0 == retcode) && (entry.count == 1)) {
+ maxDigitalZoom = entry.data.f[0];
+ } else {
+ ADD_FAILURE() << "Get camera scalerAvailableMaxDigitalZoom failed!";
+ }
+
+ retcode = find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool hasZoomRatioRange = (0 == retcode && entry.count == 2);
+ if (!hasZoomRatioRange) {
+ return;
+ }
+ float minZoomRatio = entry.data.f[0];
+ float maxZoomRatio = entry.data.f[1];
+ constexpr float FLOATING_POINT_THRESHOLD = 0.00001f;
+ if (abs(maxDigitalZoom - maxZoomRatio) > FLOATING_POINT_THRESHOLD) {
+ ADD_FAILURE() << "Difference between maximum digital zoom " << maxDigitalZoom
+ << " and maximum zoom ratio " << maxZoomRatio
+ << " is greater than the threshold " << FLOATING_POINT_THRESHOLD << "!";
+ }
+ if (minZoomRatio > maxZoomRatio) {
+ ADD_FAILURE() << "Maximum zoom ratio is less than minimum zoom ratio!";
+ }
+ if (minZoomRatio > 1.0f) {
+ ADD_FAILURE() << "Minimum zoom ratio is more than 1.0!";
+ }
+ if (maxZoomRatio < 1.0f) {
+ ADD_FAILURE() << "Maximum zoom ratio is less than 1.0!";
+ }
+ }
+}
+
std::vector<ConcurrentCameraIdCombination> CameraAidlTest::getConcurrentDeviceCombinations(
std::shared_ptr<ICameraProvider>& provider) {
std::vector<ConcurrentCameraIdCombination> combinations;
@@ -4026,3 +4075,12 @@
}
}
}
+
+void CameraAidlTest::validateDefaultRequestMetadata(RequestTemplate reqTemplate,
+ const CameraMetadata& rawMetadata) {
+ const camera_metadata_t* metadata = (camera_metadata_t*)rawMetadata.metadata.data();
+ size_t expectedSize = rawMetadata.metadata.size();
+ int result = validate_camera_metadata_structure(metadata, &expectedSize);
+ ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+ verifyRequestTemplate(metadata, reqTemplate);
+}
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index b51544f..e3b0820 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -281,6 +281,8 @@
static void verifyStreamCombination(const std::shared_ptr<ICameraDevice>& device,
const StreamConfiguration& config, bool expectedStatus);
+ static void verifySessionCharacteristics(const CameraMetadata& chars);
+
static void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata,
const std::vector<uint8_t>& resultMetadata);
@@ -588,6 +590,9 @@
static void waitForReleaseFence(
std::vector<InFlightRequest::StreamBufferAndTimestamp>& resultOutputBuffers);
+ static void validateDefaultRequestMetadata(RequestTemplate reqTemplate,
+ const CameraMetadata& rawMetadata);
+
// Map from frame number to the in-flight request state
typedef std::unordered_map<uint32_t, std::shared_ptr<InFlightRequest>> InFlightMap;
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 9057788..777eb84 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -116,7 +116,7 @@
</hal>
<hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.face</name>
- <version>3</version>
+ <version>3-4</version>
<interface>
<name>IFace</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 2b134e9..cbeb18e 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -173,6 +173,14 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.bluetooth.lmp_event</name>
+ <version>1</version>
+ <interface>
+ <name>IBluetoothLmpEvent</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.boot</name>
<interface>
<name>IBootControl</name>
@@ -267,7 +275,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.health</name>
- <version>1-2</version>
+ <version>3</version>
<interface>
<name>IHealth</name>
<instance>default</instance>
@@ -325,6 +333,7 @@
<version>1</version>
<interface>
<name>ISecretkeeper</name>
+ <instance>default</instance>
<instance>nonsecure</instance>
</interface>
</hal>
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl
index e573556..c99169e 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl
@@ -45,4 +45,5 @@
byte chreApiMinorVersion;
char chrePatchVersion;
String[] supportedPermissions;
+ boolean supportsReliableMessages;
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl
index e38c251..a6951a8 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl
@@ -39,4 +39,6 @@
int messageType;
byte[] messageBody;
String[] permissions;
+ boolean isReliable;
+ int messageSequenceNumber;
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ErrorCode.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ErrorCode.aidl
new file mode 100644
index 0000000..8924658
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ErrorCode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@Backing(type="byte") @VintfStability
+enum ErrorCode {
+ OK = 0,
+ TRANSIENT_ERROR,
+ PERMANENT_ERROR,
+ PERMISSION_DENIED,
+ DESTINATION_NOT_FOUND,
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
index de8d752..7341e0e 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -48,5 +48,6 @@
long[] getPreloadedNanoappIds(in int contextHubId);
void onNanSessionStateChanged(in android.hardware.contexthub.NanSessionStateUpdate update);
void setTestMode(in boolean enable);
+ void sendMessageDeliveryStatusToHub(in int contextHubId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
const int EX_CONTEXT_HUB_UNSPECIFIED = (-1) /* -1 */;
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
index 4e99082..70f69c6 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
@@ -39,6 +39,7 @@
void handleContextHubAsyncEvent(in android.hardware.contexthub.AsyncEventType evt);
void handleTransactionResult(in int transactionId, in boolean success);
void handleNanSessionRequest(in android.hardware.contexthub.NanSessionRequest request);
+ void handleMessageDeliveryStatus(in char hostEndpointId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
byte[16] getUuid();
String getName();
const int CONTEXTHUB_NAN_TRANSACTION_TIMEOUT_MS = 10000;
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/MessageDeliveryStatus.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/MessageDeliveryStatus.aidl
new file mode 100644
index 0000000..40dac13
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/MessageDeliveryStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable MessageDeliveryStatus {
+ int messageSequenceNumber;
+ android.hardware.contexthub.ErrorCode errorCode;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl b/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl
index c0fa702..42dba10 100644
--- a/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl
@@ -33,7 +33,9 @@
/** Peak MIPs this platform can deliver */
float peakMips;
- /** The maximum length in bytes of the message that can be sent to the Context Hub. */
+ /**
+ * The maximum length in bytes of a message sent to the Context Hub.
+ */
int maxSupportedMessageLengthBytes;
/**
@@ -61,4 +63,11 @@
* are granted in order to communicate with them.
*/
String[] supportedPermissions;
+
+ /**
+ * True if the Context Hub supports reliable messages. False otherwise, in which case
+ * ContextHubMessage.isReliable must always be set to false. See
+ * ContextHubMessage.isReliable for more information.
+ */
+ boolean supportsReliableMessages;
}
diff --git a/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
index 95d478e..3cd20ca 100644
--- a/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
@@ -50,4 +50,35 @@
* of the permissions that the sending nanoapp is using.
*/
String[] permissions;
+
+ /**
+ * Whether the message is reliable.
+ *
+ * For reliable messages, the receiver is expected to acknowledge the reception of
+ * the message by sending a message delivery status back to the sender. Acknowledgment of
+ * the message must be returned within 1 second.
+ *
+ * For reliable messages sent by the host, the Context Hub invokes
+ * IContextHubCallback#handleMessageDeliveryStatus to report the status.
+ *
+ * For reliable messages sent by the Context Hub, the host calls
+ * IContextHub#sendMessageDeliveryStatusToHub to report the status.
+ */
+ boolean isReliable;
+
+ /**
+ * The sequence number for a reliable message. For less than 2^32 messages, each message sent
+ * from a Context Hub will have a unique sequence number generated by the Context Hub, and the
+ * sequence numbers are guaranteed to not be reused for unacknowledged messages. For messages
+ * sent to the Context Hub, sequence numbers are only guaranteed to be unique within the scope
+ * of a given hostEndPoint. The sequence number may be reused if more than 2^32 messages are
+ * sent, due to the size limit of int.
+ *
+ * The sequence number is used only for reliable messages. There is no guarantee of strict
+ * ordering of messages. The recipient may receive messages with gaps between the sequence
+ * numbers. This is not an indication of a missed message.
+ *
+ * See isReliable for more information.
+ */
+ int messageSequenceNumber;
}
diff --git a/contexthub/aidl/android/hardware/contexthub/ErrorCode.aidl b/contexthub/aidl/android/hardware/contexthub/ErrorCode.aidl
new file mode 100644
index 0000000..22e7ea1
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/ErrorCode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.contexthub;
+
+@VintfStability
+@Backing(type="byte")
+enum ErrorCode {
+ /**
+ * No Error.
+ */
+ OK = 0,
+
+ /**
+ * A generic transient error. The sender may retry the
+ * operation, but there is no guarantee of success.
+ */
+ TRANSIENT_ERROR,
+
+ /**
+ * A generic permanent error. The sender should not retry the operation.
+ */
+ PERMANENT_ERROR,
+
+ /**
+ * The request failed because the sender does not have necessary permissions.
+ * The sender should not retry the operation.
+ */
+ PERMISSION_DENIED,
+
+ /**
+ * The request failed because the destination was not found.
+ * The sender should not retry the operation.
+ */
+ DESTINATION_NOT_FOUND,
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
index 9683d2d..b146ff8 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -20,6 +20,7 @@
import android.hardware.contexthub.ContextHubMessage;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.IContextHubCallback;
+import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionStateUpdate;
import android.hardware.contexthub.NanoappBinary;
import android.hardware.contexthub.NanoappInfo;
@@ -147,7 +148,7 @@
/**
* Register a callback for the HAL implementation to send asynchronous messages to the service
- * from a Context hub. There can only be one callback registered for a single Context Hub ID.
+ * from a Context hub. Each HAL client can only have one callback for each Context Hub ID.
*
* A call to this function when a callback has already been registered must override the
* previous registration.
@@ -236,6 +237,21 @@
void setTestMode(in boolean enable);
/**
+ * Sends a message delivery status to the Context Hub in response to receiving a
+ * ContextHubMessage with isReliable=true. Each reliable message should have a
+ * messageDeliveryStatus response. This method sends the message delivery status
+ * back to the Context Hub.
+ *
+ * @param contextHubId The identifier of the Context Hub.
+ * @param messageDeliveryStatus The status to be sent.
+ *
+ * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
+ * this hub.
+ */
+ void sendMessageDeliveryStatusToHub(
+ in int contextHubId, in MessageDeliveryStatus messageDeliveryStatus);
+
+ /**
* Error codes that are used as service specific errors with the AIDL return
* value EX_SERVICE_SPECIFIC.
*/
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
index ebfc4d8..1aa0776 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
@@ -18,6 +18,7 @@
import android.hardware.contexthub.AsyncEventType;
import android.hardware.contexthub.ContextHubMessage;
+import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionRequest;
import android.hardware.contexthub.NanoappInfo;
@@ -91,6 +92,19 @@
void handleNanSessionRequest(in NanSessionRequest request);
/**
+ * This callback is passed by the Contexthub service to the HAL
+ * implementation to allow the HAL to send the response for a reliable message.
+ * The response is the message delivery status of a recently sent message. See
+ * sendMessageDeliveryStatusToHub() for more details.
+ *
+ * @param hostEndPointId The ID of the host endpoint associated with this message delivery
+ * status.
+ * @param messageDeliveryStatus The status to be sent.
+ */
+ void handleMessageDeliveryStatus(
+ in char hostEndpointId, in MessageDeliveryStatus messageDeliveryStatus);
+
+ /**
* This callback is passed to the HAL implementation to allow the HAL to request a UUID that
* uniquely identifies a client.
*
diff --git a/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl b/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl
new file mode 100644
index 0000000..ae425b3
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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.contexthub;
+
+import android.hardware.contexthub.ErrorCode;
+
+@VintfStability
+parcelable MessageDeliveryStatus {
+ /**
+ * The messageSequenceNumber of the ContextHubMessage to which this status applies.
+ */
+ int messageSequenceNumber;
+
+ /**
+ * The error code associated with this status.
+ */
+ ErrorCode errorCode;
+}
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index 5272957..bd483d7 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -16,10 +16,7 @@
#include "contexthub-impl/ContextHub.h"
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace contexthub {
+namespace aidl::android::hardware::contexthub {
using ::ndk::ScopedAStatus;
@@ -34,10 +31,11 @@
hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
hub.chreApiMajorVersion = 1;
hub.chreApiMinorVersion = 6;
+ hub.supportsReliableMessages = false;
out_contextHubInfos->push_back(hub);
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
// We don't expose any nanoapps for the default impl, therefore all nanoapp-related APIs fail.
@@ -63,14 +61,14 @@
}
ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId) {
if (in_contextHubId == kMockHubId && mCallback != nullptr) {
std::vector<NanoappInfo> nanoapps;
mCallback->handleNanoappInfo(nanoapps);
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -85,18 +83,18 @@
for (uint64_t i = 0; i < 10; ++i) {
out_preloadedNanoappIds->push_back(i);
}
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onNanSessionStateChanged(const NanSessionStateUpdate& /*in_update*/) {
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
const std::shared_ptr<IContextHubCallback>& in_cb) {
if (in_contextHubId == kMockHubId) {
mCallback = in_cb;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -108,20 +106,20 @@
// Return true here to indicate that the HAL has accepted the message.
// Successful delivery of the message to a nanoapp should be handled at
// a higher level protocol.
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
} else {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
}
ScopedAStatus ContextHub::setTestMode(bool /* enable */) {
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
mConnectedHostEndpoints.insert(in_info.hostEndpointId);
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
@@ -129,10 +127,13 @@
mConnectedHostEndpoints.erase(in_hostEndpointId);
}
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-} // namespace contexthub
-} // namespace hardware
-} // namespace android
-} // namespace aidl
+ScopedAStatus ContextHub::sendMessageDeliveryStatusToHub(
+ int32_t /* in_contextHubId */,
+ const MessageDeliveryStatus& /* in_messageDeliveryStatus */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+} // namespace aidl::android::hardware::contexthub
diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
index 7a2cfd1..72e8b3b 100644
--- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -49,6 +49,9 @@
::ndk::ScopedAStatus onHostEndpointDisconnected(char16_t in_hostEndpointId) override;
::ndk::ScopedAStatus onNanSessionStateChanged(const NanSessionStateUpdate& in_update) override;
+ ::ndk::ScopedAStatus sendMessageDeliveryStatusToHub(
+ int32_t in_contextHubId,
+ const MessageDeliveryStatus& in_messageDeliveryStatus) override;
private:
static constexpr uint32_t kMockHubId = 0;
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
index 76b25b6..fd55b80 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -36,9 +36,11 @@
using ::android::hardware::contexthub::AsyncEventType;
using ::android::hardware::contexthub::ContextHubInfo;
using ::android::hardware::contexthub::ContextHubMessage;
+using ::android::hardware::contexthub::ErrorCode;
using ::android::hardware::contexthub::HostEndpointInfo;
using ::android::hardware::contexthub::IContextHub;
using ::android::hardware::contexthub::IContextHubCallbackDefault;
+using ::android::hardware::contexthub::MessageDeliveryStatus;
using ::android::hardware::contexthub::NanoappBinary;
using ::android::hardware::contexthub::NanoappInfo;
using ::android::hardware::contexthub::NanoappRpcService;
@@ -132,6 +134,12 @@
return Status::ok();
}
+ Status handleMessageDeliveryStatus(
+ char16_t /* hostEndPointId */,
+ const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
+ return Status::ok();
+ }
+
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -172,6 +180,12 @@
return Status::ok();
}
+ Status handleMessageDeliveryStatus(
+ char16_t /* hostEndPointId */,
+ const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
+ return Status::ok();
+ }
+
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -248,6 +262,12 @@
return Status::ok();
}
+ Status handleMessageDeliveryStatus(
+ char16_t /* hostEndPointId */,
+ const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
+ return Status::ok();
+ }
+
Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
*out_uuid = kUuid;
return Status::ok();
@@ -431,6 +451,20 @@
}
}
+TEST_P(ContextHubAidl, TestSendMessageDeliveryStatusToHub) {
+ MessageDeliveryStatus messageDeliveryStatus;
+ messageDeliveryStatus.messageSequenceNumber = 123;
+ messageDeliveryStatus.errorCode = ErrorCode::OK;
+
+ Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
+ if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ } else {
+ EXPECT_TRUE(status.isOk());
+ }
+}
+
std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
index f02f8aa..ee004d6 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
@@ -45,4 +45,5 @@
BOOT_DISPLAY_CONFIG = 5,
HDR_OUTPUT_CONVERSION_CONFIG = 6,
REFRESH_RATE_CHANGED_CALLBACK_DEBUG = 7,
+ LAYER_LIFECYCLE_BATCH_COMMAND = 8,
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
index 2b9801a..e9305e1 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
@@ -36,4 +36,5 @@
parcelable RefreshRateChangedDebugData {
long display;
int vsyncPeriodNanos;
+ int refreshPeriodNanos;
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
index bb2569f..7377b4b 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -42,7 +42,7 @@
int averageRefreshPeriodNs;
}
parcelable NotifyExpectedPresentConfig {
- int notifyExpectedPresentHeadsUpNs;
- int notifyExpectedPresentTimeoutNs;
+ int headsUpNs;
+ int timeoutNs;
}
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
index 4638610..1dfc074 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
@@ -86,4 +86,14 @@
* @see IComposerCallback.onRefreshRateChangedDebug
*/
REFRESH_RATE_CHANGED_CALLBACK_DEBUG = 7,
+
+ /**
+ * Specifies that the device HAL supports the batching of layer creation and destruction
+ * for better performance.
+ *
+ * @see IComposerClient.executeCommands
+ * @see LayerCommand.layerLifecycleBatchCommandType
+ * @see LayerCommand.newBufferSlotCount
+ */
+ LAYER_LIFECYCLE_BATCH_COMMAND = 8,
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 725c947..213e8e9 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -895,9 +895,9 @@
*
* The framework will call this function based on the parameters specified in
* DisplayConfiguration.VrrConfig:
- * - notifyExpectedPresentTimeoutNs specifies the idle time from the previous present command
- * where the framework must send the early hint for the next frame.
- * - notifyExpectedPresentHeadsUpNs specifies minimal time that framework must send
+ * - notifyExpectedPresentConfig.timeoutNs specifies the idle time from the previous
+ * present command where the framework must send the early hint for the next frame.
+ * - notifyExpectedPresentConfig.headsUpNs specifies minimal time that framework must send
* the early hint before the next frame.
*
* The framework can omit calling this API when the next present command matches
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
index c1f78d6..11c0112 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.aidl
@@ -27,4 +27,15 @@
* The display vsync period in nanoseconds.
*/
int vsyncPeriodNanos;
+
+ /**
+ * The refresh period of the display in nanoseconds.
+ * On VRR (Variable Refresh Rate) displays, refreshPeriodNanos can be different from the
+ * vsyncPeriodNanos because not every vsync cycle of the display is a refresh cycle.
+ * This should be set to the current refresh period.
+ * On non-VRR displays this value should be equal to vsyncPeriodNanos
+ *
+ * @see vsyncPeriodNanos
+ */
+ int refreshPeriodNanos;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
index 3b241ba..99c1c62 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -45,15 +45,16 @@
* The minimal time in nanoseconds that IComposerClient.notifyExpectedPresent needs to be
* called ahead of an expectedPresentTime provided on a presentDisplay command.
*/
- int notifyExpectedPresentHeadsUpNs;
+ int headsUpNs;
/**
* The time in nanoseconds that represents a timeout from the previous presentDisplay, which
* after this point the display needs a call to IComposerClient.notifyExpectedPresent before
- * sending the next frame. If set to 0, there is no need to call
+ * sending the next frame.
+ * If set to 0, hint is sent for every frame.
* IComposerClient.notifyExpectedPresent for timeout.
*/
- int notifyExpectedPresentTimeoutNs;
+ int timeoutNs;
}
/**
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index 8605628..c72ec69 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -293,8 +293,8 @@
TestBufferLayer::TestBufferLayer(const std::shared_ptr<VtsComposerClient>& client,
TestRenderEngine& renderEngine, int64_t display, uint32_t width,
uint32_t height, common::PixelFormat format,
- Composition composition)
- : TestLayer{client, display}, mRenderEngine(renderEngine) {
+ ComposerClientWriter& writer, Composition composition)
+ : TestLayer{client, display, writer}, mRenderEngine(renderEngine) {
mComposition = composition;
mWidth = width;
mHeight = height;
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index ee20573..8ac0f4b 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -50,9 +50,10 @@
class TestLayer {
public:
- TestLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display)
+ TestLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display,
+ ComposerClientWriter& writer)
: mDisplay(display) {
- const auto& [status, layer] = client->createLayer(display, kBufferSlotCount);
+ const auto& [status, layer] = client->createLayer(display, kBufferSlotCount, &writer);
EXPECT_TRUE(status.isOk());
mLayer = layer;
}
@@ -108,8 +109,9 @@
class TestColorLayer : public TestLayer {
public:
- TestColorLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display)
- : TestLayer{client, display} {}
+ TestColorLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display,
+ ComposerClientWriter& writer)
+ : TestLayer{client, display, writer} {}
void write(ComposerClientWriter& writer) override;
@@ -125,7 +127,7 @@
public:
TestBufferLayer(const std::shared_ptr<VtsComposerClient>& client,
TestRenderEngine& renderEngine, int64_t display, uint32_t width,
- uint32_t height, common::PixelFormat format,
+ uint32_t height, common::PixelFormat format, ComposerClientWriter& writer,
Composition composition = Composition::DEVICE);
void write(ComposerClientWriter& writer) override;
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 11b995e..2c24bfb 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -33,6 +33,14 @@
mComposer = IComposer::fromBinder(binder);
ALOGE_IF(mComposer == nullptr, "Failed to acquire the composer from the binder");
}
+
+ const auto& [status, capabilities] = getCapabilities();
+ EXPECT_TRUE(status.isOk());
+ if (std::any_of(capabilities.begin(), capabilities.end(), [&](const Capability& cap) {
+ return cap == Capability::LAYER_LIFECYCLE_BATCH_COMMAND;
+ })) {
+ mSupportsBatchedCreateLayer = true;
+ }
}
ScopedAStatus VtsComposerClient::createClient() {
@@ -54,8 +62,8 @@
return mComposerClient->registerCallback(mComposerCallback);
}
-bool VtsComposerClient::tearDown() {
- return verifyComposerCallbackParams() && destroyAllLayers();
+bool VtsComposerClient::tearDown(ComposerClientWriter* writer) {
+ return verifyComposerCallbackParams() && destroyAllLayers(writer);
}
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() const {
@@ -86,7 +94,16 @@
}
std::pair<ScopedAStatus, int64_t> VtsComposerClient::createLayer(int64_t display,
- int32_t bufferSlotCount) {
+ int32_t bufferSlotCount,
+ ComposerClientWriter* writer) {
+ if (mSupportsBatchedCreateLayer) {
+ int64_t layer = mNextLayerHandle++;
+ writer->setLayerLifecycleBatchCommandType(display, layer,
+ LayerLifecycleBatchCommandType::CREATE);
+ writer->setNewBufferSlotCount(display, layer, bufferSlotCount);
+ return {addLayerToDisplayResources(display, layer), layer};
+ }
+
int64_t outLayer;
auto status = mComposerClient->createLayer(display, bufferSlotCount, &outLayer);
@@ -96,14 +113,20 @@
return {addLayerToDisplayResources(display, outLayer), outLayer};
}
-ScopedAStatus VtsComposerClient::destroyLayer(int64_t display, int64_t layer) {
- auto status = mComposerClient->destroyLayer(display, layer);
-
- if (!status.isOk()) {
- return status;
+ScopedAStatus VtsComposerClient::destroyLayer(int64_t display, int64_t layer,
+ ComposerClientWriter* writer) {
+ if (mSupportsBatchedCreateLayer) {
+ writer->setLayerLifecycleBatchCommandType(display, layer,
+ LayerLifecycleBatchCommandType::DESTROY);
+ } else {
+ auto status = mComposerClient->destroyLayer(display, layer);
+ if (!status.isOk()) {
+ return status;
+ }
}
+
removeLayerFromDisplayResources(display, layer);
- return status;
+ return ScopedAStatus::ok();
}
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getActiveConfig(int64_t display) {
@@ -517,7 +540,8 @@
void VtsComposerClient::addDisplayConfigs(VtsDisplay* vtsDisplay,
const std::vector<DisplayConfiguration>& configs) {
for (const auto& config : configs) {
- vtsDisplay->addDisplayConfig(config.configId, {config.vsyncPeriod, config.configGroup});
+ vtsDisplay->addDisplayConfig(config.configId,
+ {config.vsyncPeriod, config.configGroup, config.vrrConfig});
}
}
@@ -631,7 +655,7 @@
return interfaceVersion >= 3;
}
-bool VtsComposerClient::destroyAllLayers() {
+bool VtsComposerClient::destroyAllLayers(ComposerClientWriter* writer) {
std::unordered_map<int64_t, DisplayResource> physicalDisplays;
while (!mDisplayResources.empty()) {
const auto& it = mDisplayResources.begin();
@@ -639,7 +663,7 @@
while (!resource.layers.empty()) {
auto layer = *resource.layers.begin();
- const auto status = destroyLayer(display, layer);
+ const auto status = destroyLayer(display, layer, writer);
if (!status.isOk()) {
ALOGE("Unable to destroy all the layers, failed at layer %" PRId64 " with error %s",
layer, status.getDescription().c_str());
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index b45c71f..fabc82a 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -25,6 +25,7 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/hardware/graphics/composer3/ComposerClientReader.h>
+#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
#include <binder/ProcessState.h>
#include <gtest/gtest.h>
#include <ui/Fence.h>
@@ -59,7 +60,7 @@
ScopedAStatus createClient();
- bool tearDown();
+ bool tearDown(ComposerClientWriter*);
std::pair<ScopedAStatus, int32_t> getInterfaceVersion() const;
@@ -69,9 +70,10 @@
ScopedAStatus destroyVirtualDisplay(int64_t display);
- std::pair<ScopedAStatus, int64_t> createLayer(int64_t display, int32_t bufferSlotCount);
+ std::pair<ScopedAStatus, int64_t> createLayer(int64_t display, int32_t bufferSlotCount,
+ ComposerClientWriter*);
- ScopedAStatus destroyLayer(int64_t display, int64_t layer);
+ ScopedAStatus destroyLayer(int64_t display, int64_t layer, ComposerClientWriter*);
std::pair<ScopedAStatus, int32_t> getActiveConfig(int64_t display);
@@ -211,7 +213,7 @@
void removeLayerFromDisplayResources(int64_t display, int64_t layer);
- bool destroyAllLayers();
+ bool destroyAllLayers(ComposerClientWriter*);
bool verifyComposerCallbackParams();
@@ -229,6 +231,8 @@
std::shared_ptr<IComposerClient> mComposerClient;
std::shared_ptr<GraphicsComposerCallback> mComposerCallback;
std::unordered_map<int64_t, DisplayResource> mDisplayResources;
+ bool mSupportsBatchedCreateLayer = false;
+ std::atomic<int64_t> mNextLayerHandle = 1;
};
class VtsDisplay {
@@ -253,10 +257,14 @@
int32_t getDisplayHeight() const { return mDisplayHeight; }
struct DisplayConfig {
- DisplayConfig(int32_t vsyncPeriod_, int32_t configGroup_)
- : vsyncPeriod(vsyncPeriod_), configGroup(configGroup_) {}
+ DisplayConfig(int32_t vsyncPeriod_, int32_t configGroup_,
+ std::optional<VrrConfig> vrrConfig_ = {})
+ : vsyncPeriod(vsyncPeriod_),
+ configGroup(configGroup_),
+ vrrConfig(std::move(vrrConfig_)) {}
int32_t vsyncPeriod;
int32_t configGroup;
+ std::optional<VrrConfig> vrrConfig;
};
void addDisplayConfig(int32_t config, DisplayConfig displayConfig) {
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 2e3f4df..164e6d5 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -86,7 +86,7 @@
void TearDown() override {
ASSERT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk());
- ASSERT_TRUE(mComposerClient->tearDown());
+ ASSERT_TRUE(mComposerClient->tearDown(mWriter.get()));
mComposerClient.reset();
const auto errors = mReader.takeErrors();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -201,7 +201,8 @@
return;
}
- auto layer = std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ auto layer =
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setColor(BLUE);
layer->setDisplayFrame(coloredSquare);
@@ -270,7 +271,7 @@
auto layer = std::make_shared<TestBufferLayer>(
mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), common::PixelFormat::RGBA_8888);
+ getDisplayHeight(), common::PixelFormat::RGBA_8888, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
@@ -315,7 +316,8 @@
return;
}
- auto layer = std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ auto layer =
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setColor(BLUE);
layer->setDisplayFrame(coloredSquare);
@@ -454,9 +456,9 @@
expectedColors, getDisplayWidth(),
{0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, BLUE);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
- getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), PixelFormat::RGBA_FP16);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight(), PixelFormat::RGBA_FP16, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
@@ -550,7 +552,7 @@
auto deviceLayer = std::make_shared<TestBufferLayer>(
mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight() / 2, PixelFormat::RGBA_8888);
+ getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter);
std::vector<Color> deviceColors(deviceLayer->getWidth() * deviceLayer->getHeight());
ReadbackHelper::fillColorsArea(deviceColors, static_cast<int32_t>(deviceLayer->getWidth()),
{0, 0, static_cast<int32_t>(deviceLayer->getWidth()),
@@ -574,7 +576,7 @@
auto clientLayer = std::make_shared<TestBufferLayer>(
mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), clientWidth,
- clientHeight, PixelFormat::RGBA_FP16, Composition::DEVICE);
+ clientHeight, PixelFormat::RGBA_FP16, *mWriter, Composition::DEVICE);
common::Rect clientFrame = {0, getDisplayHeight() / 2, getDisplayWidth(),
getDisplayHeight()};
clientLayer->setDisplayFrame(clientFrame);
@@ -643,9 +645,9 @@
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
- getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
@@ -714,7 +716,8 @@
return;
}
- auto layer = std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ auto layer =
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
layer->setColor(RED);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
@@ -774,9 +777,9 @@
expectedColors, getDisplayWidth(),
{0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, BLUE);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
- getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
@@ -828,11 +831,13 @@
common::Rect redRect = {0, 0, getDisplayWidth(), getDisplayHeight() / 2};
common::Rect blueRect = {0, getDisplayHeight() / 4, getDisplayWidth(), getDisplayHeight()};
- auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ auto redLayer =
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
redLayer->setColor(RED);
redLayer->setDisplayFrame(redRect);
- auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ auto blueLayer =
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
blueLayer->setColor(BLUE);
blueLayer->setDisplayFrame(blueRect);
blueLayer->setZOrder(5);
@@ -914,14 +919,14 @@
static constexpr float kMaxBrightnessNits = 300.f;
const auto redLayer =
- std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
redLayer->setColor(RED);
redLayer->setDisplayFrame(redRect);
redLayer->setWhitePointNits(kMaxBrightnessNits);
redLayer->setBrightness(1.f);
const auto dimmerRedLayer =
- std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
dimmerRedLayer->setColor(RED);
dimmerRedLayer->setDisplayFrame(dimmerRedRect);
// Intentionally use a small dimming ratio as some implementations may be more likely to
@@ -992,14 +997,14 @@
mTopLayerColor);
auto backgroundLayer =
- std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
backgroundLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
backgroundLayer->setZOrder(0);
backgroundLayer->setColor(mBackgroundColor);
- auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
- getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(Dataspace::UNKNOWN);
@@ -1190,7 +1195,7 @@
GraphicsCompositionTest::SetUp();
auto backgroundLayer =
- std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
+ std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter);
backgroundLayer->setColor({0.0f, 0.0f, 0.0f, 0.0f});
backgroundLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
backgroundLayer->setZOrder(0);
@@ -1202,7 +1207,7 @@
mLayer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
getPrimaryDisplayId(), mSideLength, mSideLength,
- PixelFormat::RGBA_8888);
+ PixelFormat::RGBA_8888, *mWriter);
mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
mLayer->setZOrder(10);
@@ -1388,7 +1393,7 @@
void makeLayer() {
mLayer = std::make_shared<TestBufferLayer>(
mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), common::PixelFormat::RGBA_8888);
+ getDisplayHeight(), common::PixelFormat::RGBA_8888, *mWriter);
mLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
mLayer->setZOrder(10);
mLayer->setAlpha(1.f);
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index a53eb38..5ff420a 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -70,7 +70,7 @@
}
void TearDown() override {
- ASSERT_TRUE(mComposerClient->tearDown());
+ ASSERT_TRUE(mComposerClient->tearDown(nullptr));
mComposerClient.reset();
}
@@ -832,36 +832,58 @@
}
TEST_P(GraphicsComposerAidlTest, CreateLayer) {
+ if (hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "Create layer will be tested in GraphicsComposerAidlBatchedCommandTest";
+ return;
+ }
+
const auto& [status, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, nullptr);
EXPECT_TRUE(status.isOk());
- EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer).isOk());
+ EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, nullptr).isOk());
}
TEST_P(GraphicsComposerAidlTest, CreateLayer_BadDisplay) {
- const auto& [status, _] = mComposerClient->createLayer(getInvalidDisplayId(), kBufferSlotCount);
+ if (hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "Create layer will be tested in GraphicsComposerAidlBatchedCommandTest";
+ return;
+ }
+
+ const auto& [status, _] =
+ mComposerClient->createLayer(getInvalidDisplayId(), kBufferSlotCount, nullptr);
EXPECT_FALSE(status.isOk());
EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_BAD_DISPLAY));
}
TEST_P(GraphicsComposerAidlTest, DestroyLayer_BadDisplay) {
+ if (hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "Destroy layer will be tested in GraphicsComposerAidlBatchedCommandTest";
+ return;
+ }
+
const auto& [status, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, nullptr);
EXPECT_TRUE(status.isOk());
- const auto& destroyStatus = mComposerClient->destroyLayer(getInvalidDisplayId(), layer);
+ const auto& destroyStatus =
+ mComposerClient->destroyLayer(getInvalidDisplayId(), layer, nullptr);
EXPECT_FALSE(destroyStatus.isOk());
EXPECT_NO_FATAL_FAILURE(
assertServiceSpecificError(destroyStatus, IComposerClient::EX_BAD_DISPLAY));
- ASSERT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer).isOk());
+ ASSERT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, nullptr).isOk());
}
TEST_P(GraphicsComposerAidlTest, DestroyLayer_BadLayerError) {
+ if (hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "Destroy layer will be tested in GraphicsComposerAidlBatchedCommandTest";
+ return;
+ }
+
// We haven't created any layers yet, so any id should be invalid
- const auto& status = mComposerClient->destroyLayer(getPrimaryDisplayId(), /*layer*/ 1);
+ const auto& status = mComposerClient->destroyLayer(getPrimaryDisplayId(), /*layer*/ 1, nullptr);
EXPECT_FALSE(status.isOk());
EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_BAD_LAYER));
@@ -1171,6 +1193,12 @@
}
}
+TEST_P(GraphicsComposerAidlTest, LayerLifecycleCapabilityNotSupportedOnOldVersions) {
+ if (hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ EXPECT_GE(getInterfaceVersion(), 3);
+ }
+}
+
class GraphicsComposerAidlV2Test : public GraphicsComposerAidlTest {
protected:
void SetUp() override {
@@ -1275,8 +1303,8 @@
if (vrrConfig.notifyExpectedPresentConfig) {
const auto& notifyExpectedPresentConfig =
*vrrConfig.notifyExpectedPresentConfig;
- EXPECT_GT(0, notifyExpectedPresentConfig.notifyExpectedPresentHeadsUpNs);
- EXPECT_GE(0, notifyExpectedPresentConfig.notifyExpectedPresentTimeoutNs);
+ EXPECT_GE(notifyExpectedPresentConfig.headsUpNs, 0);
+ EXPECT_GE(notifyExpectedPresentConfig.timeoutNs, 0);
}
}
}
@@ -1376,6 +1404,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
+ ASSERT_TRUE(mComposerClient->tearDown(&getWriter(getPrimaryDisplayId())));
ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
}
@@ -1463,10 +1492,10 @@
RenderIntent::COLORIMETRIC)
.isOk());
- const auto& [status, layer] =
- mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount);
- EXPECT_TRUE(status.isOk());
auto& writer = getWriter(display.getDisplayId());
+ const auto& [status, layer] =
+ mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(status.isOk());
{
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
ASSERT_NE(nullptr, buffer);
@@ -1506,7 +1535,7 @@
execute();
}
- EXPECT_TRUE(mComposerClient->destroyLayer(display.getDisplayId(), layer).isOk());
+ EXPECT_TRUE(mComposerClient->destroyLayer(display.getDisplayId(), layer, &writer).isOk());
}
sp<::android::Fence> presentAndGetFence(
@@ -1541,15 +1570,16 @@
}
int64_t createOnScreenLayer(Composition composition = Composition::DEVICE) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [status, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(status.isOk());
Rect displayFrame{0, 0, getPrimaryDisplay().getDisplayWidth(),
getPrimaryDisplay().getDisplayHeight()};
FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(),
(float)getPrimaryDisplay().getDisplayHeight()};
configureLayer(getPrimaryDisplay(), layer, composition, displayFrame, cropRect);
- auto& writer = getWriter(getPrimaryDisplayId());
+
writer.setLayerDataspace(getPrimaryDisplayId(), layer, common::Dataspace::UNKNOWN);
return layer;
}
@@ -1758,10 +1788,10 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerColorTransform) {
- const auto& [status, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
- EXPECT_TRUE(status.isOk());
auto& writer = getWriter(getPrimaryDisplayId());
+ const auto& [status, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(status.isOk());
writer.setLayerColorTransform(getPrimaryDisplayId(), layer, kIdentity.data());
execute();
@@ -1773,6 +1803,7 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetDisplayBrightness) {
+ EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk());
const auto& [status, capabilities] =
mComposerClient->getDisplayCapabilities(getPrimaryDisplayId());
ASSERT_TRUE(status.isOk());
@@ -1899,7 +1930,7 @@
ASSERT_NE(nullptr, handle);
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
Rect displayFrame{0, 0, getPrimaryDisplay().getDisplayWidth(),
@@ -1936,15 +1967,15 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerCursorPosition) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
const auto handle = buffer->handle;
ASSERT_NE(nullptr, handle);
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
Rect displayFrame{0, 0, getPrimaryDisplay().getDisplayWidth(),
@@ -1980,19 +2011,19 @@
const auto handle = buffer->handle;
ASSERT_NE(nullptr, handle);
- const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
- EXPECT_TRUE(layerStatus.isOk());
auto& writer = getWriter(getPrimaryDisplayId());
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(layerStatus.isOk());
writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferMultipleTimes) {
- const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
- EXPECT_TRUE(layerStatus.isOk());
auto& writer = getWriter(getPrimaryDisplayId());
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(layerStatus.isOk());
// Setup 3 buffers in the buffer cache, with the last buffer being active. Then, emulate the
// Android platform code that clears all 3 buffer slots by setting all but the active buffer
@@ -2040,14 +2071,14 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerSurfaceDamage) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2062,14 +2093,14 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerBlockingRegion) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2084,11 +2115,11 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerBlendMode) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::NONE);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2103,11 +2134,11 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerColor) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerColor(getPrimaryDisplayId(), layer, Color{1.0f, 1.0f, 1.0f, 1.0f});
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2118,11 +2149,11 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerCompositionType) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::CLIENT);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2141,8 +2172,9 @@
TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) {
for (VtsDisplay& display : mDisplays) {
+ auto& writer = getWriter(display.getDisplayId());
const auto [layerStatus, layer] =
- mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
const auto [error, support] =
@@ -2165,8 +2197,7 @@
}
configureLayer(display, layer, Composition::DISPLAY_DECORATION, display.getFrameRect(),
- display.getCrop());
- auto& writer = getWriter(display.getDisplayId());
+ display.getCrop());
writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, decorBuffer->handle,
/*acquireFence*/ -1);
writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp,
@@ -2183,31 +2214,31 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerDataspace) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerDisplayFrame) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerDisplayFrame(getPrimaryDisplayId(), layer, Rect{0, 0, 1, 1});
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerPlaneAlpha) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerPlaneAlpha(getPrimaryDisplayId(), layer, /*alpha*/ 0.0f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2227,31 +2258,31 @@
const auto handle = buffer->handle;
ASSERT_NE(nullptr, handle);
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerSidebandStream(getPrimaryDisplayId(), layer, handle);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerSourceCrop) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerSourceCrop(getPrimaryDisplayId(), layer, FRect{0.0f, 0.0f, 1.0f, 1.0f});
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerTransform) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerTransform(getPrimaryDisplayId(), layer, static_cast<Transform>(0));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2290,14 +2321,14 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerVisibleRegion) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2312,11 +2343,12 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerZOrder) {
+ auto& writer = getWriter(getPrimaryDisplayId());
+
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerZOrder(getPrimaryDisplayId(), layer, /*z*/ 10);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2327,8 +2359,9 @@
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerPerFrameMetadata) {
+ auto& writer = getWriter(getPrimaryDisplayId());
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
/**
@@ -2343,7 +2376,6 @@
* white (D65) 0.3127 0.3290
*/
- auto& writer = getWriter(getPrimaryDisplayId());
std::vector<PerFrameMetadata> aidlMetadata;
aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680f});
aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320f});
@@ -2363,18 +2395,19 @@
const auto errors = mReader.takeErrors();
if (errors.size() == 1 && errors[0].errorCode == EX_UNSUPPORTED_OPERATION) {
GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
- EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer).isOk());
+ EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, &writer).isOk());
return;
}
- EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer).isOk());
+ EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, &writer).isOk());
}
TEST_P(GraphicsComposerAidlCommandTest, setLayerBrightness) {
- const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
-
auto& writer = getWriter(getPrimaryDisplayId());
+
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+
writer.setLayerBrightness(getPrimaryDisplayId(), layer, 0.2f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2603,12 +2636,12 @@
}
TEST_P(GraphicsComposerAidlCommandV2Test, SetLayerBufferSlotsToClear) {
+ auto& writer = getWriter(getPrimaryDisplayId());
// Older HAL versions use a backwards compatible way of clearing buffer slots
// HAL at version 1 or lower does not have LayerCommand::bufferSlotsToClear
const auto& [layerStatus, layer] =
- mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
EXPECT_TRUE(layerStatus.isOk());
- auto& writer = getWriter(getPrimaryDisplayId());
// setup 3 buffers in the buffer cache, with the last buffer being active
// then emulate the Android platform code that clears all 3 buffer slots
@@ -2664,26 +2697,40 @@
return;
}
- const auto displayId = getPrimaryDisplayId();
- EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
- // Enable the callback
- ASSERT_TRUE(mComposerClient
- ->setRefreshRateChangedCallbackDebugEnabled(displayId,
- /*enabled*/ true)
- .isOk());
- std::this_thread::sleep_for(100ms);
+ for (VtsDisplay& display : mDisplays) {
+ const auto displayId = display.getDisplayId();
+ EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
+ // Enable the callback
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ true)
+ .isOk());
+ std::this_thread::sleep_for(100ms);
- const auto displayFilter = [displayId](auto refreshRateChangedDebugData) {
- return displayId == refreshRateChangedDebugData.display;
- };
+ const auto [status, configId] = mComposerClient->getActiveConfig(display.getDisplayId());
+ EXPECT_TRUE(status.isOk());
- // Check that we immediately got a callback
- EXPECT_TRUE(checkIfCallbackRefreshRateChangedDebugEnabledReceived(displayFilter));
+ const auto displayFilter = [&](auto refreshRateChangedDebugData) {
+ bool nonVrrRateMatching = true;
+ if (std::optional<VrrConfig> vrrConfigOpt =
+ display.getDisplayConfig(configId).vrrConfig;
+ getInterfaceVersion() >= 3 && !vrrConfigOpt) {
+ nonVrrRateMatching = refreshRateChangedDebugData.refreshPeriodNanos ==
+ refreshRateChangedDebugData.vsyncPeriodNanos;
+ }
+ const bool isDisplaySame =
+ display.getDisplayId() == refreshRateChangedDebugData.display;
+ return nonVrrRateMatching && isDisplaySame;
+ };
- ASSERT_TRUE(mComposerClient
- ->setRefreshRateChangedCallbackDebugEnabled(displayId,
- /*enabled*/ false)
- .isOk());
+ // Check that we immediately got a callback
+ EXPECT_TRUE(checkIfCallbackRefreshRateChangedDebugEnabledReceived(displayFilter));
+
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ false)
+ .isOk());
+ }
}
TEST_P(GraphicsComposerAidlCommandV2Test,
@@ -2853,7 +2900,8 @@
EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
- const auto& [status, layer] = mComposerClient->createLayer(displayId, kBufferSlotCount);
+ const auto& [status, layer] =
+ mComposerClient->createLayer(displayId, kBufferSlotCount, &writer);
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
ASSERT_NE(nullptr, buffer);
ASSERT_EQ(::android::OK, buffer->initCheck());
@@ -2903,7 +2951,8 @@
}
for (auto& [displayId, layer] : layers) {
- EXPECT_TRUE(mComposerClient->destroyLayer(displayId, layer).isOk());
+ auto& writer = getWriter(displayId);
+ EXPECT_TRUE(mComposerClient->destroyLayer(displayId, layer, &writer).isOk());
}
std::lock_guard guard{readersMutex};
@@ -2913,22 +2962,22 @@
}
}
-class GraphicsComposerAidlBatchedCommandTest : public GraphicsComposerAidlCommandTest {
+class GraphicsComposerAidlCommandV3Test : public GraphicsComposerAidlCommandTest {
protected:
void SetUp() override {
- GraphicsComposerAidlCommandTest::SetUp();
+ GraphicsComposerAidlTest::SetUp();
if (getInterfaceVersion() <= 2) {
GTEST_SKIP() << "Device interface version is expected to be >= 3";
}
}
- void TearDown() override {
- const auto errors = mReader.takeErrors();
- ASSERT_TRUE(mReader.takeErrors().empty());
- ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
- }
};
-TEST_P(GraphicsComposerAidlBatchedCommandTest, CreateBatchedCommand) {
+TEST_P(GraphicsComposerAidlCommandV3Test, CreateBatchedCommand) {
+ if (!hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
+ return;
+ }
+
auto& writer = getWriter(getPrimaryDisplayId());
int64_t layer = 5;
writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
@@ -2940,7 +2989,30 @@
ASSERT_TRUE(mReader.takeErrors().empty());
}
-TEST_P(GraphicsComposerAidlBatchedCommandTest, DestroyBatchedCommand) {
+TEST_P(GraphicsComposerAidlCommandV3Test, CreateBatchedCommand_BadDisplay) {
+ if (!hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
+ return;
+ }
+
+ auto& writer = getWriter(getPrimaryDisplayId());
+ int64_t layer = 5;
+ writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
+ LayerLifecycleBatchCommandType::CREATE);
+ writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
+ VtsComposerClient::kNoFrameIntervalNs);
+ execute();
+ const auto errors = mReader.takeErrors();
+ ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY);
+}
+
+TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand) {
+ if (!hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
+ return;
+ }
+
auto& writer = getWriter(getPrimaryDisplayId());
int64_t layer = 5;
writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
@@ -2958,10 +3030,42 @@
writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
execute();
+ const auto errors = mReader.takeErrors();
+ ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY);
+}
+
+TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand_BadDisplay) {
+ if (!hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
+ return;
+ }
+
+ auto& writer = getWriter(getPrimaryDisplayId());
+ int64_t layer = 5;
+ writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
+ LayerLifecycleBatchCommandType::CREATE);
+ writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
+ VtsComposerClient::kNoFrameIntervalNs);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+ writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
+ LayerLifecycleBatchCommandType::DESTROY);
+ layer++;
+ writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
+ LayerLifecycleBatchCommandType::CREATE);
+ writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
+
+ execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
-TEST_P(GraphicsComposerAidlBatchedCommandTest, NoCreateDestroyBatchedCommandIncorrectLayer) {
+TEST_P(GraphicsComposerAidlCommandV3Test, NoCreateDestroyBatchedCommandIncorrectLayer) {
+ if (!hasCapability(Capability::LAYER_LIFECYCLE_BATCH_COMMAND)) {
+ GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
+ return;
+ }
+
auto& writer = getWriter(getPrimaryDisplayId());
int64_t layer = 5;
writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
@@ -2971,11 +3075,6 @@
ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_LAYER);
}
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlBatchedCommandTest);
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, GraphicsComposerAidlBatchedCommandTest,
- testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
- ::android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlCommandTest,
@@ -3001,7 +3100,11 @@
PerInstance, GraphicsComposerAidlCommandV2Test,
testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
::android::PrintInstanceNameToString);
-
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandV3Test);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, GraphicsComposerAidlCommandV3Test,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+ ::android::PrintInstanceNameToString);
} // namespace aidl::android::hardware::graphics::composer3::vts
int main(int argc, char** argv) {
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index e288f17..4691dd6 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -48,7 +48,7 @@
},
],
- frozen: true,
+ frozen: false,
}
@@ -80,7 +80,7 @@
name: "android.hardware.health-translate-ndk",
defaults: ["android.hardware.health-translate-ndk_defaults"],
shared_libs: [
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
],
}
@@ -97,7 +97,7 @@
name: "android.hardware.health-translate-java",
srcs: ["android/hardware/health/Translate.java"],
libs: [
- "android.hardware.health-V2-java",
+ "android.hardware.health-V3-java",
"android.hardware.health-V2.0-java",
"android.hardware.health-V2.1-java",
],
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
index 2dd01b1..089c8ac 100644
--- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
@@ -37,4 +37,6 @@
long batteryManufacturingDateSeconds;
long batteryFirstUsageSeconds;
long batteryStateOfHealth;
+ @nullable String batterySerialNumber;
+ android.hardware.health.BatteryPartStatus batteryPartStatus = android.hardware.health.BatteryPartStatus.UNSUPPORTED;
}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl
new file mode 100644
index 0000000..e013e31
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@Backing(type="int") @VintfStability
+enum BatteryPartStatus {
+ UNSUPPORTED,
+ ORIGINAL,
+ REPLACED,
+}
diff --git a/health/aidl/android/hardware/health/BatteryHealthData.aidl b/health/aidl/android/hardware/health/BatteryHealthData.aidl
index 594bcce..7245298 100644
--- a/health/aidl/android/hardware/health/BatteryHealthData.aidl
+++ b/health/aidl/android/hardware/health/BatteryHealthData.aidl
@@ -16,6 +16,8 @@
package android.hardware.health;
+import android.hardware.health.BatteryPartStatus;
+
/*
* Battery health data
*/
@@ -36,4 +38,14 @@
* Otherwise, value must be in the range 0 to 100.
*/
long batteryStateOfHealth;
+ /**
+ * Serial number of the battery. Null if not supported. If supported, a string of at least 6
+ * alphanumeric characters. Characters may either be upper or lower case, but for comparison
+ * and uniqueness purposes, must be treated as case-insensitive.
+ */
+ @nullable String batterySerialNumber;
+ /**
+ * Indicator for part originality of the battery.
+ */
+ BatteryPartStatus batteryPartStatus = BatteryPartStatus.UNSUPPORTED;
}
diff --git a/health/aidl/android/hardware/health/BatteryPartStatus.aidl b/health/aidl/android/hardware/health/BatteryPartStatus.aidl
new file mode 100644
index 0000000..6c2060a
--- /dev/null
+++ b/health/aidl/android/hardware/health/BatteryPartStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.health;
+
+/**
+ * Possible values for BatteryPartStatus.
+ * Note: These are currently in sync with BatteryManager and must not
+ * be extended / altered.
+ */
+@VintfStability
+@Backing(type="int")
+enum BatteryPartStatus {
+ /**
+ * Device cannot differentiate an original battery from a replaced battery.
+ */
+ UNSUPPORTED = 0,
+ /**
+ * Device has the original battery it was manufactured with.
+ */
+ ORIGINAL = 1,
+ /**
+ * Device has a replaced battery.
+ */
+ REPLACED = 2,
+}
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index b51e4f3..2071f08 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -29,7 +29,7 @@
"libcutils",
"liblog",
"libutils",
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
// TODO(b/177269435): remove when BatteryMonitor works with AIDL HealthInfo.
"libhidlbase",
@@ -48,7 +48,7 @@
name: "libhealth_aidl_charger_defaults",
shared_libs: [
// common
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"libbase",
"libcutils",
"liblog",
@@ -195,7 +195,7 @@
"service_fuzzer_defaults",
],
static_libs: [
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"libbase",
"liblog",
"fuzz_libhealth_aidl_impl",
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index 4ad8f50..6df623a 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -62,6 +62,18 @@
Health::~Health() {}
+static inline ndk::ScopedAStatus TranslateStatus(::android::status_t err) {
+ switch (err) {
+ case ::android::OK:
+ return ndk::ScopedAStatus::ok();
+ case ::android::NAME_NOT_FOUND:
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ default:
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ IHealth::STATUS_UNKNOWN, ::android::statusToString(err).c_str());
+ }
+}
+
//
// Getters.
//
@@ -78,16 +90,7 @@
LOG(DEBUG) << "getProperty(" << id << ")"
<< " fails: (" << err << ") " << ::android::statusToString(err);
}
-
- switch (err) {
- case ::android::OK:
- return ndk::ScopedAStatus::ok();
- case ::android::NAME_NOT_FOUND:
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
- default:
- return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
- IHealth::STATUS_UNKNOWN, ::android::statusToString(err).c_str());
- }
+ return TranslateStatus(err);
}
ndk::ScopedAStatus Health::getChargeCounterUah(int32_t* out) {
@@ -153,6 +156,21 @@
!res.isOk()) {
LOG(WARNING) << "Cannot get Battery_state_of_health: " << res.getDescription();
}
+ if (auto res = battery_monitor_.getSerialNumber(&out->batterySerialNumber);
+ res != ::android::OK) {
+ LOG(WARNING) << "Cannot get Battery_serial_number: "
+ << TranslateStatus(res).getDescription();
+ }
+
+ int64_t part_status = static_cast<int64_t>(BatteryPartStatus::UNSUPPORTED);
+ if (auto res = GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_PART_STATUS,
+ static_cast<int64_t>(BatteryPartStatus::UNSUPPORTED),
+ &part_status);
+ !res.isOk()) {
+ LOG(WARNING) << "Cannot get Battery_part_status: " << res.getDescription();
+ }
+ out->batteryPartStatus = static_cast<BatteryPartStatus>(part_status);
+
return ndk::ScopedAStatus::ok();
}
diff --git a/health/aidl/default/android.hardware.health-service.example.xml b/health/aidl/default/android.hardware.health-service.example.xml
index 1fe9b8d..2acaaba 100644
--- a/health/aidl/default/android.hardware.health-service.example.xml
+++ b/health/aidl/default/android.hardware.health-service.example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.health</name>
- <version>2</version>
+ <version>3</version>
<fqname>IHealth/default</fqname>
</hal>
</manifest>
diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp
index b735a87..6d2b530 100644
--- a/health/aidl/vts/functional/Android.bp
+++ b/health/aidl/vts/functional/Android.bp
@@ -39,7 +39,7 @@
"libbinder_ndk",
],
static_libs: [
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"libgmock",
],
header_libs: [
diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
index 783ce11..9360789 100644
--- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -84,6 +84,21 @@
return AnyOfArray(enum_range<T>().begin(), enum_range<T>().end());
}
+MATCHER(IsValidSerialNumber, "") {
+ if (!arg) {
+ return true;
+ }
+ if (arg->size() < 6) {
+ return false;
+ }
+ for (const auto& c : *arg) {
+ if (!isalnum(c)) {
+ return false;
+ }
+ }
+ return true;
+}
+
class HealthAidl : public testing::TestWithParam<std::string> {
public:
void SetUp() override {
@@ -270,7 +285,7 @@
ASSERT_THAT(static_cast<int>(value), AnyOf(Eq(1), Eq(4)));
}
-MATCHER(IsValidHealthData, "") {
+MATCHER_P(IsValidHealthData, version, "") {
*result_listener << "value is " << arg.toString() << ".";
if (!ExplainMatchResult(Ge(-1), arg.batteryManufacturingDateSeconds, result_listener)) {
*result_listener << " for batteryManufacturingDateSeconds.";
@@ -284,6 +299,15 @@
*result_listener << " for batteryStateOfHealth.";
return false;
}
+ if (!ExplainMatchResult(IsValidSerialNumber(), arg.batterySerialNumber, result_listener)) {
+ *result_listener << " for batterySerialNumber.";
+ return false;
+ }
+ if (!ExplainMatchResult(IsValidEnum<BatteryPartStatus>(), arg.batteryPartStatus,
+ result_listener)) {
+ *result_listener << " for batteryPartStatus.";
+ return false;
+ }
return true;
}
@@ -303,7 +327,7 @@
status = health->getBatteryHealthData(&value);
ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
if (!status.isOk()) return;
- ASSERT_THAT(value, IsValidHealthData());
+ ASSERT_THAT(value, IsValidHealthData(version));
}
MATCHER(IsValidStorageInfo, "") {
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
index 14c32ae..b0ea743 100644
--- a/health/utils/libhealthshim/Android.bp
+++ b/health/utils/libhealthshim/Android.bp
@@ -34,7 +34,7 @@
"-Werror",
],
static_libs: [
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"android.hardware.health-translate-ndk",
"android.hardware.health@1.0",
"android.hardware.health@2.0",
diff --git a/health/utils/libhealthshim/shim.cpp b/health/utils/libhealthshim/shim.cpp
index 6a5f512..a5ba919 100644
--- a/health/utils/libhealthshim/shim.cpp
+++ b/health/utils/libhealthshim/shim.cpp
@@ -230,6 +230,7 @@
ScopedAStatus HealthShim::getBatteryHealthData(BatteryHealthData* out) {
out->batteryManufacturingDateSeconds = 0;
out->batteryFirstUsageSeconds = 0;
+ out->batteryPartStatus = BatteryPartStatus::UNSUPPORTED;
return ResultToStatus(Result::NOT_SUPPORTED);
}
diff --git a/ir/aidl/default/android.hardware.ir-service.example.rc b/ir/aidl/default/android.hardware.ir-service.example.rc
index 1a721da..d27f282 100644
--- a/ir/aidl/default/android.hardware.ir-service.example.rc
+++ b/ir/aidl/default/android.hardware.ir-service.example.rc
@@ -1,4 +1,4 @@
-service vendor.ir-default /apex/com.android.hardware.ir/bin/hw/android.hardware.ir-service.example
+service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.example
class hal
user system
group system
diff --git a/media/bufferpool/aidl/default/BufferPoolClient.cpp b/media/bufferpool/aidl/default/BufferPoolClient.cpp
index e9777d8..0e249d5 100644
--- a/media/bufferpool/aidl/default/BufferPoolClient.cpp
+++ b/media/bufferpool/aidl/default/BufferPoolClient.cpp
@@ -297,7 +297,7 @@
mLastEvictCacheMs(::android::elapsedRealtime()) {
IAccessor::ConnectionInfo conInfo;
bool valid = false;
- if(accessor->connect(observer, &conInfo).isOk()) {
+ if (accessor && accessor->connect(observer, &conInfo).isOk()) {
auto channel = std::make_unique<BufferStatusChannel>(conInfo.toFmqDesc);
auto observer = std::make_unique<BufferInvalidationListener>(conInfo.fromFmqDesc);
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
index 3c0915d..84cb382 100644
--- a/media/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -42,11 +42,8 @@
],
},
rust: {
- min_sdk_version: "31",
- enabled: true,
- additional_rustlibs: [
- "libnativewindow_rs",
- ],
+ // No users, and no rust implementation of android.os.Surface yet
+ enabled: false,
},
},
}
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 7643926..8900fb8 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -28,11 +28,20 @@
"android/hardware/power/*.aidl",
],
stability: "vintf",
+ imports: [
+ "android.hardware.common.fmq-V1",
+ "android.hardware.common-V2",
+ ],
backend: {
cpp: {
+ enabled: false,
+ },
+ ndk: {
enabled: true,
},
java: {
+ sdk_version: "module_current",
+ enabled: true,
platform_apis: true,
},
},
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelConfig.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelConfig.aidl
new file mode 100644
index 0000000..d3caca4
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelConfig.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable ChannelConfig {
+ android.hardware.common.fmq.MQDescriptor<android.hardware.power.ChannelMessage,android.hardware.common.fmq.SynchronizedReadWrite> channelDescriptor;
+ @nullable android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> eventFlagDescriptor;
+ int readFlagBitmask;
+ int writeFlagBitmask;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelMessage.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelMessage.aidl
new file mode 100644
index 0000000..25f01c0
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/ChannelMessage.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@FixedSize @VintfStability
+parcelable ChannelMessage {
+ int sessionID;
+ android.hardware.power.ChannelMessage.ChannelMessageContents data;
+ @FixedSize @VintfStability
+ union ChannelMessageContents {
+ int[20] tids = {(-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */, (-1) /* -1 */};
+ long targetDuration;
+ android.hardware.power.SessionHint hint;
+ android.hardware.power.ChannelMessage.ChannelMessageContents.SessionModeSetter mode;
+ android.hardware.power.WorkDurationFixedV1 workDuration;
+ @FixedSize @VintfStability
+ parcelable SessionModeSetter {
+ android.hardware.power.SessionMode modeInt;
+ boolean enabled;
+ }
+ }
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
index ae03313..8acdaf2 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
@@ -40,4 +40,7 @@
boolean isBoostSupported(in android.hardware.power.Boost type);
android.hardware.power.IPowerHintSession createHintSession(in int tgid, in int uid, in int[] threadIds, in long durationNanos);
long getHintSessionPreferredRate();
+ android.hardware.power.IPowerHintSession createHintSessionWithConfig(in int tgid, in int uid, in int[] threadIds, in long durationNanos, in android.hardware.power.SessionTag tag, out android.hardware.power.SessionConfig config);
+ android.hardware.power.ChannelConfig getSessionChannel(in int tgid, in int uid);
+ oneway void closeSessionChannel(in int tgid, in int uid);
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index 6bc663e..010f815 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -42,4 +42,5 @@
oneway void sendHint(android.hardware.power.SessionHint hint);
void setThreads(in int[] threadIds);
oneway void setMode(android.hardware.power.SessionMode type, boolean enabled);
+ android.hardware.power.SessionConfig getSessionConfig();
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionConfig.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionConfig.aidl
new file mode 100644
index 0000000..b03cfb2
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable SessionConfig {
+ long id;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
index 9c1f381..cb37719 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
@@ -39,4 +39,6 @@
CPU_LOAD_RESET = 2,
CPU_LOAD_RESUME = 3,
POWER_EFFICIENCY = 4,
+ GPU_LOAD_UP = 5,
+ GPU_LOAD_DOWN = 6,
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl
new file mode 100644
index 0000000..80848a4
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum SessionTag {
+ OTHER,
+ SURFACEFLINGER,
+ HWUI,
+ GAME,
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDurationFixedV1.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDurationFixedV1.aidl
new file mode 100644
index 0000000..8cd246d
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDurationFixedV1.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@FixedSize @VintfStability
+parcelable WorkDurationFixedV1 {
+ long timeStampNanos;
+ long durationNanos;
+ long workPeriodStartTimestampNanos;
+ long cpuDurationNanos;
+ long gpuDurationNanos;
+}
diff --git a/power/aidl/android/hardware/power/ChannelConfig.aidl b/power/aidl/android/hardware/power/ChannelConfig.aidl
new file mode 100644
index 0000000..4da292e
--- /dev/null
+++ b/power/aidl/android/hardware/power/ChannelConfig.aidl
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright (C) 2023 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.power;
+
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.power.ChannelMessage;
+
+@VintfStability
+parcelable ChannelConfig {
+ /**
+ * The message queue descriptor that provides the information necessary for
+ * a client to write to this channel.
+ */
+ MQDescriptor<ChannelMessage, SynchronizedReadWrite> channelDescriptor;
+
+ /**
+ * A message queue descriptor used to pass an optional event flag to clients,
+ * used to synchronize multiple message queues using the same flag. If not
+ * defined, the flag from the channelDescriptor should be used.
+ */
+ @nullable MQDescriptor<byte, SynchronizedReadWrite> eventFlagDescriptor;
+
+ /**
+ * The read flag bitmask to be used with the event flag, specifying the
+ * bits used by this channel to mark that the buffer has been read from.
+ * If set to 0, the default bitmask will be used.
+ */
+ int readFlagBitmask;
+
+ /**
+ * The write flag bitmask to be used with the event flag, specifying the
+ * bits used by this channel to mark that the buffer has been written to.
+ * If set to 0, the default bitmask will be used.
+ */
+ int writeFlagBitmask;
+}
diff --git a/power/aidl/android/hardware/power/ChannelMessage.aidl b/power/aidl/android/hardware/power/ChannelMessage.aidl
new file mode 100644
index 0000000..4747d90
--- /dev/null
+++ b/power/aidl/android/hardware/power/ChannelMessage.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 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.power;
+
+import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
+import android.hardware.power.WorkDurationFixedV1;
+
+/**
+ * Data sent through the FMQ must follow this structure. It's important to note
+ * that such data may come from the app itself, so the HAL must validate all
+ * data received through this interface, and reject any calls not guaranteed to be
+ * valid. Each of the types defined in the inner union maps to an equivalent call
+ * on IPowerHintSession, and is merely being used to expedite the use of that API
+ * in cases where it is safe to bypass the HintManagerService.
+ */
+@FixedSize
+@VintfStability
+parcelable ChannelMessage {
+ /**
+ * The ID of the specific session sending the hint, used to enable a single
+ * channel to be multiplexed across all sessions in a single process.
+ */
+ int sessionID;
+
+ /**
+ * A union defining the different messages that can be passed through the
+ * channel. Each type corresponds to a different call in IPowerHintSession.
+ */
+ ChannelMessageContents data;
+
+ @FixedSize
+ @VintfStability
+ union ChannelMessageContents {
+ /**
+ * List of TIDs for this session to change to. Can be used in cases
+ * where HintManagerService is not needed to validate the TIDs, such as
+ * when all TIDs directly belong to the process that owns the session.
+ */
+ int[20] tids = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+ /**
+ * Setting this field will update the session’s target duration, equivalent
+ * to calling updateTargetWorkDuration(targetDuration).
+ */
+ long targetDuration;
+
+ /**
+ * Setting this field will send a hint to the session, equivalent to
+ * calling sendHint(hint).
+ */
+ SessionHint hint;
+
+ /**
+ * Setting this field will send a hint to the session, equivalent to
+ * calling setMode(mode.modeInt, mode.enabled).
+ */
+ SessionModeSetter mode;
+
+ /**
+ * Setting this field will update the session’s actual duration, equivalent
+ * to calling reportActualWorkDuration([workDuration]). Only one duration
+ * can be passed at a time; this API expects durations to be reported
+ * immediately each frame, since the overhead of this call is much lower.
+ */
+ WorkDurationFixedV1 workDuration;
+
+ /**
+ * This structure is used to fit both the mode and the state within one
+ * entry in the union.
+ */
+ @FixedSize
+ @VintfStability
+ parcelable SessionModeSetter {
+ SessionMode modeInt;
+ boolean enabled;
+ }
+ }
+}
diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl
index ee8e5a3..e25714f 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -17,8 +17,11 @@
package android.hardware.power;
import android.hardware.power.Boost;
+import android.hardware.power.ChannelConfig;
import android.hardware.power.IPowerHintSession;
import android.hardware.power.Mode;
+import android.hardware.power.SessionConfig;
+import android.hardware.power.SessionTag;
@VintfStability
interface IPower {
@@ -103,4 +106,42 @@
* EX_UNSUPPORTED_OPERATION if hint session is not supported.
*/
long getHintSessionPreferredRate();
+
+ /**
+ * A version of createHintSession that returns an additional bundle of session
+ * data, useful to help the session immediately communicate via an FMQ channel
+ * for more efficient updates.
+ *
+ * @return the new session if it is supported on this device, otherwise return
+ * with EX_UNSUPPORTED_OPERATION error if hint session is not
+ * supported on this device.
+ * @param tgid The TGID to be associated with this session.
+ * @param uid The UID to be associated with this session.
+ * @param threadIds The list of threads to be associated with this session.
+ * @param durationNanos The desired duration in nanoseconds for this session.
+ * @param config Extra session metadata to be returned to the caller.
+ */
+ IPowerHintSession createHintSessionWithConfig(in int tgid, in int uid, in int[] threadIds,
+ in long durationNanos, in SessionTag tag, out SessionConfig config);
+
+ /**
+ * Used to get an FMQ channel, per-process. The channel should be unique to
+ * that process, and should return the same ChannelConfig if called multiple
+ * times from that same process.
+ *
+ * @return the channel config if hint sessions are supported on this device,
+ * otherwise return with EX_UNSUPPORTED_OPERATION.
+ * @param tgid The TGID to be associated with this channel.
+ * @param uid The UID to be associated with this channel.
+ */
+ ChannelConfig getSessionChannel(in int tgid, in int uid);
+
+ /**
+ * Used to close a channel once it is no longer needed by a process, or that
+ * process dies.
+ *
+ * @param tgid The TGID to be associated with this channel.
+ * @param uid The UID to be associated with this channel.
+ */
+ oneway void closeSessionChannel(in int tgid, in int uid);
}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 62263c8..9dd251f 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -16,6 +16,7 @@
package android.hardware.power;
+import android.hardware.power.SessionConfig;
import android.hardware.power.SessionHint;
import android.hardware.power.SessionMode;
import android.hardware.power.WorkDuration;
@@ -91,4 +92,11 @@
* @param enabled True to enable the mode, false to disable it
*/
oneway void setMode(SessionMode type, boolean enabled);
+
+ /**
+ * This method provides direct access to a session's config data.
+ *
+ * @return the config data for this session
+ */
+ SessionConfig getSessionConfig();
}
diff --git a/power/aidl/android/hardware/power/SessionConfig.aidl b/power/aidl/android/hardware/power/SessionConfig.aidl
new file mode 100644
index 0000000..93dc9a2
--- /dev/null
+++ b/power/aidl/android/hardware/power/SessionConfig.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.power;
+
+/**
+ * Additional session to be passed to the hint session during creation, or acquired
+ * after creation from the session directly.
+ */
+@VintfStability
+parcelable SessionConfig {
+ /**
+ * The session's unique ID, used to identify the session for debugging and
+ * for multiplexing on the per-process FMQ channel.
+ */
+ long id;
+}
diff --git a/power/aidl/android/hardware/power/SessionHint.aidl b/power/aidl/android/hardware/power/SessionHint.aidl
index a172e12..ae91061 100644
--- a/power/aidl/android/hardware/power/SessionHint.aidl
+++ b/power/aidl/android/hardware/power/SessionHint.aidl
@@ -52,4 +52,17 @@
* power hint session is noncritical despite its CPU intensity.
*/
POWER_EFFICIENCY = 4,
+
+ /**
+ * This hint indicates an increase in GPU workload intensity. It means that
+ * this hint session needs extra GPU resources to meet the target duration.
+ * This hint must be sent before reporting the actual duration to the session.
+ */
+ GPU_LOAD_UP = 5,
+
+ /**
+ * This hint indicates a decrease in GPU workload intensity. It means that
+ * this hint session can reduce GPU resources and still meet the target duration.
+ */
+ GPU_LOAD_DOWN = 6,
}
diff --git a/power/aidl/android/hardware/power/SessionTag.aidl b/power/aidl/android/hardware/power/SessionTag.aidl
new file mode 100644
index 0000000..c1d48e4
--- /dev/null
+++ b/power/aidl/android/hardware/power/SessionTag.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.power;
+
+@VintfStability
+@Backing(type="int")
+enum SessionTag {
+ /**
+ * This tag is used to mark uncategorized hint sessions.
+ */
+ OTHER,
+
+ /**
+ * This tag is used to mark the SurfaceFlinger hint session.
+ */
+ SURFACEFLINGER,
+
+ /**
+ * This tag is used to mark HWUI hint sessions.
+ */
+ HWUI,
+
+ /**
+ * This tag is used to mark Game hint sessions.
+ */
+ GAME,
+}
diff --git a/power/aidl/android/hardware/power/WorkDurationFixedV1.aidl b/power/aidl/android/hardware/power/WorkDurationFixedV1.aidl
new file mode 100644
index 0000000..2d202ff
--- /dev/null
+++ b/power/aidl/android/hardware/power/WorkDurationFixedV1.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.power;
+
+@FixedSize
+@VintfStability
+parcelable WorkDurationFixedV1 {
+ /**
+ * Timestamp in nanoseconds based on CLOCK_MONOTONIC when the duration
+ * sample was measured.
+ */
+ long timeStampNanos;
+
+ /**
+ * Total work duration in nanoseconds.
+ */
+ long durationNanos;
+
+ /**
+ * Timestamp in nanoseconds based on CLOCK_MONOTONIC when the work starts.
+ * The work period start timestamp could be zero if the call is from
+ * the legacy SDK/NDK reportActualWorkDuration API.
+ */
+ long workPeriodStartTimestampNanos;
+
+ /**
+ * CPU work duration in nanoseconds.
+ * The CPU work duration could be the same as the total work duration if
+ * the call is from the legacy SDK/NDK reportActualWorkDuration API.
+ */
+ long cpuDurationNanos;
+
+ /**
+ * GPU work duration in nanoseconds.
+ * The GPU work duration could be zero if the call is from the legacy
+ * SDK/NDK reportActualWorkDuration API.
+ */
+ long gpuDurationNanos;
+}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index e3af179..b4ccc7d 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -29,8 +29,12 @@
vintf_fragments: [":android.hardware.power.xml"],
vendor: true,
shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"libbase",
"libbinder_ndk",
+ "libcutils",
+ "libfmq",
],
srcs: [
"main.cpp",
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 8fe370c..8f15663 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -18,6 +18,8 @@
#include "PowerHintSession.h"
#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
namespace aidl {
namespace android {
@@ -27,6 +29,10 @@
namespace example {
using namespace std::chrono_literals;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::power::ChannelMessage;
+using ::android::AidlMessageQueue;
using ndk::ScopedAStatus;
@@ -70,6 +76,27 @@
return ScopedAStatus::ok();
}
+ndk::ScopedAStatus Power::createHintSessionWithConfig(
+ int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos,
+ SessionTag, SessionConfig* config, std::shared_ptr<IPowerHintSession>* _aidl_return) {
+ auto out = createHintSession(tgid, uid, threadIds, durationNanos, _aidl_return);
+ static_cast<PowerHintSession*>(_aidl_return->get())->getSessionConfig(config);
+ return out;
+}
+
+ndk::ScopedAStatus Power::getSessionChannel(int32_t, int32_t, ChannelConfig* _aidl_return) {
+ static AidlMessageQueue<ChannelMessage, SynchronizedReadWrite> stubQueue{1, true};
+ _aidl_return->channelDescriptor = stubQueue.dupeDesc();
+ _aidl_return->readFlagBitmask = 0;
+ _aidl_return->writeFlagBitmask = 0;
+ _aidl_return->eventFlagDescriptor = std::nullopt;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Power::closeSessionChannel(int32_t, int32_t) {
+ return ndk::ScopedAStatus::ok();
+}
+
ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
*outNanoseconds = std::chrono::nanoseconds(1ms).count();
return ScopedAStatus::ok();
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index 7f8405e..baabaa7 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -17,6 +17,7 @@
#pragma once
#include <aidl/android/hardware/power/BnPower.h>
+#include "aidl/android/hardware/power/SessionTag.h"
namespace aidl {
namespace android {
@@ -35,7 +36,14 @@
const std::vector<int32_t>& threadIds,
int64_t durationNanos,
std::shared_ptr<IPowerHintSession>* _aidl_return) override;
+ ndk::ScopedAStatus createHintSessionWithConfig(
+ int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos,
+ SessionTag tag, SessionConfig* config,
+ std::shared_ptr<IPowerHintSession>* _aidl_return) override;
ndk::ScopedAStatus getHintSessionPreferredRate(int64_t* outNanoseconds) override;
+ ndk::ScopedAStatus getSessionChannel(int32_t tgid, int32_t uid,
+ ChannelConfig* _aidl_return) override;
+ ndk::ScopedAStatus closeSessionChannel(int32_t tgid, int32_t uid) override;
private:
std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
index 452e435..847a42e 100644
--- a/power/aidl/default/PowerHintSession.cpp
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -17,6 +17,7 @@
#include "PowerHintSession.h"
#include <android-base/logging.h>
+#include "android/binder_auto_utils.h"
namespace aidl::android::hardware::power::impl::example {
@@ -63,4 +64,9 @@
return ScopedAStatus::ok();
}
+ScopedAStatus PowerHintSession::getSessionConfig(SessionConfig* _aidl_return) {
+ _aidl_return->id = 1;
+ return ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
index b488bf1..2ed5588 100644
--- a/power/aidl/default/PowerHintSession.h
+++ b/power/aidl/default/PowerHintSession.h
@@ -35,6 +35,7 @@
ndk::ScopedAStatus sendHint(SessionHint hint) override;
ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
+ ndk::ScopedAStatus getSessionConfig(SessionConfig* _aidl_return) override;
};
} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index eb98b8b..c9285f4 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -31,6 +31,11 @@
srcs: ["VtsHalPowerTargetTest.cpp"],
shared_libs: [
"libbinder_ndk",
+ "libfmq",
+ ],
+ static_libs: [
+ "android.hardware.common.fmq-V1-ndk",
+ "android.hardware.common-V2-ndk",
],
test_suites: [
"general-tests",
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 96995a0..11d44b8 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -24,12 +24,22 @@
#include <android/binder_process.h>
#include <android/binder_status.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+
#include <unistd.h>
+#include <cstdint>
+#include "aidl/android/hardware/common/fmq/SynchronizedReadWrite.h"
+#include "fmq/EventFlag.h"
namespace aidl::android::hardware::power {
namespace {
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
using android::hardware::power::Boost;
+using android::hardware::power::ChannelConfig;
+using android::hardware::power::ChannelMessage;
using android::hardware::power::IPower;
using android::hardware::power::IPowerHintSession;
using android::hardware::power::Mode;
@@ -37,6 +47,8 @@
using android::hardware::power::SessionMode;
using android::hardware::power::WorkDuration;
+using SessionMessageQueue = AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>;
+
const std::vector<Boost> kBoosts{ndk::enum_range<Boost>().begin(), ndk::enum_range<Boost>().end()};
const std::vector<Mode> kModes{ndk::enum_range<Mode>().begin(), ndk::enum_range<Mode>().end()};
@@ -190,6 +202,31 @@
ASSERT_GE(rate, 1000000);
}
+TEST_P(PowerAidl, createHintSessionWithConfig) {
+ if (mServiceVersion < 5) {
+ GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+ }
+ std::shared_ptr<IPowerHintSession> session;
+ SessionConfig config;
+
+ auto status = power->createHintSessionWithConfig(getpid(), getuid(), kSelfTids, 16666666L,
+ SessionTag::OTHER, &config, &session);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_NE(nullptr, session);
+}
+
+TEST_P(PowerAidl, getAndCloseSessionChannel) {
+ if (mServiceVersion < 5) {
+ GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+ }
+ ChannelConfig config;
+ auto status = power->getSessionChannel(getpid(), getuid(), &config);
+ ASSERT_TRUE(status.isOk());
+ auto messageQueue = std::make_shared<SessionMessageQueue>(config.channelDescriptor, true);
+ ASSERT_TRUE(messageQueue->isValid());
+ ASSERT_TRUE(power->closeSessionChannel(getpid(), getuid()).isOk());
+}
+
TEST_P(HintSessionAidl, createAndCloseHintSession) {
ASSERT_TRUE(mSession->pause().isOk());
ASSERT_TRUE(mSession->resume().isOk());
@@ -252,6 +289,14 @@
}
}
+TEST_P(HintSessionAidl, getSessionConfig) {
+ if (mServiceVersion < 5) {
+ GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+ }
+ SessionConfig config;
+ ASSERT_TRUE(mSession->getSessionConfig(&config).isOk());
+}
+
// FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
// or later
TEST_P(PowerAidl, hasFixedPerformance) {
diff --git a/radio/OWNERS b/radio/OWNERS
index 67ac2e2..8107287 100644
--- a/radio/OWNERS
+++ b/radio/OWNERS
@@ -2,3 +2,4 @@
jackyu@google.com
sarahchin@google.com
+jayachandranc@google.com
\ No newline at end of file
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
index 0f5e7e4..bc1c292 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
@@ -51,4 +51,5 @@
oneway void setPreferredDataModem(in int serial, in byte modemId);
oneway void setResponseFunctions(in android.hardware.radio.config.IRadioConfigResponse radioConfigResponse, in android.hardware.radio.config.IRadioConfigIndication radioConfigIndication);
oneway void setSimSlotsMapping(in int serial, in android.hardware.radio.config.SlotPortMapping[] slotMap);
+ oneway void getSimultaneousCallingSupport(in int serial);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
index 9189f90..f786373 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -36,4 +36,5 @@
@VintfStability
interface IRadioConfigIndication {
oneway void simSlotsStatusChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.config.SimSlotStatus[] slotStatus);
+ oneway void onSimultaneousCallingSupportChanged(in int[] enabledLogicalSlots);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
index 348aa34..6ff7bd0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -42,4 +42,5 @@
oneway void setNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setPreferredDataModemResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setSimSlotsMappingResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void getSimultaneousCallingSupportResponse(in android.hardware.radio.RadioResponseInfo info, in int[] enabledLogicalSlots);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
index 3648866..2c66abd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
@@ -39,4 +39,6 @@
byte maxActiveInternetData;
boolean isInternetLingeringSupported;
byte[] logicalModemIds;
+ byte maxActiveVoice = UNKNOWN /* -1 */;
+ const byte UNKNOWN = (-1) /* -1 */;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
index 6dbf09d..9846006 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
@@ -39,5 +39,5 @@
TRIGGER_PLMN_BLOCK,
TRIGGER_PLMN_BLOCK_WITH_TIMEOUT,
TRIGGER_RAT_BLOCK,
- TRIGGER_CLEAR_RAT_BLOCK,
+ TRIGGER_CLEAR_RAT_BLOCKS,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithm.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithm.aidl
index 1664501..3eb51e7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithm.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithm.aidl
@@ -64,9 +64,9 @@
DES_EDE3_CBC = 72,
AES_EDE3_CBC = 73,
HMAC_SHA1_96 = 74,
- HMAC_SHA1_96_null = 75,
+ HMAC_SHA1_96_NULL = 75,
HMAC_MD5_96 = 76,
- HMAC_MD5_96_null = 77,
+ HMAC_MD5_96_NULL = 77,
SRTP_AES_COUNTER = 87,
SRTP_AES_F8 = 88,
SRTP_HMAC_SHA1 = 89,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierInfo.aidl
new file mode 100644
index 0000000..5838959
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
+parcelable CarrierInfo {
+ String mcc;
+ String mnc;
+ @nullable String spn;
+ @nullable String gid1;
+ @nullable String gid2;
+ @nullable String imsiPrefix;
+ @nullable List<android.hardware.radio.sim.Plmn> ephlmn;
+ @nullable String iccid;
+ @nullable String impi;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
index 84cdf5d..a5b8dc9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -35,10 +35,18 @@
/* @hide */
@JavaDerive(toString=true) @VintfStability
parcelable CarrierRestrictions {
+ /**
+ * @deprecated use @List<CarrierInfo> allowedCarrierInfoList
+ */
android.hardware.radio.sim.Carrier[] allowedCarriers;
+ /**
+ * @deprecated use @List<CarrierInfo> excludedCarrierInfoList
+ */
android.hardware.radio.sim.Carrier[] excludedCarriers;
boolean allowedCarriersPrioritized;
android.hardware.radio.sim.CarrierRestrictions.CarrierRestrictionStatus status;
+ android.hardware.radio.sim.CarrierInfo[] allowedCarrierInfoList = {};
+ android.hardware.radio.sim.CarrierInfo[] excludedCarrierInfoList = {};
@Backing(type="int") @VintfStability
enum CarrierRestrictionStatus {
UNKNOWN = 0,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Plmn.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Plmn.aidl
new file mode 100644
index 0000000..b29a4a7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Plmn.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
+parcelable Plmn {
+ String mcc;
+ String mnc;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index 5a5e8ac..8cfe417 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -37,4 +37,11 @@
enum SimLockMultiSimPolicy {
NO_MULTISIM_POLICY,
ONE_VALID_SIM_MUST_BE_PRESENT,
+ APPLY_TO_ALL_SLOTS,
+ APPLY_TO_ONLY_SLOT_1,
+ VALID_SIM_MUST_PRESENT_ON_SLOT_1,
+ ACTIVE_SERVICE_ON_SLOT_1_TO_UNBLOCK_OTHER_SLOTS,
+ ACTIVE_SERVICE_ON_ANY_SLOT_TO_UNBLOCK_OTHER_SLOTS,
+ ALL_SIMS_MUST_BE_VALID,
+ SLOT_POLICY_OTHER,
}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
index 9058d9d..8f4dff4 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
@@ -191,4 +191,20 @@
* This is available when android.hardware.telephony.subscription is defined.
*/
void setSimSlotsMapping(in int serial, in SlotPortMapping[] slotMap);
+
+ /**
+ * Get the set of logical slots where simultaneous cellular calling is currently possible. This
+ * does not include simultaneous calling availability over other non-cellular transports, such
+ * as IWLAN.
+ *
+ * Get the set of slots that currently support simultaneous cellular calling. When a new
+ * cellular call is placed/received, if another slot is active and handing a call, both the
+ * active slot and proposed slot must be in this list in order to support simultaneous cellular
+ * calling for both of those slots.
+ *
+ * @param serial Serial number of request
+ *
+ * This is available when android.hardware.telephony is defined.
+ */
+ void getSimultaneousCallingSupport(in int serial);
}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
index ed2366b..9eacb8e 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -37,4 +37,15 @@
*/
void simSlotsStatusChanged(
in android.hardware.radio.RadioIndicationType type, in SimSlotStatus[] slotStatus);
+
+ /**
+ * The logical slots supporting simultaneous cellular calling has changed.
+ *
+ * @param enabledLogicalSlots The slots that have simultaneous cellular calling enabled. If
+ * there is a call active on logical slot X, then a simultaneous cellular call is only possible
+ * on logical slot Y if BOTH slot X and slot Y are in enabledLogicalSlots. If simultaneous
+ * cellular calling is not currently supported, the expected value of enabledLogicalSLots is an
+ * empty int array. Sending only one radio slot is not acceptable in any case.
+ */
+ void onSimultaneousCallingSupportChanged(in int[] enabledLogicalSlots);
}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
index df93e3c..33b0ff0 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -129,4 +129,27 @@
* RadioError:INVALID_ARGUMENTS
*/
void setSimSlotsMappingResponse(in android.hardware.radio.RadioResponseInfo info);
+
+ /**
+ * Response to the asynchronous
+ * {@link IRadioConfig#getSimultaneousCallingSupport} request.
+ *
+ * @param info Response info struct containing response type, serial no. and error
+ * @param enabledLogicalSlots The slots that have simultaneous cellular calling enabled. If
+ * there is a call active on logical slot X, then a simultaneous cellular call is only possible
+ * on logical slot Y if BOTH slot X and slot Y are in enabledLogicalSlots. If simultaneous
+ * cellular calling is not currently supported, the expected value of enabledLogicalSLots is an
+ * empty int array. Sending only one radio slot is not acceptable in any case.
+ *
+ * Valid errors returned:
+ * RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony is not defined
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:MODEM_ERR
+ *
+ * @see IRadioConfig#getSimultaneousCallingSupport for more information.
+ */
+ void getSimultaneousCallingSupportResponse(
+ in android.hardware.radio.RadioResponseInfo info, in int[] enabledLogicalSlots);
}
diff --git a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
index 35d6b5d..7936eb6 100644
--- a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
+++ b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
@@ -25,6 +25,7 @@
@VintfStability
@JavaDerive(toString=true)
parcelable PhoneCapability {
+ const byte UNKNOWN = -1;
/**
* maxActiveData defines how many logical modems can have
* PS attached simultaneously. For example, for L+L modem it
@@ -47,4 +48,10 @@
* List of logical modem IDs.
*/
byte[] logicalModemIds;
+ /**
+ * maxActiveVoice defines how many logical modems can have
+ * cellular voice calls simultaneously. For example, for cellular DSDA
+ * with simultaneous calling support, it should be 2.
+ */
+ byte maxActiveVoice = UNKNOWN;
}
diff --git a/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
index f0e28fc..73c57fa 100644
--- a/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
+++ b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
@@ -37,9 +37,10 @@
TRIGGER_PLMN_BLOCK_WITH_TIMEOUT,
/**
* Indicates that the IMS registration on current RAT failed multiple times.
- * The radio shall block the current RAT and search for other available RATs in the
- * background. If no other RAT is available that meets the carrier requirements, the
- * radio may remain on the current RAT for internet service. The radio clears all
+ * The radio shall block the {@link AccessNetwork} included with this and
+ * search for other available RATs in the background.
+ * If no other RAT is available that meets the carrier requirements, the
+ * radio may remain on the blocked RAT for internet service. The radio clears all
* RATs marked as unavailable if {@link IRadioIms#updateImsRegistrationInfo()} API
* with REGISTERED state is invoked.
*/
@@ -48,5 +49,5 @@
* Indicates that the radio clears all RATs marked as unavailable and tries to find
* an available RAT that meets the carrier requirements.
*/
- TRIGGER_CLEAR_RAT_BLOCK,
+ TRIGGER_CLEAR_RAT_BLOCKS,
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index e2df8dd..5f26195 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -649,8 +649,8 @@
/**
* Get whether pre-auth cellular identifier in-the-clear transparency is enabled. If
* IRadioNetworkInterface.setCellularIdentifierTransparencyEnabled has been called, this should
- * return the value of the `enabled` parameter of the last successful call. If it hasn't been
- * called this should return the default value of true.
+ * return the value of the `enabled` parameter of the last successful call and false if
+ * IRadioNetworkInterface.setCellularIdentifierTransparencyEnabled has not been called yet.
*
* @param serial Serial number of request
*
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index 9c2502d..875a1b2 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -233,14 +233,22 @@
* Indicates that a new ciphering or integrity algorithm was used for a particular voice,
* signaling, or data connection attempt for a given PLMN and/or access network. Due to
* power concerns, once a connection type has been reported on, follow-up reports about that
- * connection type are only generated if there is any change to the previously reported
- * encryption or integrity. Thus the AP is only to be notified when there is new information.
- * List is reset upon rebooting thus info about initial connections is always passed to the
- * AP after a reboot. List is also reset if the SIM is changed or if there has been a change
- * in the access network.
+ * connection type are only generated if there is any change to the most-recently reported
+ * encryption or integrity, or if the value of SecurityAlgorithmUpdate#isUnprotectedEmergency
+ * changes. Thus the AP is only to be notified when there is new information. A change only in
+ * cell ID should not trigger an update, as the design is intended to be agnostic to dual
+ * connectivity ("secondary serving cells").
*
- * Note: a change only in cell ID should not trigger an update, as the design is intended to
- * be agnostic to dual connectivity ("secondary serving cells").
+ * Sample scenario to further clarify "most-recently reported":
+ *
+ * 1. Modem reports user is connected to a null-ciphered 3G network.
+ * 2. User then moves and connects to a well-ciphered 5G network, and modem reports this.
+ * 3. User returns to original location and reconnects to the null-ciphered 3G network. Modem
+ * should report this as it's different than the most-recently reported data from step (2).
+ *
+ * List is reset upon rebooting thus info about initial connections is always passed to the AP
+ * after a reboot. List is also reset if the SIM is changed or if there has been a change in
+ * the access network.
*
* @param type Type of radio indication
* @param securityAlgorithmUpdate SecurityAlgorithmUpdate encapsulates details of security
diff --git a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
index 71c654c..fefa26e 100644
--- a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
+++ b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
@@ -67,9 +67,9 @@
DES_EDE3_CBC = 72,
AES_EDE3_CBC = 73,
HMAC_SHA1_96 = 74,
- HMAC_SHA1_96_null = 75,
+ HMAC_SHA1_96_NULL = 75,
HMAC_MD5_96 = 76,
- HMAC_MD5_96_null = 77,
+ HMAC_MD5_96_NULL = 77,
// RTP (see 3GPP TS 33.328)
SRTP_AES_COUNTER = 87,
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl b/radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
new file mode 100644
index 0000000..a890497
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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.sim;
+
+import android.hardware.radio.sim.Plmn;
+
+/** @hide */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CarrierInfo {
+ /**
+ * MCC (Mobile Country Code) of Carrier. Wild char is either '*' or '?'.
+ */
+ String mcc;
+
+ /**
+ * MNC (Mobile Network Code) of the Carrier. Wild char is either '*' or '?'.
+ */
+ String mnc;
+ /**
+ * Service Provider Name(SPN) of the SIM card of the Carrier.
+ */
+ @nullable
+ String spn;
+ /**
+ * GID1 value of the SIM card of the Carrier.
+ */
+ @nullable
+ String gid1;
+ /**
+ * GID2 value of the SIM card of the Carrier.
+ */
+ @nullable
+ String gid2;
+
+ /**
+ * IMSI (International Mobile Subscriber Identity) prefix. Wild char is '*'.
+ */
+ @nullable
+ String imsiPrefix;
+ /**
+ * Equivalent HPLMN of the SIM card of the Carrier.
+ */
+ @nullable
+ List<Plmn> ephlmn;
+ /**
+ * ICCID (Integrated Circuit Card Identification) of the SIM card.
+ */
+ @nullable
+ String iccid;
+ /**
+ * IMPI (IMS Private Identity) of the SIM card of the Carrier.
+ */
+ @nullable
+ String impi;
+}
\ No newline at end of file
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
index d5e0c43..0002d5a 100644
--- a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -17,6 +17,7 @@
package android.hardware.radio.sim;
import android.hardware.radio.sim.Carrier;
+import android.hardware.radio.sim.CarrierInfo;
/** @hide */
@VintfStability
@@ -40,12 +41,14 @@
}
/**
* Allowed carriers
+ * @deprecated use @List<CarrierInfo> allowedCarrierInfoList
*/
Carrier[] allowedCarriers;
/**
* Explicitly excluded carriers which match allowed_carriers. Eg. allowedCarriers match mcc/mnc,
* excludedCarriers has same mcc/mnc and gid1 is ABCD. It means except the carrier whose gid1
* is ABCD, all carriers with the same mcc/mnc are allowed.
+ * @deprecated use @List<CarrierInfo> excludedCarrierInfoList
*/
Carrier[] excludedCarriers;
/**
@@ -59,4 +62,14 @@
boolean allowedCarriersPrioritized;
/** Current restriction status as defined in CarrierRestrictionStatus enum */
CarrierRestrictionStatus status;
-}
+
+ /** Allowed carriers. */
+ CarrierInfo[] allowedCarrierInfoList = {};
+
+ /**
+ * Explicitly excluded carriers which match allowed_carriers. Eg. allowedCarriers match mcc/mnc,
+ * excludedCarriers has same mcc/mnc and gid1 is ABCD. It means except the carrier whose gid1
+ * is ABCD, all carriers with the same mcc/mnc are allowed.
+ */
+ CarrierInfo[] excludedCarrierInfoList = {};
+}
\ No newline at end of file
diff --git a/radio/aidl/android/hardware/radio/sim/Plmn.aidl b/radio/aidl/android/hardware/radio/sim/Plmn.aidl
new file mode 100644
index 0000000..fd82692
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/Plmn.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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.sim;
+
+/** @hide */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable Plmn {
+ /**
+ * MCC (Mobile Country Code) of the PLMN
+ */
+ String mcc;
+ /**
+ * MNC (Mobile Network Code) of the PLMN
+ */
+ String mnc;
+}
\ No newline at end of file
diff --git a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index 18f97f7..89d85a9 100644
--- a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -21,14 +21,56 @@
@Backing(type="int")
@JavaDerive(toString=true)
enum SimLockMultiSimPolicy {
+
/**
* Indicates that configuration applies to each slot independently.
*/
NO_MULTISIM_POLICY,
+
/**
* Indicates that any SIM card can be used as far as one valid card is present in the device.
* For the modem, a SIM card is valid when its content (i.e. MCC, MNC, GID, SPN) matches the
* carrier restriction configuration.
*/
ONE_VALID_SIM_MUST_BE_PRESENT,
+
+ /**
+ * Indicates that the SIM lock policy applies uniformly to all sim slots.
+ */
+ APPLY_TO_ALL_SLOTS,
+
+ /**
+ * The SIM lock configuration applies exclusively to sim slot 1, leaving
+ * all other sim slots unlocked irrespective of the SIM card in slot 1
+ */
+ APPLY_TO_ONLY_SLOT_1,
+
+ /**
+ * Valid sim cards must be present on sim slot1 in order
+ * to use other sim slots.
+ */
+ VALID_SIM_MUST_PRESENT_ON_SLOT_1,
+
+ /**
+ * Valid sim card must be present on slot1 and it must be in full service
+ * in order to use other sim slots.
+ */
+ ACTIVE_SERVICE_ON_SLOT_1_TO_UNBLOCK_OTHER_SLOTS,
+
+ /**
+ * Valid sim card be present on any slot and it must be in full service
+ * in order to use other sim slots.
+ */
+ ACTIVE_SERVICE_ON_ANY_SLOT_TO_UNBLOCK_OTHER_SLOTS,
+
+ /**
+ * Valid sim cards must be present on all slots. If any SIM cards become
+ * invalid then device would set other SIM cards as invalid as well.
+ */
+ ALL_SIMS_MUST_BE_VALID,
+
+ /**
+ * In case there is no match policy listed above.
+ */
+ SLOT_POLICY_OTHER
}
diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
index c2eaed1..96aaebc 100644
--- a/radio/aidl/compat/libradiocompat/CallbackManager.cpp
+++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
@@ -53,6 +53,10 @@
return *mRadioResponse;
}
+RadioIndication& CallbackManager::indication() const {
+ return *mRadioIndication;
+}
+
void CallbackManager::setResponseFunctionsDelayed() {
std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay;
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
index b450418..837c626 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -62,6 +62,13 @@
return ok();
}
+ScopedAStatus RadioConfig::getSimultaneousCallingSupport(int32_t serial) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " getSimultaneousCallingSupport is unsupported by HIDL HALs";
+ respond()->getSimultaneousCallingSupportResponse(notSupported(serial), {});
+ return ok();
+}
+
ScopedAStatus RadioConfig::getSimSlotsStatus(int32_t serial) {
LOG_CALL << serial;
mHal1_1->getSimSlotsStatus(serial);
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
index f1a7b49..34ab5d7 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
@@ -46,6 +46,7 @@
~CallbackManager();
RadioResponse& response() const;
+ RadioIndication& indication() const;
template <typename ResponseType, typename IndicationType>
void setResponseFunctions(const std::shared_ptr<ResponseType>& response,
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
index 89ddea0..17d5985 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -42,6 +42,7 @@
::ndk::ScopedAStatus getHalDeviceCapabilities(int32_t serial) override;
::ndk::ScopedAStatus getNumOfLiveModems(int32_t serial) override;
::ndk::ScopedAStatus getPhoneCapability(int32_t serial) override;
+ ::ndk::ScopedAStatus getSimultaneousCallingSupport(int32_t serial) override;
::ndk::ScopedAStatus getSimSlotsStatus(int32_t serial) override;
::ndk::ScopedAStatus setNumOfLiveModems(int32_t serial, int8_t numOfLiveModems) override;
::ndk::ScopedAStatus setPreferredDataModem(int32_t serial, int8_t modemId) override;
diff --git a/radio/aidl/vts/radio_config_indication.cpp b/radio/aidl/vts/radio_config_indication.cpp
index a84c20b..c707663 100644
--- a/radio/aidl/vts/radio_config_indication.cpp
+++ b/radio/aidl/vts/radio_config_indication.cpp
@@ -22,3 +22,8 @@
RadioIndicationType /*type*/, const std::vector<SimSlotStatus>& /*slotStatus*/) {
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioConfigIndication::onSimultaneousCallingSupportChanged(
+ const std::vector<int32_t>& /*enabledLogicalSlots*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_response.cpp b/radio/aidl/vts/radio_config_response.cpp
index 7384f87..dccbd0e 100644
--- a/radio/aidl/vts/radio_config_response.cpp
+++ b/radio/aidl/vts/radio_config_response.cpp
@@ -40,6 +40,13 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus RadioConfigResponse::getSimultaneousCallingSupportResponse(
+ const RadioResponseInfo& info, const std::vector<int32_t>& /* enabledLogicalSlots */) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus RadioConfigResponse::setPreferredDataModemResponse(
const RadioResponseInfo& info) {
rspInfo = info;
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
index d8c0142..f725136 100644
--- a/radio/aidl/vts/radio_config_test.cpp
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -122,6 +122,41 @@
}
/*
+ * Test IRadioConfig.getSimultaneousCallingSupport() for the response returned.
+ */
+TEST_P(RadioConfigTest, getSimultaneousCallingSupport) {
+ if (telephony_flags::enforce_telephony_feature_mapping()) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY)) {
+ GTEST_SKIP() << "Skipping getSimultaneousCallingSupport "
+ "due to undefined FEATURE_TELEPHONY";
+ }
+ }
+
+ int32_t aidl_version;
+ ndk::ScopedAStatus aidl_status = radio_config->getInterfaceVersion(&aidl_version);
+ ASSERT_OK(aidl_status);
+ if (aidl_version < 3) {
+ ALOGI("Skipped the test since"
+ " getSimultaneousCallingSupport is not supported on version < 3.");
+ GTEST_SKIP();
+ }
+
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getSimultaneousCallingSupport(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+ ALOGI("getSimultaneousCallingSupport, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_config->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+ RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
* Test IRadioConfig.setPreferredDataModem() for the response returned.
*/
TEST_P(RadioConfigTest, setPreferredDataModem) {
diff --git a/radio/aidl/vts/radio_config_utils.h b/radio/aidl/vts/radio_config_utils.h
index f79aedb..9e809ff 100644
--- a/radio/aidl/vts/radio_config_utils.h
+++ b/radio/aidl/vts/radio_config_utils.h
@@ -48,6 +48,9 @@
virtual ndk::ScopedAStatus getPhoneCapabilityResponse(
const RadioResponseInfo& info, const PhoneCapability& phoneCapability) override;
+ virtual ndk::ScopedAStatus getSimultaneousCallingSupportResponse(
+ const RadioResponseInfo& info, const std::vector<int32_t>& enabledLogicalSlots) override;
+
virtual ndk::ScopedAStatus setPreferredDataModemResponse(
const RadioResponseInfo& info) override;
@@ -71,6 +74,9 @@
virtual ndk::ScopedAStatus simSlotsStatusChanged(
RadioIndicationType type, const std::vector<SimSlotStatus>& slotStatus) override;
+
+ virtual ndk::ScopedAStatus onSimultaneousCallingSupportChanged(
+ const std::vector<int32_t>& /*enabledLogicalSlots*/) override;
};
// The main test class for Radio AIDL Config.
diff --git a/security/authgraph/aidl/vts/functional/sink.rs b/security/authgraph/aidl/vts/functional/sink.rs
index bb357b8..a331eef 100644
--- a/security/authgraph/aidl/vts/functional/sink.rs
+++ b/security/authgraph/aidl/vts/functional/sink.rs
@@ -29,11 +29,11 @@
}
/// Perform mainline AuthGraph key exchange with the provided sink and local implementation.
-/// Return the agreed AES keys in plaintext.
+/// Return the agreed AES keys in plaintext, together with the session ID.
pub fn test_mainline(
local_source: &mut ke::AuthGraphParticipant,
sink: binder::Strong<dyn IAuthGraphKeyExchange>,
-) -> [key::AesKey; 2] {
+) -> ([key::AesKey; 2], Vec<u8>) {
// Step 1: create an ephemeral ECDH key at the (local) source.
let source_init_info = local_source
.create()
@@ -113,7 +113,7 @@
Ok(array) => array,
Err(_) => panic!("wrong number of decrypted shared key arcs"),
};
- decrypted_shared_keys_array
+ (decrypted_shared_keys_array, sink_info.sessionId)
}
/// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid
diff --git a/security/authgraph/aidl/vts/functional/source.rs b/security/authgraph/aidl/vts/functional/source.rs
index a1e76b3..019e1e8 100644
--- a/security/authgraph/aidl/vts/functional/source.rs
+++ b/security/authgraph/aidl/vts/functional/source.rs
@@ -29,11 +29,11 @@
}
/// Perform mainline AuthGraph key exchange with the provided source.
-/// Return the agreed AES keys in plaintext.
+/// Return the agreed AES keys in plaintext, together with the session ID.
pub fn test_mainline(
local_sink: &mut ke::AuthGraphParticipant,
source: binder::Strong<dyn IAuthGraphKeyExchange>,
-) -> [key::AesKey; 2] {
+) -> ([key::AesKey; 2], Vec<u8>) {
// Step 1: create an ephemeral ECDH key at the (remote) source.
let source_init_info = source
.create()
@@ -120,7 +120,7 @@
Ok(array) => array,
Err(_) => panic!("wrong number of decrypted shared key arcs"),
};
- decrypted_shared_keys_array
+ (decrypted_shared_keys_array, source_info.sessionId)
}
/// Perform mainline AuthGraph key exchange with the provided source, but provide an invalid session
diff --git a/security/authgraph/default/src/lib.rs b/security/authgraph/default/src/lib.rs
index 1f851b2..1d6ffb3 100644
--- a/security/authgraph/default/src/lib.rs
+++ b/security/authgraph/default/src/lib.rs
@@ -22,6 +22,7 @@
ta::{AuthGraphTa, Role},
};
use authgraph_hal::channel::SerializedChannel;
+use log::error;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{mpsc, Mutex};
@@ -57,10 +58,23 @@
);
// Loop forever processing request messages.
loop {
- let req_data: Vec<u8> = in_rx.recv().expect("failed to receive next req");
+ let req_data: Vec<u8> = match in_rx.recv() {
+ Ok(data) => data,
+ Err(_) => {
+ error!("local TA failed to receive request!");
+ break;
+ }
+ };
let rsp_data = ta.process(&req_data);
- out_tx.send(rsp_data).expect("failed to send out rsp");
+ match out_tx.send(rsp_data) {
+ Ok(_) => {}
+ Err(_) => {
+ error!("local TA failed to send out response");
+ break;
+ }
+ }
}
+ error!("local TA terminating!");
});
Ok(Self {
channels: Mutex::new(Channels { in_tx, out_rx }),
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 2180d0f..2d00b83 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -210,10 +210,10 @@
describes an RKP VM. If there are further certificates without the RKP VM
marker, then the chain does not describe an RKP VM.
- Implementations must include the first RPK VM marker as early as possible
+ Implementations must include the first RKP VM marker as early as possible
after the point of divergence between TEE and non-TEE components in the DICE
chain, prior to loading the Android Bootloader (ABL).
2. "widevine" or "keymint": If there are no certificates with the RKP VM
marker then it describes a TEE component.
3. None: Any component described by a DICE chain that does not match the above
- two categories.
\ No newline at end of file
+ two categories.
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index a1de93e..68b966c 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -402,7 +402,7 @@
for (auto& key : keysToSign_) {
bytevec privateKeyBlob;
auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
vector<uint8_t> payload_value;
check_maced_pubkey(key, testMode, &payload_value);
@@ -447,7 +447,7 @@
auto status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto result = verifyProductionProtectedData(
deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
@@ -472,7 +472,7 @@
auto status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto firstBcc = verifyProductionProtectedData(
deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
@@ -482,7 +482,7 @@
status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto secondBcc = verifyProductionProtectedData(
deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
@@ -532,7 +532,7 @@
auto status = provisionable_->generateCertificateRequest(
testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
&keysToSignMac);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto result = verifyProductionProtectedData(
deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
@@ -576,7 +576,7 @@
auto status = provisionable_->generateCertificateRequest(
testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_FALSE(status.isOk()) << status.getMessage();
+ ASSERT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
@@ -596,7 +596,7 @@
auto status = provisionable_->generateCertificateRequest(
testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
challenge_, &deviceInfo, &protectedData, &keysToSignMac);
- ASSERT_FALSE(status.isOk()) << status.getMessage();
+ ASSERT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
@@ -722,7 +722,7 @@
auto challenge = randomBytes(size);
auto status =
provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge);
ASSERT_TRUE(result) << result.message();
@@ -743,7 +743,7 @@
SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
auto challenge = randomBytes(size);
auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge);
ASSERT_TRUE(result) << result.message();
@@ -758,7 +758,7 @@
auto status = provisionable_->generateCertificateRequestV2(
/* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
- EXPECT_FALSE(status.isOk()) << status.getMessage();
+ EXPECT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
}
@@ -773,13 +773,13 @@
bytevec csr;
auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
ASSERT_TRUE(firstCsr) << firstCsr.message();
status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
ASSERT_TRUE(secondCsr) << secondCsr.message();
@@ -797,7 +797,7 @@
bytevec csr;
auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
- ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
ASSERT_TRUE(result) << result.message();
@@ -815,7 +815,7 @@
bytevec csr;
auto status =
provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
- ASSERT_FALSE(status.isOk()) << status.getMessage();
+ ASSERT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
@@ -829,7 +829,7 @@
auto status = provisionable_->generateCertificateRequest(
false /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_FALSE(status.isOk()) << status.getMessage();
+ ASSERT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
}
@@ -843,7 +843,7 @@
auto status = provisionable_->generateCertificateRequest(
true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
- ASSERT_FALSE(status.isOk()) << status.getMessage();
+ ASSERT_FALSE(status.isOk()) << status.getDescription();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
}
@@ -927,7 +927,7 @@
bytevec csr;
irpcStatus =
provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
- ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage();
+ ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
ASSERT_TRUE(result) << result.message();
diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index 023fc8f..8ce37cd 100644
--- a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -36,4 +36,9 @@
interface ISecretkeeper {
android.hardware.security.authgraph.IAuthGraphKeyExchange getAuthGraphKe();
byte[] processSecretManagementRequest(in byte[] request);
+ void deleteIds(in android.hardware.security.secretkeeper.SecretId[] ids);
+ void deleteAll();
+ const int ERROR_UNKNOWN_KEY_ID = 1;
+ const int ERROR_INTERNAL_ERROR = 2;
+ const int ERROR_REQUEST_MALFORMED = 3;
}
diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl
new file mode 100644
index 0000000..9887066
--- /dev/null
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.secretkeeper;
+/* @hide */
+@VintfStability
+parcelable SecretId {
+ byte[64] id;
+}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index 1f4768a..b07dba8 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -17,6 +17,7 @@
package android.hardware.security.secretkeeper;
import android.hardware.security.authgraph.IAuthGraphKeyExchange;
+import android.hardware.security.secretkeeper.SecretId;
@VintfStability
/**
@@ -30,19 +31,22 @@
* - A trusted execution environment such as ARM TrustZone.
* - A completely separate, purpose-built and certified secure CPU.
*
- * TODO(b/291224769): Extend the HAL interface to include:
- * 1. Dice policy operation - These allow sealing of the secrets with a class of Dice chains.
- * Typical operations are (securely) updating the dice policy sealing the Secrets above. These
- * operations are core to AntiRollback protected secrets - ie, ensuring secrets of a pVM are only
- * accessible to same or higher versions of the images.
- * 2. Maintenance api: This is required for removing the Secretkeeper entries for obsolete pvMs.
*/
interface ISecretkeeper {
+ const int ERROR_UNKNOWN_KEY_ID = 1;
+ const int ERROR_INTERNAL_ERROR = 2;
+ const int ERROR_REQUEST_MALFORMED = 3;
+
/**
* Retrieve the instance of the `IAuthGraphKeyExchange` HAL that should be used for shared
- * session key establishment. These keys are used to perform encryption of messages as
+ * session key establishment. These keys are used to perform encryption of messages as
* described in SecretManagement.cddl, allowing the client and Secretkeeper to have a
- * cryptographically secure channel.
+ * cryptographically secure channel. In the key exchange protocol the client acts as P1
+ * (source) and Secretkeeper as P2 (sink). The interface returned here can be used to invoke
+ * methods on the sink.
+ *
+ * The client's identity is its DICE chain; Secretkeeper's identity is a
+ * per-boot key pair.
*/
IAuthGraphKeyExchange getAuthGraphKe();
@@ -57,10 +61,14 @@
* ProtectedRequestPacket & ProtectedResponsePacket using symmetric keys agreed between
* the client & service. This cryptographic protection is required because the messages are
* ferried via Android, which is allowed to be outside the TCB of clients (for example protected
- * Virtual Machines). For this, service (& client) must implement a key exchange protocol, which
- * is critical for establishing the secure channel.
+ * Virtual Machines). For this, service (& client) must implement the AuthGraph key exchange
+ * protocol to establish a secure channel between them.
+ *
+ * If an encrypted response cannot be generated, then a service-specific Binder error using one
+ * of the ERROR_ codes above will be returned.
*
* Secretkeeper database should guarantee the following properties:
+ *
* 1. Confidentiality: No entity (of security privilege lower than Secretkeeper) should
* be able to get a client's data in clear.
*
@@ -78,4 +86,19 @@
* @return CBOR-encoded ProtectedResponsePacket. See SecretManagement.cddl for its definition
*/
byte[] processSecretManagementRequest(in byte[] request);
+
+ /**
+ * Delete the data corresponding to a collection of IDs.
+ *
+ * Note that unlike `processSecretManagementRequest`, the contents of this method are in
+ * plaintext, and no client authentication is required.
+ *
+ * @param Secret identifiers to delete.
+ */
+ void deleteIds(in SecretId[] ids);
+
+ /**
+ * Delete data of all clients.
+ */
+ void deleteAll();
}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl
new file mode 100644
index 0000000..b17917f
--- /dev/null
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.secretkeeper;
+
+/**
+ * SecretId contains an identifier for a secret held by Secretkeeper.
+ * @hide
+ */
+@VintfStability
+parcelable SecretId {
+ /**
+ * 64-byte identifier for a secret.
+ */
+ byte[64] id;
+}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
index 5631937..6a824c9 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
@@ -1,116 +1,116 @@
; CDDL for the Secret Management API.
-; Also see processSecretManagementRequest method in ISecretkeeper.aidl
-; ProtectedRequestPacket is used by client for accessing Secret Management API
-; in Secretkeeper service. The service returns ProtectedResponsePacket of the corresponding type.
+; The input parameter to the `processSecretManagementRequest` operation in
+; `ISecretkeeper.aidl` is always an encrypted request message, CBOR-encoded as a
+; COSE_Encrypt0 object. The encryption uses the first of the keys agreed using
+; the associated AuthGraph instance, referred to as `KeySourceToSink`. Additionally,
+; an external aad is used - RequestSeqNum.
+ProtectedRequestPacket = CryptoPayload<RequestPacket, KeySourceToSink, RequestSeqNum>
-; ProtectedRequestPacket & ProtectedResponsePacket are encrypted wrappers
-; on RequestPacket & ResponsePacket using symmetric keys agreed between Secretkeeper & clients
-; (these are referred to as KeySourceToSink & KeySinkToSource)
-;
-; The API operation required is encoded using 'Opcode', the arguments using 'Params'
-; and returned values as 'Result'.
-
-ProtectedRequestPacket =
- ProtectedGetVersionRequest / ProtectedStoreSecretRequest / ProtectedGetSecretRequest
-ProtectedResponsePacket =
- ProtectedGetVersionResponse / ProtectedStoreSecretResponse / ProtectedGetSecretResponse
-
-ProtectedGetVersionRequest = ProtectedRequestPacket<GetVersionRequestPacket>
-ProtectedGetVersionResponse = ProtectedResponsePacket<GetVersionResponsePacket>
-ProtectedStoreSecretRequest = ProtectedRequestPacket<StoreSecretRequestPacket>
-ProtectedStoreSecretResponse = ProtectedResponsePacket<StoreSecretResponsePacket>
-ProtectedGetSecretRequest = ProtectedRequestPacket<GetSecretRequestPacket>
-ProtectedGetSecretResponse = ProtectedResponsePacket<GetSecretResponsePacket>
-
-GetVersionRequestPacket = RequestPacket<GetVersionOpcode, GetVersionParams>
-GetVersionResponsePacket = ResponsePacket<GetVersionResult>
-StoreSecretRequestPacket = RequestPacket<StoreSecretOpcode, StoreSecretParams>
-StoreSecretResponsePacket = ResponsePacket<StoreSecretResult>
-GetSecretRequestPacket = RequestPacket<GetOpcode, GetSecretParams>
-GetSecretResponsePacket = ResponsePacket<GetSecretResult>
-
-RequestPacket<Opcode, Params> = [
- Opcode,
- Params
-]
-ResponsePacket<Result> = ResponsePacketError / ResponsePacketSuccess<Result>
-
-ResponsePacketSuccess = [
- 0, ; Indicates successful Response
- result : Result
-]
-ResponsePacketError = [
- error_code: ErrorCode, ; Indicate the error
- error_message: tstr ; Additional human-readable context
-]
-
-Opcode = &(
- GetVersionOpcode: 1, ; Get version of the SecretManagement API
- StoreSecretOpcode: 2, ; Store a secret
- GetSecretOpcode: 3, ; Get the secret
-)
-
-GetVersionParams = ()
-GetVersionResult = (version : uint)
-
-StoreSecretParams = (
- id : bstr .size 64 ; Unique identifier of the secret
- secret : bstr .size 32,
- sealing_policy : bstr .cbor DicePolicy, ; See DicePolicy.cddl for definition of DicePolicy
-)
-StoreSecretResult = ()
-
-GetSecretParams = (
- id : bstr .size 64 ; Unique identifier of the secret
- ; Use this to update the sealing policy associated with a secret during GetSecret operation.
- updated_sealing_policy : bstr .cbor DicePolicy / nil,
-)
-GetSecretResult = (secret : bstr .size 32)
-
-
-ProtectedRequestPacket<Payload, Key> = CryptoPayload<Payload, KeySourceToSink>
-ProtectedResponsePacket<Payload, Key> = ProtectedResponseError
- / ProtectedResponseSuccess<Payload>
-
-ProtectedResponseSuccess<Payload> = [
- 0, ; Indicates successful crypto operations. Note: Payload
- ; may contain Error from functional layer.
- message: CryptoPayload<Payload, KeySinkToSource> ; message is the encrypted payload
-]
-
-ProtectedResponseError = [
- error_code: CryptoErrorCode, ; Indicates the error. This is in cleartext & will be
- ; visible to Android. These are errors from crypto
- ; layer & indicates the request could not even be read
- message: tstr ; Additional human-readable context
-]
-
-CryptoPayload<Payload, Key> = [ ; COSE_Encrypt0 (untagged), [RFC 9052 s5.2]
+CryptoPayload<Payload, Key, SeqNum> = [ ; COSE_Encrypt0 (untagged), [RFC 9052 s5.2]
protected: bstr .cbor {
1 : 3, ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag
- 4 : bstr ; key identifier, uniquely identifies the session
- ; TODO(b/291228560): Refer to the Key Exchange spec.
+ 4 : bstr ; key identifier set to session ID produced
+ ; by AuthGraph key exchange.
},
unprotected: {
- 5 : bstr .size 12 ; IV
+ 5 : bstr .size 12 ; IV
},
- ciphertext : bstr ; AES-GCM-256(Key, bstr .cbor Payload)
- ; AAD for the encryption is CBOR-serialized
- ; Enc_structure (RFC 9052 s5.3) with empty external_aad.
+ ciphertext : bstr ; AES-GCM-256(Key, bstr .cbor Payload)
+ ; AAD for the encryption is CBOR-serialized
+ ; Enc_structure (RFC 9052 s5.3) with SeqNum as the external_aad.
]
-; TODO(b/291224769): Create a more exhaustive set of CryptoErrorCode
-CryptoErrorCode = &(
- CryptoErrorCode_SessionExpired: 1,
+; Once decrypted, the request packet is an encoded CBOR array holding:
+; - An initial integer indicating which request is present.
+; - Subsequent objects holding the parameters for that specific request.
+RequestPacket =
+ [GetVersionOpcode, GetVersionParams] /
+ [StoreSecretOpcode, StoreSecretParams] /
+ [GetSecretOpcode, GetSecretParams]
+
+GetVersionOpcode = 1 ; Get version of the SecretManagement API
+StoreSecretOpcode = 2 ; Store a secret
+GetSecretOpcode = 3 ; Get the secret
+
+; Retrieve Secretkeeper version.
+GetVersionParams = ()
+
+; Store a secret identified by the given ID, with access to the secret policed
+; by the associated sealing policy.
+StoreSecretParams = (
+ id : SecretId,
+ secret : Secret,
+ sealing_policy : bstr .cbor DicePolicy,
)
-; TODO(b/291224769): Create a more exhaustive set of ErrorCodes
+; INCLUDE DicePolicy.cddl for: DicePolicy
+
+; Retrieve a secret identified by the given ID, policed according to the sealing
+; policy that was associated with the secret. If successful, optionally also
+; update the sealing policy for the secret.
+GetSecretParams = (
+ id : SecretId,
+ ; Retrieving the value of a secret may optionally also update the sealing
+ ; policy associated with a secret.
+ updated_sealing_policy : bstr .cbor DicePolicy / nil,
+)
+
+SecretId = bstr .size 64 ; Unique identifier of the secret.
+Secret = bstr .size 32 ; The secret value.
+
+; A monotonically incrementing number is associated with each RequestPacket to prevent replay
+; of messages within a session. This starts with 0 and is incremented (by 1) for each request
+; in a session. Secretkeeper implementation must maintain an expected RequestSeqNum for each
+; session (increasing it by 1 for each SecretManagement request received). This will be used in
+; in decryption (external_aad).
+RequestSeqNum = bstr .cbor uint ; Encoded in accordance with Core Deterministic Encoding
+ ; Requirements [RFC 8949 s4.2.1]
+
+; The return value from a successful `processSecretManagementRequest` operation is a
+; response message encrypted with the second of the keys agreed using the associated
+; AuthGraph instance, referred to as `KeySinkToSource`.
+ProtectedResponsePacket = CryptoPayload<ResponsePacket, KeySinkToSource, ResponseSeqNum>
+
+; Once decrypted, the inner response message is encoded as a CBOR array holding:
+; - An initial integer return code value.
+; - Subsequently:
+; - If the return code is zero: result value(s).
+; - If the return code is non-zero: an error message.
+ResponsePacket =
+ [0, Result] /
+ [error_code: ErrorCode, error_message: tstr]
+
+; An error code in the inner response message indicates a failure in
+; secret management processing.
ErrorCode = &(
; Use this as if no other error code can be used.
ErrorCode_UnexpectedServerError: 1,
; Indicate the Request was malformed & hence couldnt be served.
ErrorCode_RequestMalformed: 2,
+ ; Requested Entry not found.
+ ErrorCode_EntryNotFound: 3,
+ ; Error happened while serialization or deserialization.
+ ErrorCode_SerializationError: 4,
+ ; Indicates that Dice Policy matching did not succeed & hence access not granted.
+ ErrorCode_DicePolicyError: 5,
)
-; INCLUDE DicePolicy.cddl for: DicePolicy
\ No newline at end of file
+; The particular result variant present is determined by which request
+; message was originally sent.
+Result = &(
+ GetVersionResult,
+ StoreSecretResult,
+ GetSecretResult,
+)
+
+GetVersionResult = (1)
+
+StoreSecretResult = ()
+
+GetSecretResult = (secret : Secret)
+
+; Analogous to RequestSeqNum, Secretkeeper must maintain ResponseSeqNum for each session.
+; This will be input to the encryption (ProtectedResponsePacket) as external_aad.
+ResponseSeqNum = bstr .cbor uint ; Encoded in accordance with Core Deterministic Encoding
+ ; Requirements [RFC 8949 s4.2.1]
diff --git a/security/secretkeeper/aidl/vts/Android.bp b/security/secretkeeper/aidl/vts/Android.bp
index 93192e9..7de9d6a 100644
--- a/security/secretkeeper/aidl/vts/Android.bp
+++ b/security/secretkeeper/aidl/vts/Android.bp
@@ -25,14 +25,20 @@
"general-tests",
"vts",
],
+ test_config: "AndroidTest.xml",
rustlibs: [
+ "libsecretkeeper_client",
"libsecretkeeper_comm_nostd",
+ "libsecretkeeper_core_nostd",
"android.hardware.security.secretkeeper-V1-rust",
+ "libauthgraph_boringssl",
"libauthgraph_core",
"libcoset",
"libauthgraph_vts_test",
"libbinder_rs",
+ "libcoset",
"liblog_rust",
+ "liblogger",
],
require_root: true,
}
diff --git a/security/secretkeeper/aidl/vts/AndroidTest.xml b/security/secretkeeper/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..4fee78f
--- /dev/null
+++ b/security/secretkeeper/aidl/vts/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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="Config for Secretkeeper VTS tests.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="VtsSecretkeeperTargetTest" value="/data/local/tmp/VtsSecretkeeperTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+ <option name="test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsSecretkeeperTargetTest" />
+ <!-- Rust tests are run in parallel by default. Run these ones
+ single-threaded, so that one test's secrets don't affect
+ the behaviour of a different test. -->
+ <option name="native-test-flag" value="--test-threads=1" />
+ </test>
+</configuration>
diff --git a/security/secretkeeper/aidl/vts/rustfmt.toml b/security/secretkeeper/aidl/vts/rustfmt.toml
new file mode 120000
index 0000000..ed2086b
--- /dev/null
+++ b/security/secretkeeper/aidl/vts/rustfmt.toml
@@ -0,0 +1 @@
+../../../../../../build/soong/scripts/rustfmt.toml
\ No newline at end of file
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
index 8c6b4fe..c457d24 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
@@ -14,38 +14,238 @@
* limitations under the License.
*/
-#[cfg(test)]
+#![cfg(test)]
+
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::SecretId::SecretId;
+use authgraph_vts_test as ag_vts;
+use authgraph_boringssl as boring;
+use authgraph_core::key;
use binder::StatusCode;
-use coset::CborSerializable;
-use log::warn;
+use coset::{CborSerializable, CoseEncrypt0};
+use log::{info, warn};
+use secretkeeper_client::SkSession;
+use secretkeeper_core::cipher;
use secretkeeper_comm::data_types::error::SecretkeeperError;
use secretkeeper_comm::data_types::request::Request;
use secretkeeper_comm::data_types::request_response_impl::{
- GetVersionRequest, GetVersionResponse,
-};
+ GetVersionRequest, GetVersionResponse, GetSecretRequest, GetSecretResponse, StoreSecretRequest,
+ StoreSecretResponse };
+use secretkeeper_comm::data_types::{Id, Secret, SeqNum};
use secretkeeper_comm::data_types::response::Response;
use secretkeeper_comm::data_types::packet::{ResponsePacket, ResponseType};
-use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
-use authgraph_vts_test as ag_vts;
-use authgraph_core::key;
-const SECRETKEEPER_IDENTIFIER: &str =
- "android.hardware.security.secretkeeper.ISecretkeeper/nonsecure";
+const SECRETKEEPER_SERVICE: &str = "android.hardware.security.secretkeeper.ISecretkeeper";
+const SECRETKEEPER_INSTANCES: [&'static str; 2] = ["default", "nonsecure"];
const CURRENT_VERSION: u64 = 1;
-fn get_connection() -> Option<binder::Strong<dyn ISecretkeeper>> {
- match binder::get_interface(SECRETKEEPER_IDENTIFIER) {
- Ok(sk) => Some(sk),
- Err(StatusCode::NAME_NOT_FOUND) => None,
- Err(e) => {
- panic!(
- "unexpected error while fetching connection to Secretkeeper {:?}",
- e
- );
+// TODO(b/291238565): This will change once libdice_policy switches to Explicit-key DiceCertChain
+// This is generated by patching libdice_policy such that it dumps an example dice chain &
+// a policy, such that the former matches the latter.
+const HYPOTHETICAL_DICE_POLICY: [u8; 43] = [
+ 0x83, 0x01, 0x81, 0x83, 0x01, 0x80, 0xA1, 0x01, 0x00, 0x82, 0x83, 0x01, 0x81, 0x01, 0x73, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x64, 0x69, 0x63, 0x65, 0x5F, 0x70, 0x6F, 0x6C, 0x69,
+ 0x63, 0x79, 0x83, 0x02, 0x82, 0x03, 0x18, 0x64, 0x19, 0xE9, 0x75,
+];
+
+// Random bytes (of ID_SIZE/SECRET_SIZE) generated for tests.
+const ID_EXAMPLE: Id = Id([
+ 0xF1, 0xB2, 0xED, 0x3B, 0xD1, 0xBD, 0xF0, 0x7D, 0xE1, 0xF0, 0x01, 0xFC, 0x61, 0x71, 0xD3, 0x42,
+ 0xE5, 0x8A, 0xAF, 0x33, 0x6C, 0x11, 0xDC, 0xC8, 0x6F, 0xAE, 0x12, 0x5C, 0x26, 0x44, 0x6B, 0x86,
+ 0xCC, 0x24, 0xFD, 0xBF, 0x91, 0x4A, 0x54, 0x84, 0xF9, 0x01, 0x59, 0x25, 0x70, 0x89, 0x38, 0x8D,
+ 0x5E, 0xE6, 0x91, 0xDF, 0x68, 0x60, 0x69, 0x26, 0xBE, 0xFE, 0x79, 0x58, 0xF7, 0xEA, 0x81, 0x7D,
+]);
+const ID_EXAMPLE_2: Id = Id([
+ 0x6A, 0xCC, 0xB1, 0xEB, 0xBB, 0xAB, 0xE3, 0xEA, 0x44, 0xBD, 0xDC, 0x75, 0x75, 0x7D, 0xC0, 0xE5,
+ 0xC7, 0x86, 0x41, 0x56, 0x39, 0x66, 0x96, 0x10, 0xCB, 0x43, 0x10, 0x79, 0x03, 0xDC, 0xE6, 0x9F,
+ 0x12, 0x2B, 0xEF, 0x28, 0x9C, 0x1E, 0x32, 0x46, 0x5F, 0xA3, 0xE7, 0x8D, 0x53, 0x63, 0xE8, 0x30,
+ 0x5A, 0x17, 0x6F, 0xEF, 0x42, 0xD6, 0x58, 0x7A, 0xF0, 0xCB, 0xD4, 0x40, 0x58, 0x96, 0x32, 0xF4,
+]);
+const ID_NOT_STORED: Id = Id([
+ 0x56, 0xD0, 0x4E, 0xAA, 0xC1, 0x7B, 0x55, 0x6B, 0xA0, 0x2C, 0x65, 0x43, 0x39, 0x0A, 0x6C, 0xE9,
+ 0x1F, 0xD0, 0x0E, 0x20, 0x3E, 0xFB, 0xF5, 0xF9, 0x3F, 0x5B, 0x11, 0x1B, 0x18, 0x73, 0xF6, 0xBB,
+ 0xAB, 0x9F, 0xF2, 0xD6, 0xBD, 0xBA, 0x25, 0x68, 0x22, 0x30, 0xF2, 0x1F, 0x90, 0x05, 0xF3, 0x64,
+ 0xE7, 0xEF, 0xC6, 0xB6, 0xA0, 0x85, 0xC9, 0x40, 0x40, 0xF0, 0xB4, 0xB9, 0xD8, 0x28, 0xEE, 0x9C,
+]);
+const SECRET_EXAMPLE: Secret = Secret([
+ 0xA9, 0x89, 0x97, 0xFE, 0xAE, 0x97, 0x55, 0x4B, 0x32, 0x35, 0xF0, 0xE8, 0x93, 0xDA, 0xEA, 0x24,
+ 0x06, 0xAC, 0x36, 0x8B, 0x3C, 0x95, 0x50, 0x16, 0x67, 0x71, 0x65, 0x26, 0xEB, 0xD0, 0xC3, 0x98,
+]);
+
+fn get_connection() -> Option<(binder::Strong<dyn ISecretkeeper>, String)> {
+ // Initialize logging (which is OK to call multiple times).
+ logger::init(logger::Config::default().with_min_level(log::Level::Debug));
+
+ // Determine which instances are available.
+ let available = binder::get_declared_instances(SECRETKEEPER_SERVICE).unwrap_or_default();
+
+ // TODO: replace this with a parameterized set of tests that run for each available instance of
+ // ISecretkeeper (rather than having a fixed set of instance names to look for).
+ for instance in &SECRETKEEPER_INSTANCES {
+ if available.iter().find(|s| s == instance).is_none() {
+ // Skip undeclared instances.
+ continue;
+ }
+ let name = format!("{SECRETKEEPER_SERVICE}/{instance}");
+ match binder::get_interface(&name) {
+ Ok(sk) => {
+ info!("Running test against /{instance}");
+ return Some((sk, name));
+ }
+ Err(StatusCode::NAME_NOT_FOUND) => {
+ info!("No /{instance} instance of ISecretkeeper present");
+ }
+ Err(e) => {
+ panic!(
+ "unexpected error while fetching connection to Secretkeeper {:?}",
+ e
+ );
+ }
+ }
+ }
+ info!("no Secretkeeper instances in {SECRETKEEPER_INSTANCES:?} are declared and present");
+ None
+}
+
+/// Macro to perform test setup. Invokes `return` if no Secretkeeper instance available.
+macro_rules! setup_client {
+ {} => {
+ match SkClient::new() {
+ Some(sk) => sk,
+ None => {
+ warn!("Secretkeeper HAL is unavailable, skipping test");
+ return;
+ }
}
}
}
-fn authgraph_key_exchange(sk: binder::Strong<dyn ISecretkeeper>) -> [key::AesKey; 2] {
+
+/// Secretkeeper client information.
+struct SkClient {
+ sk: binder::Strong<dyn ISecretkeeper>,
+ name: String,
+ session: SkSession,
+}
+
+impl Drop for SkClient {
+ fn drop(&mut self) {
+ // Delete any IDs that may be left over.
+ self.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
+ }
+}
+
+impl SkClient {
+ fn new() -> Option<Self> {
+ let (sk, name) = get_connection()?;
+ Some(Self {
+ sk: sk.clone(),
+ name,
+ session: SkSession::new(sk).unwrap(),
+ })
+ }
+
+ /// This method is wrapper that use `SkSession::secret_management_request` which handles
+ /// encryption and decryption.
+ fn secret_management_request(&mut self, req_data: &[u8]) -> Vec<u8> {
+ self.session.secret_management_request(req_data).unwrap()
+ }
+
+ /// Unlike the method [`secret_management_request`], this method directly uses
+ /// `cipher::encrypt_message` & `cipher::decrypt_message`, allowing finer control of request
+ /// & response aad.
+ fn secret_management_request_custom_aad(
+ &self,
+ req_data: &[u8],
+ req_aad: &[u8],
+ expected_res_aad: &[u8],
+ ) -> Vec<u8> {
+ let aes_gcm = boring::BoringAes;
+ let rng = boring::BoringRng;
+ let request_bytes = cipher::encrypt_message(
+ &aes_gcm,
+ &rng,
+ self.session.encryption_key(),
+ self.session.session_id(),
+ &req_data,
+ req_aad,
+ )
+ .unwrap();
+
+ // Binder call!
+ let response_bytes = self
+ .sk
+ .processSecretManagementRequest(&request_bytes)
+ .unwrap();
+
+ let response_encrypt0 = CoseEncrypt0::from_slice(&response_bytes).unwrap();
+ cipher::decrypt_message(
+ &aes_gcm,
+ self.session.decryption_key(),
+ &response_encrypt0,
+ expected_res_aad,
+ )
+ .unwrap()
+ }
+
+ /// Helper method to store a secret.
+ fn store(&mut self, id: &Id, secret: &Secret) {
+ let store_request = StoreSecretRequest {
+ id: id.clone(),
+ secret: secret.clone(),
+ sealing_policy: HYPOTHETICAL_DICE_POLICY.to_vec(),
+ };
+ let store_request = store_request.serialize_to_packet().to_vec().unwrap();
+
+ let store_response = self.secret_management_request(&store_request);
+ let store_response = ResponsePacket::from_slice(&store_response).unwrap();
+
+ assert_eq!(
+ store_response.response_type().unwrap(),
+ ResponseType::Success
+ );
+ // Really just checking that the response is indeed StoreSecretResponse
+ let _ = StoreSecretResponse::deserialize_from_packet(store_response).unwrap();
+ }
+
+ /// Helper method to get a secret.
+ fn get(&mut self, id: &Id) -> Option<Secret> {
+ let get_request = GetSecretRequest {
+ id: id.clone(),
+ updated_sealing_policy: None,
+ };
+ let get_request = get_request.serialize_to_packet().to_vec().unwrap();
+
+ let get_response = self.secret_management_request(&get_request);
+ let get_response = ResponsePacket::from_slice(&get_response).unwrap();
+
+ if get_response.response_type().unwrap() == ResponseType::Success {
+ let get_response = *GetSecretResponse::deserialize_from_packet(get_response).unwrap();
+ Some(Secret(get_response.secret.0))
+ } else {
+ // Only expect a not-found failure.
+ let err = *SecretkeeperError::deserialize_from_packet(get_response).unwrap();
+ assert_eq!(err, SecretkeeperError::EntryNotFound);
+ None
+ }
+ }
+
+ /// Helper method to delete secrets.
+ fn delete(&self, ids: &[&Id]) {
+ let ids: Vec<SecretId> = ids
+ .iter()
+ .map(|id| SecretId { id: id.0 })
+ .collect();
+ self.sk.deleteIds(&ids).unwrap();
+ }
+
+ /// Helper method to delete everything.
+ fn delete_all(&self) {
+ self.sk.deleteAll().unwrap();
+ }
+}
+
+/// Perform AuthGraph key exchange, returning the session keys and session ID.
+fn authgraph_key_exchange(sk: binder::Strong<dyn ISecretkeeper>) -> ([key::AesKey; 2], Vec<u8>) {
let sink = sk.getAuthGraphKe().expect("failed to get AuthGraph");
let mut source = ag_vts::test_ag_participant().expect("failed to create a local source");
ag_vts::sink::test_mainline(&mut source, sink)
@@ -55,21 +255,21 @@
/// mainline key exchange against a local source implementation.
#[test]
fn authgraph_mainline() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
return;
}
};
- let _aes_keys = authgraph_key_exchange(sk);
+ let (_aes_keys, _session_id) = authgraph_key_exchange(sk);
}
/// Test that the AuthGraph instance returned by SecretKeeper correctly rejects
/// a corrupted session ID signature.
#[test]
fn authgraph_corrupt_sig() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
@@ -85,7 +285,7 @@
/// when corrupted keys are returned to it.
#[test]
fn authgraph_corrupt_keys() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
@@ -102,23 +302,13 @@
#[test]
fn secret_management_get_version() {
- let secretkeeper = match get_connection() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let mut sk_client = setup_client!();
+
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
let request_bytes = request_packet.to_vec().unwrap();
- // TODO(b/291224769) The request will need to be encrypted & response need to be decrypted
- // with key & related artifacts pre-shared via Authgraph Key Exchange HAL.
-
- let response_bytes = secretkeeper
- .processSecretManagementRequest(&request_bytes)
- .unwrap();
+ let response_bytes = sk_client.secret_management_request(&request_bytes);
let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
assert_eq!(
@@ -132,13 +322,8 @@
#[test]
fn secret_management_malformed_request() {
- let secretkeeper = match get_connection() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let mut sk_client = setup_client!();
+
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
let mut request_bytes = request_packet.to_vec().unwrap();
@@ -146,12 +331,7 @@
// Deform the request
request_bytes[0] = !request_bytes[0];
- // TODO(b/291224769) The request will need to be encrypted & response need to be decrypted
- // with key & related artifacts pre-shared via Authgraph Key Exchange HAL.
-
- let response_bytes = secretkeeper
- .processSecretManagementRequest(&request_bytes)
- .unwrap();
+ let response_bytes = sk_client.secret_management_request(&request_bytes);
let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
assert_eq!(
@@ -161,3 +341,212 @@
let err = *SecretkeeperError::deserialize_from_packet(response_packet).unwrap();
assert_eq!(err, SecretkeeperError::RequestMalformed);
}
+
+#[test]
+fn secret_management_store_get_secret_found() {
+ let mut sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+
+ // Get the secret that was just stored
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
+}
+
+#[test]
+fn secret_management_store_get_secret_not_found() {
+ let mut sk_client = setup_client!();
+
+ // Store a secret (corresponding to an id).
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+
+ // Get the secret that was never stored
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_ids() {
+ let mut sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_EXAMPLE]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+
+ sk_client.delete(&[&ID_EXAMPLE_2]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_multiple_ids() {
+ let mut sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_duplicate_ids() {
+ let mut sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ // Delete the same secret twice.
+ sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+}
+
+#[test]
+fn secretkeeper_store_delete_nonexistent() {
+ let mut sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_NOT_STORED]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_all() {
+ let mut sk_client = setup_client!();
+
+ if sk_client.name != "nonsecure" {
+ // Don't run deleteAll() on a secure device, as it might affect
+ // real secrets.
+ warn!("skipping deleteAll test due to real impl");
+ return;
+ }
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+
+ sk_client.delete_all();
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+
+ // Store a new secret (corresponding to an id).
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+
+ // Get the restored secret.
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
+
+ // (Try to) Get the secret that was never stored
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
+}
+
+// This test checks that Secretkeeper uses the expected [`RequestSeqNum`] as aad while
+// decrypting requests and the responses are encrypted with correct [`ResponseSeqNum`] for the
+// first few messages.
+#[test]
+fn secret_management_replay_protection_seq_num() {
+ let sk_client = setup_client!();
+ // Construct encoded request packets for the test
+ let (req_1, req_2, req_3) = construct_secret_management_requests();
+
+ // Lets now construct the seq_numbers(in request & expected in response)
+ let mut seq_a = SeqNum::new();
+ let [seq_0, seq_1, seq_2] = std::array::from_fn(|_| seq_a.get_then_increment().unwrap());
+
+ // Check first request/response is successful
+ let res = ResponsePacket::from_slice(
+ &sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0),
+ )
+ .unwrap();
+ assert_eq!(res.response_type().unwrap(), ResponseType::Success);
+
+ // Check 2nd request/response is successful
+ let res = ResponsePacket::from_slice(
+ &sk_client.secret_management_request_custom_aad(&req_2, &seq_1, &seq_1),
+ )
+ .unwrap();
+ assert_eq!(res.response_type().unwrap(), ResponseType::Success);
+
+ // Check 3rd request/response is successful
+ let res = ResponsePacket::from_slice(
+ &sk_client.secret_management_request_custom_aad(&req_3, &seq_2, &seq_2),
+ )
+ .unwrap();
+ assert_eq!(res.response_type().unwrap(), ResponseType::Success);
+}
+
+// This test checks that Secretkeeper uses fresh [`RequestSeqNum`] & [`ResponseSeqNum`]
+// for new sessions.
+#[test]
+fn secret_management_replay_protection_seq_num_per_session() {
+ let sk_client = setup_client!();
+
+ // Construct encoded request packets for the test
+ let (req_1, _, _) = construct_secret_management_requests();
+
+ // Lets now construct the seq_number (in request & expected in response)
+ let mut seq_a = SeqNum::new();
+ let seq_0 = seq_a.get_then_increment().unwrap();
+ // Check first request/response is successful
+ let res = ResponsePacket::from_slice(
+ &sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0),
+ )
+ .unwrap();
+ assert_eq!(res.response_type().unwrap(), ResponseType::Success);
+
+ // Start another session
+ let sk_client_diff = setup_client!();
+ // Check first request/response is with seq_0 is successful
+ let res = ResponsePacket::from_slice(
+ &sk_client_diff.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0),
+ )
+ .unwrap();
+ assert_eq!(res.response_type().unwrap(), ResponseType::Success);
+}
+
+// This test checks that Secretkeeper rejects requests with out of order [`RequestSeqNum`]
+#[test]
+// TODO(b/317416663): This test fails, when HAL is not present in the device. Refactor to fix this.
+#[ignore]
+#[should_panic]
+fn secret_management_replay_protection_out_of_seq_req_not_accepted() {
+ let sk_client = setup_client!();
+
+ // Construct encoded request packets for the test
+ let (req_1, req_2, _) = construct_secret_management_requests();
+
+ // Lets now construct the seq_numbers(in request & expected in response)
+ let mut seq_a = SeqNum::new();
+ let [seq_0, seq_1, seq_2] = std::array::from_fn(|_| seq_a.get_then_increment().unwrap());
+
+ // Assume First request/response is successful
+ sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0);
+
+ // Check 2nd request/response with skipped seq_num in request is a binder error
+ // This should panic!
+ sk_client.secret_management_request_custom_aad(&req_2, /*Skipping seq_1*/ &seq_2, &seq_1);
+}
+
+fn construct_secret_management_requests() -> (Vec<u8>, Vec<u8>, Vec<u8>) {
+ let version_request = GetVersionRequest {};
+ let version_request = version_request.serialize_to_packet().to_vec().unwrap();
+ let store_request = StoreSecretRequest {
+ id: ID_EXAMPLE,
+ secret: SECRET_EXAMPLE,
+ sealing_policy: HYPOTHETICAL_DICE_POLICY.to_vec(),
+ };
+ let store_request = store_request.serialize_to_packet().to_vec().unwrap();
+ let get_request = GetSecretRequest {
+ id: ID_EXAMPLE,
+ updated_sealing_policy: None,
+ };
+ let get_request = get_request.serialize_to_packet().to_vec().unwrap();
+ (version_request, store_request, get_request)
+}
diff --git a/security/secretkeeper/default/Android.bp b/security/secretkeeper/default/Android.bp
index 6612ea2..1d75c74 100644
--- a/security/secretkeeper/default/Android.bp
+++ b/security/secretkeeper/default/Android.bp
@@ -18,6 +18,28 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+rust_library {
+ name: "libsecretkeeper_nonsecure",
+ crate_name: "secretkeeper_nonsecure",
+ srcs: [
+ "src/lib.rs",
+ ],
+ vendor_available: true,
+ defaults: [
+ "authgraph_use_latest_hal_aidl_rust",
+ ],
+ rustlibs: [
+ "android.hardware.security.secretkeeper-V1-rust",
+ "libauthgraph_boringssl",
+ "libauthgraph_core",
+ "libauthgraph_hal",
+ "libbinder_rs",
+ "liblog_rust",
+ "libsecretkeeper_core_nostd",
+ "libsecretkeeper_comm_nostd",
+ ],
+}
+
rust_binary {
name: "android.hardware.security.secretkeeper-service.nonsecure",
relative_install_path: "hw",
@@ -30,19 +52,34 @@
rustlibs: [
"android.hardware.security.secretkeeper-V1-rust",
"libandroid_logger",
- "libauthgraph_boringssl",
- "libauthgraph_core",
- "libauthgraph_hal",
"libbinder_rs",
"liblog_rust",
- "libsecretkeeper_core_nostd",
"libsecretkeeper_hal",
+ "libsecretkeeper_nonsecure",
],
srcs: [
"src/main.rs",
],
}
+rust_fuzz {
+ name: "android.hardware.security.secretkeeper-service.nonsecure_fuzzer",
+ rustlibs: [
+ "libsecretkeeper_hal",
+ "libsecretkeeper_nonsecure",
+ "libbinder_random_parcel_rs",
+ "libbinder_rs",
+ ],
+ srcs: ["src/fuzzer.rs"],
+ fuzz_config: {
+ cc: [
+ "alanstokes@google.com",
+ "drysdale@google.com",
+ "shikhapanwar@google.com",
+ ],
+ },
+}
+
prebuilt_etc {
name: "secretkeeper.rc",
src: "secretkeeper.rc",
diff --git a/security/secretkeeper/default/src/fuzzer.rs b/security/secretkeeper/default/src/fuzzer.rs
new file mode 100644
index 0000000..914ebe6
--- /dev/null
+++ b/security/secretkeeper/default/src/fuzzer.rs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#![allow(missing_docs)]
+#![no_main]
+extern crate libfuzzer_sys;
+
+use binder_random_parcel_rs::fuzz_service;
+use libfuzzer_sys::fuzz_target;
+use secretkeeper_hal::SecretkeeperService;
+use secretkeeper_nonsecure::{AuthGraphChannel, LocalTa, SecretkeeperChannel};
+use std::sync::{Arc, Mutex};
+
+fuzz_target!(|data: &[u8]| {
+ let ta = Arc::new(Mutex::new(LocalTa::new()));
+ let ag_channel = AuthGraphChannel(ta.clone());
+ let sk_channel = SecretkeeperChannel(ta.clone());
+
+ let service = SecretkeeperService::new_as_binder(sk_channel, ag_channel);
+ fuzz_service(&mut service.as_binder(), data);
+});
diff --git a/security/secretkeeper/default/src/lib.rs b/security/secretkeeper/default/src/lib.rs
new file mode 100644
index 0000000..412ad45
--- /dev/null
+++ b/security/secretkeeper/default/src/lib.rs
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! Non-secure implementation of a local Secretkeeper TA.
+
+use authgraph_boringssl as boring;
+use authgraph_core::keyexchange::{AuthGraphParticipant, MAX_OPENED_SESSIONS};
+use authgraph_core::ta::{AuthGraphTa, Role};
+use authgraph_hal::channel::SerializedChannel;
+use log::error;
+use secretkeeper_core::ta::SecretkeeperTa;
+use std::cell::RefCell;
+use std::rc::Rc;
+use std::sync::mpsc;
+use std::sync::{Arc, Mutex};
+
+mod store;
+
+/// Implementation of the Secrekeeper TA that runs locally in-process (and which is therefore
+/// insecure).
+pub struct LocalTa {
+ in_tx: mpsc::Sender<Vec<u8>>,
+ out_rx: mpsc::Receiver<Vec<u8>>,
+}
+
+/// Prefix byte for messages intended for the AuthGraph TA.
+const AG_MESSAGE_PREFIX: u8 = 0x00;
+/// Prefix byte for messages intended for the Secretkeeper TA.
+const SK_MESSAGE_PREFIX: u8 = 0x01;
+
+impl LocalTa {
+ /// Create a new instance.
+ pub fn new() -> Self {
+ // Create a pair of channels to communicate with the TA thread.
+ let (in_tx, in_rx) = mpsc::channel();
+ let (out_tx, out_rx) = mpsc::channel();
+
+ // The TA code expects to run single threaded, so spawn a thread to run it in.
+ std::thread::spawn(move || {
+ let mut crypto_impls = boring::crypto_trait_impls();
+ let storage_impl = Box::new(store::InMemoryStore::default());
+ let sk_ta = Rc::new(RefCell::new(
+ SecretkeeperTa::new(&mut crypto_impls, storage_impl)
+ .expect("Failed to create local Secretkeeper TA"),
+ ));
+ let mut ag_ta = AuthGraphTa::new(
+ AuthGraphParticipant::new(crypto_impls, sk_ta.clone(), MAX_OPENED_SESSIONS)
+ .expect("Failed to create local AuthGraph TA"),
+ Role::Sink,
+ );
+
+ // Loop forever processing request messages.
+ loop {
+ let req_data: Vec<u8> = match in_rx.recv() {
+ Ok(data) => data,
+ Err(_) => {
+ error!("local TA failed to receive request!");
+ break;
+ }
+ };
+ let rsp_data = match req_data[0] {
+ AG_MESSAGE_PREFIX => ag_ta.process(&req_data[1..]),
+ SK_MESSAGE_PREFIX => {
+ // It's safe to `borrow_mut()` because this code is not a callback
+ // from AuthGraph (the only other holder of an `Rc`), and so there
+ // can be no live `borrow()`s in this (single) thread.
+ sk_ta.borrow_mut().process(&req_data[1..])
+ }
+ prefix => panic!("unexpected messageprefix {prefix}!"),
+ };
+ match out_tx.send(rsp_data) {
+ Ok(_) => {}
+ Err(_) => {
+ error!("local TA failed to send out response");
+ break;
+ }
+ }
+ }
+ error!("local TA terminating!");
+ });
+ Self { in_tx, out_rx }
+ }
+
+ fn execute_for(&mut self, prefix: u8, req_data: &[u8]) -> Vec<u8> {
+ let mut prefixed_req = Vec::with_capacity(req_data.len() + 1);
+ prefixed_req.push(prefix);
+ prefixed_req.extend_from_slice(req_data);
+ self.in_tx
+ .send(prefixed_req)
+ .expect("failed to send in request");
+ self.out_rx.recv().expect("failed to receive response")
+ }
+}
+
+pub struct AuthGraphChannel(pub Arc<Mutex<LocalTa>>);
+
+impl SerializedChannel for AuthGraphChannel {
+ const MAX_SIZE: usize = usize::MAX;
+ fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
+ Ok(self
+ .0
+ .lock()
+ .unwrap()
+ .execute_for(AG_MESSAGE_PREFIX, req_data))
+ }
+}
+
+pub struct SecretkeeperChannel(pub Arc<Mutex<LocalTa>>);
+
+impl SerializedChannel for SecretkeeperChannel {
+ const MAX_SIZE: usize = usize::MAX;
+ fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
+ Ok(self
+ .0
+ .lock()
+ .unwrap()
+ .execute_for(SK_MESSAGE_PREFIX, req_data))
+ }
+}
diff --git a/security/secretkeeper/default/src/main.rs b/security/secretkeeper/default/src/main.rs
index a291017..436f9a7 100644
--- a/security/secretkeeper/default/src/main.rs
+++ b/security/secretkeeper/default/src/main.rs
@@ -17,105 +17,12 @@
//! Non-secure implementation of the Secretkeeper HAL.
use log::{error, info, Level};
-use std::sync::{Arc, Mutex};
-use authgraph_boringssl as boring;
-use authgraph_core::ta::{Role, AuthGraphTa};
-use authgraph_core::keyexchange::{MAX_OPENED_SESSIONS, AuthGraphParticipant};
-use secretkeeper_core::ta::SecretkeeperTa;
use secretkeeper_hal::SecretkeeperService;
-use authgraph_hal::channel::SerializedChannel;
+use secretkeeper_nonsecure::{AuthGraphChannel, SecretkeeperChannel, LocalTa};
+use std::sync::{Arc, Mutex};
use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::{
- ISecretkeeper, BpSecretkeeper,
+ BpSecretkeeper, ISecretkeeper,
};
-use std::cell::RefCell;
-use std::rc::Rc;
-use std::sync::mpsc;
-
-/// Implementation of the Secrekeeper TA that runs locally in-process (and which is therefore
-/// insecure).
-pub struct LocalTa {
- in_tx: mpsc::Sender<Vec<u8>>,
- out_rx: mpsc::Receiver<Vec<u8>>,
-}
-
-/// Prefix byte for messages intended for the AuthGraph TA.
-const AG_MESSAGE_PREFIX: u8 = 0x00;
-/// Prefix byte for messages intended for the Secretkeeper TA.
-const SK_MESSAGE_PREFIX: u8 = 0x01;
-
-impl LocalTa {
- /// Create a new instance.
- pub fn new() -> Self {
- // Create a pair of channels to communicate with the TA thread.
- let (in_tx, in_rx) = mpsc::channel();
- let (out_tx, out_rx) = mpsc::channel();
-
- // The TA code expects to run single threaded, so spawn a thread to run it in.
- std::thread::spawn(move || {
- let mut crypto_impls = boring::crypto_trait_impls();
- let sk_ta = Rc::new(RefCell::new(
- SecretkeeperTa::new(&mut crypto_impls)
- .expect("Failed to create local Secretkeeper TA"),
- ));
- let mut ag_ta = AuthGraphTa::new(
- AuthGraphParticipant::new(crypto_impls, sk_ta.clone(), MAX_OPENED_SESSIONS)
- .expect("Failed to create local AuthGraph TA"),
- Role::Sink,
- );
-
- // Loop forever processing request messages.
- loop {
- let req_data: Vec<u8> = in_rx.recv().expect("failed to receive next req");
- let rsp_data = match req_data[0] {
- AG_MESSAGE_PREFIX => ag_ta.process(&req_data[1..]),
- SK_MESSAGE_PREFIX => {
- // It's safe to `borrow_mut()` because this code is not a callback
- // from AuthGraph (the only other holder of an `Rc`), and so there
- // can be no live `borrow()`s in this (single) thread.
- sk_ta.borrow_mut().process(&req_data[1..])
- }
- prefix => panic!("unexpected messageprefix {prefix}!"),
- };
- out_tx.send(rsp_data).expect("failed to send out rsp");
- }
- });
- Self { in_tx, out_rx }
- }
-
- fn execute_for(&mut self, prefix: u8, req_data: &[u8]) -> Vec<u8> {
- let mut prefixed_req = Vec::with_capacity(req_data.len() + 1);
- prefixed_req.push(prefix);
- prefixed_req.extend_from_slice(req_data);
- self.in_tx
- .send(prefixed_req)
- .expect("failed to send in request");
- self.out_rx.recv().expect("failed to receive response")
- }
-}
-
-pub struct AuthGraphChannel(Arc<Mutex<LocalTa>>);
-impl SerializedChannel for AuthGraphChannel {
- const MAX_SIZE: usize = usize::MAX;
- fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
- Ok(self
- .0
- .lock()
- .unwrap()
- .execute_for(AG_MESSAGE_PREFIX, req_data))
- }
-}
-
-pub struct SecretkeeperChannel(Arc<Mutex<LocalTa>>);
-impl SerializedChannel for SecretkeeperChannel {
- const MAX_SIZE: usize = usize::MAX;
- fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
- Ok(self
- .0
- .lock()
- .unwrap()
- .execute_for(SK_MESSAGE_PREFIX, req_data))
- }
-}
fn main() {
// Initialize Android logging.
diff --git a/security/secretkeeper/default/src/store.rs b/security/secretkeeper/default/src/store.rs
new file mode 100644
index 0000000..6c7dba1
--- /dev/null
+++ b/security/secretkeeper/default/src/store.rs
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! In-memory store for nonsecure Secretkeeper.
+
+use secretkeeper_comm::data_types::error::Error;
+use secretkeeper_core::store::KeyValueStore;
+use std::collections::HashMap;
+
+/// An in-memory implementation of [`KeyValueStore`]. Please note that this is entirely for testing
+/// purposes. Refer to the documentation of `PolicyGatedStorage` and Secretkeeper HAL for
+/// persistence requirements.
+#[derive(Default)]
+pub struct InMemoryStore(HashMap<Vec<u8>, Vec<u8>>);
+impl KeyValueStore for InMemoryStore {
+ fn store(&mut self, key: &[u8], val: &[u8]) -> Result<(), Error> {
+ // This will overwrite the value if key is already present.
+ let _ = self.0.insert(key.to_vec(), val.to_vec());
+ Ok(())
+ }
+
+ fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Error> {
+ let optional_val = self.0.get(key);
+ Ok(optional_val.cloned())
+ }
+
+ fn delete(&mut self, key: &[u8]) -> Result<(), Error> {
+ self.0.remove(key);
+ Ok(())
+ }
+
+ fn delete_all(&mut self) -> Result<(), Error> {
+ self.0.clear();
+ Ok(())
+ }
+}
diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp
index 08ee773..e93c391 100644
--- a/sensors/aidl/default/Android.bp
+++ b/sensors/aidl/default/Android.bp
@@ -97,12 +97,5 @@
prebuilts: [
"sensors-default.rc", // init rc
"sensors-default.xml", // vintf fragment
- "android.hardware.sensor.ambient_temperature.prebuilt.xml",
- "android.hardware.sensor.barometer.prebuilt.xml",
- "android.hardware.sensor.gyroscope.prebuilt.xml",
- "android.hardware.sensor.hinge_angle.prebuilt.xml",
- "android.hardware.sensor.light.prebuilt.xml",
- "android.hardware.sensor.proximity.prebuilt.xml",
- "android.hardware.sensor.relative_humidity.prebuilt.xml",
],
}
diff --git a/sensors/aidl/default/multihal/Android.bp b/sensors/aidl/default/multihal/Android.bp
index a20d6d7..40cb2d9 100644
--- a/sensors/aidl/default/multihal/Android.bp
+++ b/sensors/aidl/default/multihal/Android.bp
@@ -45,11 +45,6 @@
"HalProxyAidl.cpp",
"ConvertUtils.cpp",
],
- visibility: [
- ":__subpackages__",
- "//hardware/interfaces/sensors/aidl/multihal:__subpackages__",
- "//hardware/interfaces/tests/extension/sensors:__subpackages__",
- ],
static_libs: [
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.X-multihal",
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
index dff3c4c..7e1aed7 100644
--- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
@@ -38,4 +38,7 @@
android.hardware.thermal.CoolingType type;
String name;
long value;
+ long powerLimitMw;
+ long powerMw;
+ long timeWindowMs;
}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl
new file mode 100644
index 0000000..ea75b1c
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+/* @hide */
+@VintfStability
+interface ICoolingDeviceChangedCallback {
+ oneway void notifyCoolingDeviceChanged(in android.hardware.thermal.CoolingDevice coolingDevice);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
index c9b6cab..904496c 100644
--- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
@@ -44,4 +44,6 @@
void registerThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
void registerThermalChangedCallbackWithType(in android.hardware.thermal.IThermalChangedCallback callback, in android.hardware.thermal.TemperatureType type);
void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+ void registerCoolingDeviceChangedCallbackWithType(in android.hardware.thermal.ICoolingDeviceChangedCallback callback, in android.hardware.thermal.CoolingType type);
+ void unregisterCoolingDeviceChangedCallback(in android.hardware.thermal.ICoolingDeviceChangedCallback callback);
}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
index 0c5c17d..406733b 100644
--- a/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
+++ b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
@@ -40,4 +40,16 @@
* means deeper throttling.
*/
long value;
+ /**
+ * Power budget (mW) of the cooling device.
+ */
+ long powerLimitMw;
+ /**
+ * Target cooling device's AVG power for the last time_window_ms.
+ */
+ long powerMw;
+ /**
+ * The time window (millisecond) to calculate the power consumption
+ */
+ long timeWindowMs;
}
diff --git a/thermal/aidl/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl
new file mode 100644
index 0000000..e6bb9fe
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/ICoolingDeviceChangedCallback.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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.thermal;
+
+import android.hardware.thermal.CoolingDevice;
+import android.hardware.thermal.Temperature;
+
+/**
+ * ICoolingDeviceChangedCallback send cooling device change notification to clients.
+ * @hide
+ */
+@VintfStability
+interface ICoolingDeviceChangedCallback {
+ /**
+ * Send a cooling device change event to all ThermalHAL
+ * cooling device event listeners.
+ *
+ * @param cooling_device The cooling device information associated with the
+ * change event.
+ */
+ oneway void notifyCoolingDeviceChanged(in CoolingDevice coolingDevice);
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl
index c94edcd..4aa4090 100644
--- a/thermal/aidl/android/hardware/thermal/IThermal.aidl
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -18,6 +18,7 @@
import android.hardware.thermal.CoolingDevice;
import android.hardware.thermal.CoolingType;
+import android.hardware.thermal.ICoolingDeviceChangedCallback;
import android.hardware.thermal.IThermalChangedCallback;
import android.hardware.thermal.Temperature;
import android.hardware.thermal.TemperatureThreshold;
@@ -188,4 +189,40 @@
* getMessage() must be populated with human-readable error message.
*/
void unregisterThermalChangedCallback(in IThermalChangedCallback callback);
+
+ /**
+ * Register an ICoolingDeviceChangedCallback for a given CoolingType, used by
+ * the Thermal HAL to receive CDEV events when cooling device status
+ * changed.
+ * Multiple registrations with different ICoolingDeviceChangedCallback must be allowed.
+ * Multiple registrations with same ICoolingDeviceChangedCallback is not allowed, client
+ * should unregister the given ICoolingDeviceChangedCallback first.
+ *
+ * @param callback the ICoolingChangedCallback to use for receiving
+ * cooling device events. If nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ * @param type the type to be filtered.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT If the callback is given nullptr or already registered. And the
+ * getMessage() must be populated with human-readable error message.
+ * @throws EX_ILLEGAL_STATE If the Thermal HAL is not initialized successfully. And the
+ * getMessage() must be populated with human-readable error message.
+ */
+ void registerCoolingDeviceChangedCallbackWithType(
+ in ICoolingDeviceChangedCallback callback, in CoolingType type);
+
+ /**
+ * Unregister an ICoolingDeviceChangedCallback, used by the Thermal HAL
+ * to receive CDEV events when cooling device status changed.
+ *
+ * @param callback the ICoolingDeviceChangedCallback to use for receiving
+ * cooling device events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT If the callback is given nullptr or not previously registered.
+ * And the getMessage() must be populated with human-readable error message.
+ * @throws EX_ILLEGAL_STATE If the Thermal HAL is not initialized successfully. And the
+ * getMessage() must be populated with human-readable error message.
+ */
+ void unregisterCoolingDeviceChangedCallback(in ICoolingDeviceChangedCallback callback);
}
diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp
index f643d22..41d0be8 100644
--- a/thermal/aidl/default/Thermal.cpp
+++ b/thermal/aidl/default/Thermal.cpp
@@ -142,4 +142,53 @@
return ScopedAStatus::ok();
}
+ScopedAStatus Thermal::registerCoolingDeviceChangedCallbackWithType(
+ const std::shared_ptr<ICoolingDeviceChangedCallback>& in_callback, CoolingType in_type) {
+ LOG(VERBOSE) << __func__ << " ICoolingDeviceChangedCallback: " << in_callback
+ << ", CoolingType: " << static_cast<int32_t>(in_type);
+ if (in_callback == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid nullptr callback");
+ }
+ {
+ std::lock_guard<std::mutex> _lock(cdev_callback_mutex_);
+ if (std::any_of(cdev_callbacks_.begin(), cdev_callbacks_.end(),
+ [&](const std::shared_ptr<ICoolingDeviceChangedCallback>& c) {
+ return interfacesEqual(c, in_callback);
+ })) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Callback already registered");
+ }
+ cdev_callbacks_.push_back(in_callback);
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::unregisterCoolingDeviceChangedCallback(
+ const std::shared_ptr<ICoolingDeviceChangedCallback>& in_callback) {
+ LOG(VERBOSE) << __func__ << " ICoolingDeviceChangedCallback: " << in_callback;
+ if (in_callback == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid nullptr callback");
+ }
+ {
+ std::lock_guard<std::mutex> _lock(cdev_callback_mutex_);
+ bool removed = false;
+ cdev_callbacks_.erase(
+ std::remove_if(cdev_callbacks_.begin(), cdev_callbacks_.end(),
+ [&](const std::shared_ptr<ICoolingDeviceChangedCallback>& c) {
+ if (interfacesEqual(c, in_callback)) {
+ removed = true;
+ return true;
+ }
+ return false;
+ }),
+ cdev_callbacks_.end());
+ if (!removed) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Callback wasn't registered");
+ }
+ }
+ return ScopedAStatus::ok();
+}
} // namespace aidl::android::hardware::thermal::impl::example
diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h
index 8885e63..d3d8874 100644
--- a/thermal/aidl/default/Thermal.h
+++ b/thermal/aidl/default/Thermal.h
@@ -46,6 +46,7 @@
ndk::ScopedAStatus registerThermalChangedCallback(
const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+
ndk::ScopedAStatus registerThermalChangedCallbackWithType(
const std::shared_ptr<IThermalChangedCallback>& in_callback,
TemperatureType in_type) override;
@@ -53,9 +54,18 @@
ndk::ScopedAStatus unregisterThermalChangedCallback(
const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+ ndk::ScopedAStatus registerCoolingDeviceChangedCallbackWithType(
+ const std::shared_ptr<ICoolingDeviceChangedCallback>& in_callback,
+ CoolingType in_type) override;
+
+ ndk::ScopedAStatus unregisterCoolingDeviceChangedCallback(
+ const std::shared_ptr<ICoolingDeviceChangedCallback>& in_callback) override;
+
private:
std::mutex thermal_callback_mutex_;
std::vector<std::shared_ptr<IThermalChangedCallback>> thermal_callbacks_;
+ std::mutex cdev_callback_mutex_;
+ std::vector<std::shared_ptr<ICoolingDeviceChangedCallback>> cdev_callbacks_;
};
} // namespace example
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 4b0eb65..403c6c8 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -26,6 +26,7 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/thermal/BnCoolingDeviceChangedCallback.h>
#include <aidl/android/hardware/thermal/BnThermal.h>
#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
#include <android-base/logging.h>
@@ -59,6 +60,15 @@
.throttlingStatus = ThrottlingSeverity::CRITICAL,
};
+static const CoolingDevice kCoolingDevice = {
+ .type = CoolingType::CPU,
+ .name = "test cooling device",
+ .value = 1,
+ .powerLimitMw = 300,
+ .powerMw = 500,
+ .timeWindowMs = 7000,
+};
+
// Callback class for receiving thermal event notifications from main class
class ThermalCallback : public BnThermalChangedCallback {
public:
@@ -85,6 +95,33 @@
bool mInvoke = false;
};
+// Callback class for receiving cooling device event notifications from main class
+class CoolingDeviceCallback : public BnCoolingDeviceChangedCallback {
+ public:
+ ndk::ScopedAStatus notifyCoolingDeviceChanged(const CoolingDevice&) override {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mInvoke = true;
+ }
+ mNotifyCoolingDeviceChanged.notify_all();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ template <typename R, typename P>
+ [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ bool r = mNotifyCoolingDeviceChanged.wait_for(lock, duration,
+ [this] { return this->mInvoke; });
+ mInvoke = false;
+ return r;
+ }
+
+ private:
+ std::mutex mMutex;
+ std::condition_variable mNotifyCoolingDeviceChanged;
+ bool mInvoke = false;
+};
+
// The main test class for THERMAL HIDL HAL.
class ThermalAidlTest : public testing::TestWithParam<std::string> {
public:
@@ -97,19 +134,42 @@
ASSERT_NE(mThermalCallback, nullptr);
::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto ret = mThermal->getInterfaceVersion(&thermal_version);
+ ASSERT_TRUE(ret.isOk()) << ret;
+ if (thermal_version > 1) {
+ mCoolingDeviceCallback = ndk::SharedRefBase::make<CoolingDeviceCallback>();
+ ASSERT_NE(mCoolingDeviceCallback, nullptr);
+ status = mThermal->registerCoolingDeviceChangedCallbackWithType(mCoolingDeviceCallback,
+ kCoolingDevice.type);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+ }
}
void TearDown() override {
::ndk::ScopedAStatus status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
ASSERT_TRUE(status.isOk()) << status.getMessage();
+
// Expect to fail if unregister again
status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+
+ auto ret = mThermal->getInterfaceVersion(&thermal_version);
+ ASSERT_TRUE(ret.isOk()) << ret;
+ if (thermal_version > 1) {
+ status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+ status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
+ ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+ }
}
+ // Stores thermal version
+ int32_t thermal_version;
protected:
std::shared_ptr<IThermal> mThermal;
std::shared_ptr<ThermalCallback> mThermalCallback;
+ std::shared_ptr<CoolingDeviceCallback> mCoolingDeviceCallback;
};
// Test ThermalChangedCallback::notifyThrottling().
@@ -121,6 +181,21 @@
ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
}
+// Test CoolingDeviceChangedCallback::notifyCoolingDeviceChanged().
+// This just calls into and back from our local CoolingDeviceChangedCallback impl.
+TEST_P(ThermalAidlTest, NotifyCoolingDeviceChangedTest) {
+ auto ret = mThermal->getInterfaceVersion(&thermal_version);
+ ASSERT_TRUE(ret.isOk()) << ret;
+ if (thermal_version < 2) {
+ return;
+ }
+ std::shared_ptr<CoolingDeviceCallback> cdevCallback =
+ ndk::SharedRefBase::make<CoolingDeviceCallback>();
+ ::ndk::ScopedAStatus status = cdevCallback->notifyCoolingDeviceChanged(kCoolingDevice);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+ ASSERT_TRUE(cdevCallback->waitForCallback(200ms));
+}
+
// Test Thermal->registerThermalChangedCallback.
TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackTest) {
// Expect to fail with same callback
@@ -169,6 +244,37 @@
|| status.getExceptionCode() == EX_NULL_POINTER);
}
+// Test Thermal->registerCoolingDeviceChangedCallbackWithType.
+TEST_P(ThermalAidlTest, RegisterCoolingDeviceChangedCallbackWithTypeTest) {
+ auto ret = mThermal->getInterfaceVersion(&thermal_version);
+ ASSERT_TRUE(ret.isOk()) << ret;
+ if (thermal_version < 2) {
+ return;
+ }
+
+ // Expect to fail with same callback
+ ::ndk::ScopedAStatus status = mThermal->registerCoolingDeviceChangedCallbackWithType(
+ mCoolingDeviceCallback, CoolingType::CPU);
+ ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+ // Expect to fail with null callback
+ status = mThermal->registerCoolingDeviceChangedCallbackWithType(nullptr, CoolingType::CPU);
+ ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
+ status.getExceptionCode() == EX_NULL_POINTER);
+ std::shared_ptr<CoolingDeviceCallback> localCoolingDeviceCallback =
+ ndk::SharedRefBase::make<CoolingDeviceCallback>();
+ // Expect to succeed with different callback
+ status = mThermal->registerCoolingDeviceChangedCallbackWithType(localCoolingDeviceCallback,
+ CoolingType::CPU);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+ // Remove the local callback
+ status = mThermal->unregisterCoolingDeviceChangedCallback(localCoolingDeviceCallback);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+ // Expect to fail with null callback
+ status = mThermal->unregisterCoolingDeviceChangedCallback(nullptr);
+ ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
+ status.getExceptionCode() == EX_NULL_POINTER);
+}
+
// Test Thermal->getCurrentTemperatures().
TEST_P(ThermalAidlTest, TemperatureTest) {
std::vector<Temperature> ret;
diff --git a/tv/hdmi/connection/aidl/default/HdmiConnectionMock.cpp b/tv/hdmi/connection/aidl/default/HdmiConnectionMock.cpp
index 8f4411b..954982e 100644
--- a/tv/hdmi/connection/aidl/default/HdmiConnectionMock.cpp
+++ b/tv/hdmi/connection/aidl/default/HdmiConnectionMock.cpp
@@ -15,12 +15,11 @@
*/
#define LOG_TAG "android.hardware.tv.hdmi.connection"
+#include "HdmiConnectionMock.h"
#include <android-base/logging.h>
#include <fcntl.h>
#include <utils/Log.h>
-#include "HdmiConnectionMock.h"
-
using ndk::ScopedAStatus;
namespace android {
@@ -34,6 +33,7 @@
ALOGE("HdmiConnectionMock died");
auto hdmi = static_cast<HdmiConnectionMock*>(cookie);
hdmi->mHdmiThreadRun = false;
+ pthread_join(hdmi->mThreadId, NULL);
}
ScopedAStatus HdmiConnectionMock::getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) {
@@ -55,12 +55,15 @@
ScopedAStatus HdmiConnectionMock::setCallback(
const std::shared_ptr<IHdmiConnectionCallback>& callback) {
if (mCallback != nullptr) {
+ stopThread();
mCallback = nullptr;
}
-
if (callback != nullptr) {
mCallback = callback;
- AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+ mDeathRecipient =
+ ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+
+ AIBinder_linkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this /* cookie */);
mInputFile = open(HDMI_MSG_IN_FIFO, O_RDWR | O_CLOEXEC);
pthread_create(&mThreadId, NULL, __threadLoop, this);
@@ -153,7 +156,7 @@
int r = -1;
// Open the input pipe
- while (mInputFile < 0) {
+ while (mHdmiThreadRun && mInputFile < 0) {
usleep(1000 * 1000);
mInputFile = open(HDMI_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC);
}
@@ -193,7 +196,21 @@
.physicalAddress = mPhysicalAddress};
mPortConnectionStatus[0] = false;
mHpdSignal[0] = HpdSignal::HDMI_HPD_PHYSICAL;
- mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(nullptr);
+}
+
+void HdmiConnectionMock::stopThread() {
+ if (mCallback != nullptr) {
+ ALOGE("[halimp_aidl] HdmiConnectionMock shutting down.");
+ mCallback = nullptr;
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(nullptr);
+ mHdmiThreadRun = false;
+ pthread_join(mThreadId, NULL);
+ }
+}
+
+HdmiConnectionMock::~HdmiConnectionMock() {
+ stopThread();
}
} // namespace implementation
diff --git a/tv/hdmi/connection/aidl/default/HdmiConnectionMock.h b/tv/hdmi/connection/aidl/default/HdmiConnectionMock.h
index c013fdd..8c66f08 100644
--- a/tv/hdmi/connection/aidl/default/HdmiConnectionMock.h
+++ b/tv/hdmi/connection/aidl/default/HdmiConnectionMock.h
@@ -41,7 +41,7 @@
struct HdmiConnectionMock : public BnHdmiConnection {
HdmiConnectionMock();
-
+ ~HdmiConnectionMock();
::ndk::ScopedAStatus getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) override;
::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override;
::ndk::ScopedAStatus setCallback(
@@ -56,6 +56,7 @@
void threadLoop();
int readMessageFromFifo(unsigned char* buf, int msgCount);
void handleHotplugMessage(unsigned char* msgBuf);
+ void stopThread();
private:
static void serviceDied(void* cookie);
diff --git a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
index 746ae1e..7e095f1 100644
--- a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
+++ b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "tv_input_aidl_hal_test"
+
#include "VtsHalTvInputTargetTest.h"
#include <android-base/properties.h>
@@ -181,7 +183,9 @@
ALOGD("OpenAndCloseStreamTest: open stream, device_id=%d, stream_id=%d", device_id,
stream_id);
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
- ASSERT_TRUE(isValidHandle(handle));
+ if (VERIFY_SIDEBAND_STREAM_HANDLE) {
+ ASSERT_TRUE(isValidHandle(handle));
+ }
ALOGD("OpenAndCloseStreamTest: close stream, device_id=%d, stream_id=%d", device_id,
stream_id);
@@ -283,7 +287,9 @@
ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
- ASSERT_TRUE(isValidHandle(handle));
+ if (VERIFY_SIDEBAND_STREAM_HANDLE) {
+ ASSERT_TRUE(isValidHandle(handle));
+ }
ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).getServiceSpecificError() ==
diff --git a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
index 7e66a88..fd98a18 100644
--- a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
+++ b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.h
@@ -43,6 +43,7 @@
#define WAIT_FOR_EVENT_TIMEOUT 5
#define DEFAULT_ID INT32_MIN
+#define VERIFY_SIDEBAND_STREAM_HANDLE 1
namespace VtsHalTvInputTargetTest {
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index fccd2ed..3d60e89 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -35,6 +35,7 @@
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type,
filterConf.config1_0.bufferSize));
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
index 513007b..09e63fc 100644
--- a/tv/tuner/aidl/vts/functional/Android.bp
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -37,6 +37,7 @@
"FrontendTests.cpp",
"LnbTests.cpp",
"VtsHalTvTunerTargetTest.cpp",
+ "utils/IpStreamer.cpp",
],
generated_headers: [
"tuner_testing_dynamic_configuration_V1_0_enums",
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index b0f614e..b7b0185 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -475,6 +475,10 @@
<< "FrontendConfig does not match the frontend info of the given id.";
mIsSoftwareFe = config.isSoftwareFe;
+ std::unique_ptr<IpStreamer> ipThread = std::make_unique<IpStreamer>();
+ if (config.type == FrontendType::IPTV) {
+ ipThread->startIpStream();
+ }
if (mIsSoftwareFe && testWithDemux) {
if (getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) != success()) {
ALOGW("[vts] Software frontend dvr configure openDvr failed.");
@@ -494,6 +498,9 @@
getDvrTests()->startDvrPlayback();
}
mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
+ if (config.type == FrontendType::IPTV) {
+ ipThread->stopIpStream();
+ }
return AssertionResult(true);
}
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.h b/tv/tuner/aidl/vts/functional/FrontendTests.h
index 1746c8e..9c2ffc0 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.h
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.h
@@ -27,6 +27,7 @@
#include "DvrTests.h"
#include "VtsHalTvTunerTestConfigurations.h"
+#include "utils/IpStreamer.h"
#define WAIT_TIMEOUT 3000000000
#define INVALID_ID -1
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 3664b6c..671d079 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -48,6 +48,7 @@
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
@@ -683,6 +684,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
@@ -779,6 +784,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
// TODO use parameterized tests
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
@@ -793,6 +802,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
@@ -808,6 +821,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
// TODO use parameterized tests
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
@@ -1111,6 +1128,10 @@
if (!record.support) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto record_configs = generateRecordConfigurations();
for (auto& configuration : record_configs) {
record = configuration;
@@ -1125,6 +1146,10 @@
if (!record.support) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto record_configs = generateRecordConfigurations();
for (auto& configuration : record_configs) {
record = configuration;
@@ -1157,6 +1182,10 @@
if (!record.support) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto record_configs = generateRecordConfigurations();
for (auto& configuration : record_configs) {
record = configuration;
@@ -1194,9 +1223,17 @@
if (!scan.hasFrontendConnection) {
return;
}
+ // Blind scan is not applicable for IPTV frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
vector<ScanHardwareConnections> scan_configs = generateScanConfigurations();
for (auto& configuration : scan_configs) {
scan = configuration;
+ // Skip test if the frontend implementation doesn't support blind scan
+ if (!frontendMap[scan.frontendId].supportBlindScan) {
+ continue;
+ }
mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
}
}
@@ -1218,9 +1255,17 @@
if (!scan.hasFrontendConnection) {
return;
}
+ // Blind scan is not application for IPTV frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
vector<ScanHardwareConnections> scan_configs = generateScanConfigurations();
for (auto& configuration : scan_configs) {
scan = configuration;
+ // Skip test if the frontend implementation doesn't support blind scan
+ if (!frontendMap[scan.frontendId].supportBlindScan) {
+ continue;
+ }
mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
}
}
@@ -1242,6 +1287,10 @@
TEST_P(TunerFrontendAidlTest, getHardwareInfo) {
description("Test Frontend get hardware info");
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
if (!live.hasFrontendConnection) {
return;
}
@@ -1289,6 +1338,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
@@ -1316,6 +1369,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
@@ -1345,6 +1402,10 @@
if (!live.hasFrontendConnection) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
@@ -1358,6 +1419,10 @@
if (!descrambling.support) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
vector<DescramblingHardwareConnections> descrambling_configs =
generateDescramblingConfigurations();
if (descrambling_configs.empty()) {
@@ -1394,6 +1459,10 @@
if (!descrambling.support) {
return;
}
+ // Do not execute tests for IPTV Frontend
+ if (frontendMap[live.frontendId].type == FrontendType::IPTV) {
+ return;
+ }
vector<DescramblingHardwareConnections> descrambling_configs =
generateDescramblingConfigurations();
if (descrambling_configs.empty()) {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
index 516cb62..5c13ed0 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -612,6 +612,7 @@
frontendMap[defaultFeId].isSoftwareFe = true;
frontendMap[defaultFeId].canConnectToCiCam = true;
frontendMap[defaultFeId].ciCamId = 0;
+ frontendMap[defaultFeId].supportBlindScan = true;
FrontendDvbtSettings dvbt;
dvbt.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K_E;
frontendMap[defaultFeId].settings.set<FrontendSettings::Tag::dvbt>(dvbt);
diff --git a/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp b/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp
new file mode 100644
index 0000000..02b2633
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp
@@ -0,0 +1,57 @@
+#include "IpStreamer.h"
+
+IpStreamer::IpStreamer() {}
+
+IpStreamer::~IpStreamer() {}
+
+void IpStreamer::startIpStream() {
+ ALOGI("Starting IP Stream thread");
+ mFp = fopen(mFilePath.c_str(), "rb");
+ if (mFp == nullptr) {
+ ALOGE("Failed to open file at path: %s", mFilePath.c_str());
+ return;
+ }
+ mIpStreamerThread = std::thread(&IpStreamer::ipStreamThreadLoop, this, mFp);
+}
+
+void IpStreamer::stopIpStream() {
+ ALOGI("Stopping IP Stream thread");
+ close(mSockfd);
+ if (mFp != nullptr) fclose(mFp);
+ if (mIpStreamerThread.joinable()) {
+ mIpStreamerThread.join();
+ }
+}
+
+void IpStreamer::ipStreamThreadLoop(FILE* fp) {
+ mSockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (mSockfd < 0) {
+ ALOGE("IpStreamer::ipStreamThreadLoop: Socket creation failed (%s)", strerror(errno));
+ exit(1);
+ }
+
+ if (mFp == NULL) {
+ ALOGE("IpStreamer::ipStreamThreadLoop: Cannot open file %s: (%s)", mFilePath.c_str(),
+ strerror(errno));
+ exit(1);
+ }
+
+ struct sockaddr_in destaddr;
+ memset(&destaddr, 0, sizeof(destaddr));
+ destaddr.sin_family = mIsIpV4 ? AF_INET : AF_INET6;
+ destaddr.sin_port = htons(mPort);
+ destaddr.sin_addr.s_addr = inet_addr(mIpAddress.c_str());
+
+ char buf[mBufferSize];
+ int n;
+ while (1) {
+ if (fp == nullptr) break;
+ n = fread(buf, 1, mBufferSize, fp);
+ ALOGI("IpStreamer::ipStreamThreadLoop: Bytes read from fread(): %d\n", n);
+ if (n <= 0) {
+ break;
+ }
+ sendto(mSockfd, buf, n, 0, (struct sockaddr*)&destaddr, sizeof(destaddr));
+ sleep(mSleepTime);
+ }
+}
diff --git a/tv/tuner/aidl/vts/functional/utils/IpStreamer.h b/tv/tuner/aidl/vts/functional/utils/IpStreamer.h
new file mode 100644
index 0000000..d073003
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/utils/IpStreamer.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <log/log.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string>
+#include <thread>
+
+/**
+ * IP Streamer class to send TS data to a specified socket for testing IPTV frontend functions
+ * e.g. tuning and playback.
+ */
+
+class IpStreamer {
+ public:
+ // Constructor for IP Streamer object
+ IpStreamer();
+
+ // Destructor for IP Streamer object
+ ~IpStreamer();
+
+ // Starts a thread to read data from a socket
+ void startIpStream();
+
+ // Stops the reading thread started by startIpStream
+ void stopIpStream();
+
+ // Thread function that consumes data from a socket
+ void ipStreamThreadLoop(FILE* fp);
+
+ std::string getFilePath() { return mFilePath; };
+
+ private:
+ int mSockfd = -1;
+ FILE* mFp;
+ bool mIsIpV4 = true; // By default, set to IPV4
+ int mPort = 12345; // default port
+ int mBufferSize = 188; // bytes
+ int mSleepTime = 1; // second
+ std::string mIpAddress = "127.0.0.1"; // default IP address
+ std::string mFilePath = "/data/local/tmp/segment000000.ts"; // default path for TS file
+ std::thread mIpStreamerThread;
+};
\ No newline at end of file
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
index 9517520..5ffb38f 100644
--- a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -114,6 +114,7 @@
FrontendSettings settings;
vector<FrontendStatusType> tuneStatusTypes;
vector<FrontendStatus> expectTuneStatuses;
+ bool supportBlindScan;
};
struct FilterConfig {
@@ -354,6 +355,11 @@
} else {
hasHwFe = true;
}
+ if (feConfig.hasSupportBlindScan()) {
+ frontendMap[id].supportBlindScan = feConfig.getSupportBlindScan();
+ } else {
+ frontendMap[id].supportBlindScan = true;
+ }
// TODO: b/182519645 complete the tune status config
frontendMap[id].tuneStatusTypes = types;
frontendMap[id].expectTuneStatuses = statuses;
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index dbd3486..ff2df90 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -369,6 +369,7 @@
method @Nullable public android.media.tuner.testing.configuration.V1_0.IsdbsFrontendSettings getIsdbsFrontendSettings_optional();
method @Nullable public android.media.tuner.testing.configuration.V1_0.IsdbtFrontendSettings getIsdbtFrontendSettings_optional();
method @Nullable public java.math.BigInteger getRemoveOutputPid();
+ method @Nullable public boolean getSupportBlindScan();
method @Nullable public android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum getType();
method public void setAtscFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AtscFrontendSettings);
method public void setConnectToCicamId(@Nullable java.math.BigInteger);
@@ -381,6 +382,7 @@
method public void setIsdbsFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IsdbsFrontendSettings);
method public void setIsdbtFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IsdbtFrontendSettings);
method public void setRemoveOutputPid(@Nullable java.math.BigInteger);
+ method public void setSupportBlindScan(@Nullable boolean);
method public void setType(@Nullable android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum);
}
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index c51ac51..eafaca9 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -162,6 +162,7 @@
<xs:attribute name="connectToCicamId" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="removeOutputPid" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="endFrequency" type="xs:nonNegativeInteger" use="optional"/>
+ <xs:attribute name="supportBlindScan" type="xs:boolean" use="optional"/>
</xs:complexType>
<!-- FILTER SESSION -->
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
index f9b79de..8af1678 100644
--- a/uwb/aidl/default/Android.bp
+++ b/uwb/aidl/default/Android.bp
@@ -24,6 +24,8 @@
"libtokio_util",
"libnix",
"libanyhow",
+ "libpdl_runtime",
+ "libuwb_uci_packets",
],
proc_macros: [
"libasync_trait",
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index efb2454..d1c3c67 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -16,6 +16,9 @@
use std::io::{self, Read, Write};
use std::os::unix::fs::OpenOptionsExt;
+use pdl_runtime::Packet;
+use uwb_uci_packets::{DeviceResetCmdBuilder, ResetConfig, UciControlPacket, UciControlPacketHal};
+
enum State {
Closed,
Opened {
@@ -46,11 +49,37 @@
impl State {
/// Terminate the reader task.
async fn close(&mut self) -> Result<()> {
- if let State::Opened { ref mut token, ref callbacks, ref mut death_recipient, ref mut handle, .. } = *self {
+ if let State::Opened {
+ ref mut token,
+ ref callbacks,
+ ref mut death_recipient,
+ ref mut handle,
+ ref mut serial,
+ } = *self
+ {
log::info!("waiting for task cancellation");
callbacks.as_binder().unlink_to_death(death_recipient)?;
token.cancel();
handle.await.unwrap();
+ let packet: UciControlPacket = DeviceResetCmdBuilder {
+ reset_config: ResetConfig::UwbsReset,
+ }
+ .build()
+ .into();
+ // DeviceResetCmd need to be send to reset the device to stop all running
+ // activities on UWBS.
+ let packet_vec: Vec<UciControlPacketHal> = packet.into();
+ for hal_packet in packet_vec.into_iter() {
+ serial
+ .write(&hal_packet.to_vec())
+ .map(|written| written as i32)
+ .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
+ }
+ consume_device_reset_rsp_and_ntf(
+ &mut serial
+ .try_clone()
+ .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?,
+ );
log::info!("task successfully cancelled");
callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
*self = State::Closed;
@@ -59,6 +88,20 @@
}
}
+fn consume_device_reset_rsp_and_ntf(reader: &mut File) {
+ // Poll the DeviceResetRsp and DeviceStatusNtf before hal is closed to prevent
+ // the host from getting response and notifications from a 'powered down' UWBS.
+ // Do nothing when these packets are received.
+ const DEVICE_RESET_RSP: [u8; 5] = [64, 0, 0, 1, 0];
+ const DEVICE_STATUS_NTF: [u8; 5] = [96, 1, 0, 1, 1];
+ let mut buffer = vec![0; DEVICE_RESET_RSP.len() + DEVICE_STATUS_NTF.len()];
+ read_exact(reader, &mut buffer).unwrap();
+
+ // Make sure received packets are the expected ones.
+ assert_eq!(&buffer[0..DEVICE_RESET_RSP.len()], &DEVICE_RESET_RSP);
+ assert_eq!(&buffer[DEVICE_RESET_RSP.len()..], &DEVICE_STATUS_NTF);
+}
+
pub fn makeraw(file: File) -> io::Result<File> {
// Configure the file descriptor as raw fd.
use nix::sys::termios::*;
@@ -209,7 +252,7 @@
let mut state = self.state.lock().await;
- if matches!(*state, State::Opened { .. }) {
+ if let State::Opened { .. } = *state {
state.close().await
} else {
Err(binder::ExceptionCode::ILLEGAL_STATE.into())
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
index bf4c2c0..ccb7876 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
@@ -62,6 +62,13 @@
void stopSendingKeepAlivePackets(in int cmdId);
void setDtimMultiplier(in int multiplier);
android.hardware.wifi.CachedScanData getCachedScanData();
+ android.hardware.wifi.TwtCapabilities twtGetCapabilities();
+ void twtSessionSetup(in int cmdId, in android.hardware.wifi.TwtRequest twtRequest);
+ void twtSessionUpdate(in int cmdId, in int sessionId, in android.hardware.wifi.TwtRequest twtRequest);
+ void twtSessionSuspend(in int cmdId, in int sessionId);
+ void twtSessionResume(in int cmdId, in int sessionId);
+ void twtSessionTeardown(in int cmdId, in int sessionId);
+ void twtSessionGetStats(in int cmdId, in int sessionId);
@Backing(type="int") @VintfStability
enum FeatureSetMask {
APF = (1 << 0) /* 1 */,
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
index 48b85b0..629ca3d 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
@@ -38,4 +38,31 @@
oneway void onBackgroundScanFailure(in int cmdId);
oneway void onBackgroundScanResults(in int cmdId, in android.hardware.wifi.StaScanData[] scanDatas);
oneway void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi);
+ oneway void onTwtFailure(in int cmdId, in android.hardware.wifi.IWifiStaIfaceEventCallback.TwtErrorCode error);
+ oneway void onTwtSessionCreate(in int cmdId, in android.hardware.wifi.TwtSession twtSession);
+ oneway void onTwtSessionUpdate(in int cmdId, in android.hardware.wifi.TwtSession twtSession);
+ oneway void onTwtSessionTeardown(in int cmdId, in int twtSessionId, in android.hardware.wifi.IWifiStaIfaceEventCallback.TwtTeardownReasonCode reasonCode);
+ oneway void onTwtSessionStats(in int cmdId, in int twtSessionId, in android.hardware.wifi.TwtSessionStats twtSessionStats);
+ oneway void onTwtSessionSuspend(in int cmdId, in int twtSessionId);
+ oneway void onTwtSessionResume(in int cmdId, in int twtSessionId);
+ @Backing(type="byte") @VintfStability
+ enum TwtErrorCode {
+ FAILURE_UNKNOWN,
+ ALREADY_RESUMED,
+ ALREADY_SUSPENDED,
+ INVALID_PARAMS,
+ MAX_SESSION_REACHED,
+ NOT_AVAILABLE,
+ NOT_SUPPORTED,
+ PEER_NOT_SUPPORTED,
+ PEER_REJECTED,
+ TIMEOUT,
+ }
+ @Backing(type="byte") @VintfStability
+ enum TwtTeardownReasonCode {
+ UNKNOWN,
+ LOCALLY_REQUESTED,
+ INTERNALLY_INITIATED,
+ PEER_INITIATED,
+ }
}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
index 56ef2d2..af1647d 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
@@ -42,9 +42,8 @@
android.hardware.wifi.RttPreamble preambleSupport;
android.hardware.wifi.RttBw bwSupport;
byte mcVersion;
- android.hardware.wifi.RttPreamble azPreambleSupport;
- android.hardware.wifi.RttBw azBwSupport;
+ int azPreambleSupport;
+ int azBwSupport;
boolean ntbInitiatorSupported;
boolean ntbResponderSupported;
- int maxTxLtfRepetitionCount;
}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
index b7830bd..b53ff9b 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
@@ -48,7 +48,6 @@
int burstDuration;
android.hardware.wifi.RttPreamble preamble;
android.hardware.wifi.RttBw bw;
- int ntbMinMeasurementTimeMillis;
- int ntbMaxMeasurementTimeMillis;
- int txLtfRepetitionCount;
+ long ntbMinMeasurementTime;
+ long ntbMaxMeasurementTime;
}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
index 30f5f58..9c6ad26 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
@@ -59,7 +59,8 @@
android.hardware.wifi.WifiInformationElement lcr;
int channelFreqMHz;
android.hardware.wifi.RttBw packetBw;
- int txLtfRepetitionCount;
- int ntbMinMeasurementTimeMillis;
- int ntbMaxMeasurementTimeMillis;
+ byte i2rTxLtfRepetitionCount;
+ byte r2iTxLtfRepetitionCount;
+ long ntbMinMeasurementTime;
+ long ntbMaxMeasurementTime;
}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl
new file mode 100644
index 0000000..75f3e83
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable TwtCapabilities {
+ boolean isTwtRequesterSupported;
+ boolean isTwtResponderSupported;
+ boolean isBroadcastTwtSupported;
+ boolean isFlexibleTwtScheduleSupported;
+ int minWakeDurationUs;
+ int maxWakeDurationUs;
+ long minWakeIntervalUs;
+ long maxWakeIntervalUs;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl
new file mode 100644
index 0000000..1e1c39a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable TwtRequest {
+ int mloLinkId;
+ int minWakeDurationUs;
+ int maxWakeDurationUs;
+ long minWakeIntervalUs;
+ long maxWakeIntervalUs;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl
new file mode 100644
index 0000000..0b88d8e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable TwtSession {
+ int sessionId;
+ int mloLinkId;
+ int wakeDurationUs;
+ long wakeIntervalUs;
+ android.hardware.wifi.TwtSession.TwtNegotiationType negotiationType;
+ boolean isTriggerEnabled;
+ boolean isAnnounced;
+ boolean isImplicit;
+ boolean isProtected;
+ boolean isUpdatable;
+ boolean isSuspendable;
+ boolean isResponderPmModeEnabled;
+ @Backing(type="byte") @VintfStability
+ enum TwtNegotiationType {
+ INDIVIDUAL = 0,
+ BROADCAST = 1,
+ }
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl
new file mode 100644
index 0000000..f62b614
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable TwtSessionStats {
+ int avgTxPktCount;
+ int avgRxPktCount;
+ int avgTxPktSize;
+ int avgRxPktSize;
+ int avgEospDurationUs;
+ int eospCount;
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
index 03b2217..6c5451b 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
@@ -25,6 +25,8 @@
import android.hardware.wifi.StaRoamingCapabilities;
import android.hardware.wifi.StaRoamingConfig;
import android.hardware.wifi.StaRoamingState;
+import android.hardware.wifi.TwtCapabilities;
+import android.hardware.wifi.TwtRequest;
import android.hardware.wifi.WifiBand;
import android.hardware.wifi.WifiDebugRxPacketFateReport;
import android.hardware.wifi.WifiDebugTxPacketFateReport;
@@ -573,4 +575,113 @@
* |WifiStatusCode.ERROR_UNKNOWN|
*/
CachedScanData getCachedScanData();
+
+ /**
+ * Get Target Wake Time (TWT) local device capabilities for the station interface.
+ *
+ * @return Instance of |TwtCapabilities|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ TwtCapabilities twtGetCapabilities();
+
+ /**
+ * Setup a Target Wake Time (TWT) session.
+ *
+ * Supported only if |TwtCapabilities.isTwtRequesterSupported| is set. Results in asynchronous
+ * callback |IWifiStaIfaceEventCallback.onTwtSessionCreate| on success or
+ * |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param twtRequest TWT Request parameters.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionSetup(in int cmdId, in TwtRequest twtRequest);
+
+ /**
+ * Update a Target Wake Time (TWT) session.
+ *
+ * Supported only if the TWT session can be updated. See |TwtSession.isUpdatable|. Results in
+ * asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionUpdate| on success or
+ * |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param sessionId TWT session id.
+ * @param twtRequest TWT Request parameters.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionUpdate(in int cmdId, in int sessionId, in TwtRequest twtRequest);
+
+ /**
+ * Suspend a Target Wake Time (TWT) session until a resume is called.
+ *
+ * Supported only if the TWT session supports suspend and resume. See
+ * |TwtSession.isSuspendable|. Results in asynchronous callback
+ * |IWifiStaIfaceEventCallback.onTwtSessionSuspend| on success or
+ * |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param sessionId TWT session id.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionSuspend(in int cmdId, in int sessionId);
+
+ /**
+ * Resume a Target Wake Time (TWT) session which is suspended.
+ *
+ * Supported only if the TWT session supports suspend and resume. See
+ * |TwtSession.isSuspendable|. Results in asynchronous callback
+ * |IWifiStaIfaceEventCallback.onTwtSessionResume| on success or
+ * |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param sessionId TWT session id.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionResume(in int cmdId, in int sessionId);
+
+ /**
+ * Teardown a Target Wake Time (TWT) session.
+ *
+ * Results in asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionTeardown| on
+ * success or |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param sessionId TWT session id.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionTeardown(in int cmdId, in int sessionId);
+
+ /**
+ * Get stats for a Target Wake Time (TWT) session.
+ *
+ * Results in asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionStats| on success
+ * or |IWifiStaIfaceEventCallback.onTwtFailure| on failure.
+ *
+ * @param cmdId Command Id to use for this invocation. The value 0 is reserved.
+ * @param sessionId TWT session id.
+ * @throws ServiceSpecificException with one of the following values:
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ void twtSessionGetStats(in int cmdId, in int sessionId);
}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
index 93a255f..dda7c77 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
@@ -18,6 +18,8 @@
import android.hardware.wifi.StaScanData;
import android.hardware.wifi.StaScanResult;
+import android.hardware.wifi.TwtSession;
+import android.hardware.wifi.TwtSessionStats;
@VintfStability
oneway interface IWifiStaIfaceEventCallback {
@@ -61,4 +63,104 @@
* @param currRssi RSSI of the currently connected access point.
*/
void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi);
+
+ @VintfStability
+ @Backing(type="byte")
+ enum TwtErrorCode {
+ /** Unknown failure */
+ FAILURE_UNKNOWN,
+ /** TWT session is already resumed */
+ ALREADY_RESUMED,
+ /** TWT session is already suspended */
+ ALREADY_SUSPENDED,
+ /** Invalid parameters */
+ INVALID_PARAMS,
+ /** Maximum number of sessions reached */
+ MAX_SESSION_REACHED,
+ /** Requested operation is not available */
+ NOT_AVAILABLE,
+ /** Requested operation is not supported */
+ NOT_SUPPORTED,
+ /** Requested operation is not supported by the peer */
+ PEER_NOT_SUPPORTED,
+ /** Requested operation is rejected by the peer */
+ PEER_REJECTED,
+ /** Requested operation is timed out */
+ TIMEOUT,
+ }
+
+ @VintfStability
+ @Backing(type="byte")
+ enum TwtTeardownReasonCode {
+ /** Unknown reason */
+ UNKNOWN,
+ /** Teardown requested by the framework */
+ LOCALLY_REQUESTED,
+ /** Teardown initiated internally by the firmware or driver */
+ INTERNALLY_INITIATED,
+ /** Teardown initiated by the peer */
+ PEER_INITIATED,
+ }
+
+ /**
+ * Called to indicate a TWT failure. If there is no command associated with this failure cmdId
+ * will be 0.
+ *
+ * @param cmdId Id used to identify the command. The value 0 indicates no associated command.
+ * @param error error code.
+ */
+ void onTwtFailure(in int cmdId, in TwtErrorCode error);
+
+ /**
+ * Called when a Target Wake Time session is created. See |IWifiStaIface.twtSessionSetup|.
+ *
+ * @param cmdId Id used to identify the command.
+ * @param twtSession TWT session.
+ */
+ void onTwtSessionCreate(in int cmdId, in TwtSession twtSession);
+
+ /**
+ * Called when a Target Wake Time session is updated. See |IWifiStaIface.twtSessionUpdate|.
+ *
+ * @param cmdId Id used to identify the command.
+ * @param twtSession TWT session.
+ */
+ void onTwtSessionUpdate(in int cmdId, in TwtSession twtSession);
+
+ /**
+ * Called when the Target Wake Time session is torndown.
+ * See |IWifiStaIface.twtSessionTeardown|.
+ *
+ * @param cmdId Id used to identify the command. The value 0 indicates no associated command.
+ * @param twtSessionId TWT session id.
+ * @param reasonCode reason code for the TWT teardown.
+ */
+ void onTwtSessionTeardown(
+ in int cmdId, in int twtSessionId, in TwtTeardownReasonCode reasonCode);
+
+ /**
+ * Called when TWT session stats available. See |IWifiStaIface.twtSessionGetStats|.
+ *
+ * @param cmdId Id used to identify the command.
+ * @param twtSessionId TWT session id.
+ * @param twtSessionStats TWT session stats.
+ */
+ void onTwtSessionStats(in int cmdId, in int twtSessionId, in TwtSessionStats twtSessionStats);
+
+ /**
+ * Called when the Target Wake Time session is suspended.
+ * See |IWifiStaIface.twtSessionSuspend|.
+ *
+ * @param cmdId Id used to identify the command. The value 0 indicates no associated command.
+ * @param twtSessionId TWT session id.
+ */
+ void onTwtSessionSuspend(in int cmdId, in int twtSessionId);
+
+ /**
+ * Called when the Target Wake Time session is resumed. See |IWifiStaIface.twtSessionResume|.
+ *
+ * @param cmdId Id used to identify the command. The value 0 indicates no associated command.
+ * @param twtSessionId TWT session id.
+ */
+ void onTwtSessionResume(in int cmdId, in int twtSessionId);
}
diff --git a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
index 0352ec8..89b70c9 100644
--- a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
@@ -64,12 +64,12 @@
* Bit mask indicating what preamble is supported by IEEE 802.11az initiator.
* Combination of |RttPreamble| values.
*/
- RttPreamble azPreambleSupport;
+ int azPreambleSupport;
/**
* Bit mask indicating what BW is supported by IEEE 802.11az initiator.
* Combination of |RttBw| values.
*/
- RttBw azBwSupport;
+ int azBwSupport;
/**
* Whether the initiator supports IEEE 802.11az Non-Trigger-based (non-TB) measurement.
*/
@@ -78,9 +78,4 @@
* Whether IEEE 802.11az Non-Trigger-based (non-TB) responder mode is supported.
*/
boolean ntbResponderSupported;
- /**
- * Maximum HE LTF repetitions the IEEE 802.11az initiator is capable of transmitting in the
- * preamble of I2R NDP.
- */
- int maxTxLtfRepetitionCount;
}
diff --git a/wifi/aidl/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
index e970656..7b18708 100644
--- a/wifi/aidl/android/hardware/wifi/RttConfig.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
@@ -121,16 +121,17 @@
*/
RttBw bw;
/**
- * IEEE 802.11az Non-Trigger-based (non-TB) minimum measurement time in milliseconds.
+ * IEEE 802.11az Non-Trigger-based (non-TB) minimum measurement time in units of 100
+ * microseconds.
+ *
+ * Reference: IEEE Std 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
*/
- int ntbMinMeasurementTimeMillis;
+ long ntbMinMeasurementTime;
/**
- * IEEE 802.11az Non-Trigger-based (non-TB) maximum measurement time in milliseconds.
+ * IEEE 802.11az Non-Trigger-based (non-TB) maximum measurement time in units of 10
+ * milliseconds.
+ *
+ * Reference: IEEE Std 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
*/
- int ntbMaxMeasurementTimeMillis;
- /**
- * Multiple transmissions of HE-LTF symbols in an HE Ranging NDP. A value of 1 indicates no
- * repetition.
- */
- int txLtfRepetitionCount;
+ long ntbMaxMeasurementTime;
}
diff --git a/wifi/aidl/android/hardware/wifi/RttResult.aidl b/wifi/aidl/android/hardware/wifi/RttResult.aidl
index 2cb0afa..ab9abb5 100644
--- a/wifi/aidl/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl
@@ -146,12 +146,18 @@
*/
RttBw packetBw;
/**
- * IEEE 802.11az Transmit LTF repetitions used to get this result.
+ * Multiple transmissions of HE-LTF symbols in an HE (I2R) Ranging NDP. An HE-LTF repetition
+ * value of 1 indicates no repetitions.
*/
- int txLtfRepetitionCount;
+ byte i2rTxLtfRepetitionCount;
/**
- * Minimum non-trigger based (non-TB) dynamic measurement time in milliseconds assigned by the
- * IEEE 802.11az responder.
+ * Multiple transmissions of HE-LTF symbols in an HE (R2I) Ranging NDP. An HE-LTF repetition
+ * value of 1 indicates no repetitions.
+ */
+ byte r2iTxLtfRepetitionCount;
+ /**
+ * Minimum non-trigger based (non-TB) dynamic measurement time in units of 100 microseconds
+ * assigned by the IEEE 802.11az responder.
*
* After initial non-TB negotiation, if the next ranging request for this peer comes in between
* [ntbMinMeasurementTime, ntbMaxMeasurementTime], vendor software shall do the NDPA sounding
@@ -160,11 +166,13 @@
* If the ranging request for this peer comes sooner than minimum measurement time, vendor
* software shall return the cached result of the last measurement including the time stamp
* |RttResult.timestamp|.
+ *
+ * Reference: IEEE Std 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
*/
- int ntbMinMeasurementTimeMillis;
+ long ntbMinMeasurementTime;
/**
- * Maximum non-trigger based (non-TB) dynamic measurement time in milliseconds assigned by the
- * IEEE 802.11az responder.
+ * Maximum non-trigger based (non-TB) dynamic measurement time in units of 10 milliseconds
+ * assigned by the IEEE 802.11az responder.
*
* After initial non-TB negotiation, if the next ranging request for this peer comes in between
* [ntbMinMeasurementTime, ntbMaxMeasurementTime], vendor software shall do the NDPA sounding
@@ -173,6 +181,8 @@
* If the ranging request for this peer comes later than the maximum measurement time, vendor
* software shall clean up any existing IEEE 802.11ax non-TB ranging session and re-do the
* non-TB ranging negotiation.
+ *
+ * Reference: IEEE Std 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
*/
- int ntbMaxMeasurementTimeMillis;
+ long ntbMaxMeasurementTime;
}
diff --git a/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl b/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl
new file mode 100644
index 0000000..28d16f0
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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;
+
+/**
+ * Target Wake Time (TWT) Capabilities supported.
+ *
+ * TWT allows Wi-Fi stations to manage activity in a network by scheduling to operate at different
+ * times. This minimizes the contention and reduces the required amount of time that a station
+ * utilizing a power management mode needs to be awake.
+ *
+ * IEEE 802.11ax standard defines two modes of TWT operation:
+ * - Individual TWT (default mode of operation if TWT requester is supported)
+ * - Broadcast TWT
+ */
+@VintfStability
+parcelable TwtCapabilities {
+ /**
+ * Whether the TWT requester mode supported.
+ */
+ boolean isTwtRequesterSupported;
+ /**
+ * Whether the TWT responder mode supported.
+ */
+ boolean isTwtResponderSupported;
+ /**
+ * Whether the Broadcast TWT mode (TWT scheduling STA) supported.
+ */
+ boolean isBroadcastTwtSupported;
+ /**
+ * Whether supports Flexible TWT schedules.
+ */
+ boolean isFlexibleTwtScheduleSupported;
+ /**
+ * Minimum TWT wake duration in microseconds.
+ */
+ int minWakeDurationUs;
+ /**
+ * Maximum TWT wake duration in microseconds.
+ */
+ int maxWakeDurationUs;
+ /**
+ * Minimum TWT wake interval in microseconds.
+ */
+ long minWakeIntervalUs;
+ /**
+ * Maximum TWT wake interval in microseconds.
+ */
+ long maxWakeIntervalUs;
+}
diff --git a/wifi/aidl/android/hardware/wifi/TwtRequest.aidl b/wifi/aidl/android/hardware/wifi/TwtRequest.aidl
new file mode 100644
index 0000000..6964a39
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/TwtRequest.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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;
+
+/**
+ * Target Wake Time (TWT) Request
+ */
+@VintfStability
+parcelable TwtRequest {
+ /**
+ * MLO Link id in case TWT is requesting for MLO connection. Otherwise -1.
+ */
+ int mloLinkId;
+ /**
+ * Minimum TWT wake duration in microseconds.
+ */
+ int minWakeDurationUs;
+ /**
+ * Maximum TWT wake duration in microseconds.
+ *
+ * As per IEEE 802.11ax spec, section 9.4.2.199 TWT element, the maximum wake duration is
+ * 65280 microseconds.
+ */
+ int maxWakeDurationUs;
+ /**
+ * Minimum TWT wake interval in microseconds.
+ */
+ long minWakeIntervalUs;
+ /**
+ * Maximum TWT wake interval in microseconds.
+ *
+ * As per IEEE 802.11ax spec, section 9.4.2.199 TWT element, the maximum wake interval is
+ * 65535 * 2^31 microseconds.
+ */
+ long maxWakeIntervalUs;
+}
diff --git a/wifi/aidl/android/hardware/wifi/TwtSession.aidl b/wifi/aidl/android/hardware/wifi/TwtSession.aidl
new file mode 100644
index 0000000..2d7e819
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/TwtSession.aidl
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 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;
+
+/**
+ * Target Wake Time (TWT) Session
+ */
+@VintfStability
+parcelable TwtSession {
+ @VintfStability
+ @Backing(type="byte")
+ enum TwtNegotiationType {
+ INDIVIDUAL = 0,
+ BROADCAST = 1,
+ }
+
+ /**
+ * An unique identifier for the session.
+ */
+ int sessionId;
+
+ /**
+ * MLO Link id in case of MLO connection. Otherwise -1.
+ */
+ int mloLinkId;
+
+ /**
+ * TWT service period in microseconds.
+ */
+ int wakeDurationUs;
+
+ /**
+ * Time interval in microseconds between two successive TWT service periods.
+ */
+ long wakeIntervalUs;
+
+ /**
+ * TWT negotiation type.
+ */
+ TwtNegotiationType negotiationType;
+
+ /**
+ * Whether the TWT session is trigger enabled or non-trigger enabled.
+ */
+ boolean isTriggerEnabled;
+
+ /**
+ * Whether the TWT session is announced or unannounced.
+ */
+ boolean isAnnounced;
+
+ /**
+ * Whether the TWT session is implicit or explicit.
+ */
+ boolean isImplicit;
+
+ /**
+ * Whether the TWT session is protected or not.
+ */
+ boolean isProtected;
+
+ /**
+ * Whether the TWT session can be updated.
+ */
+ boolean isUpdatable;
+
+ /**
+ * Whether the TWT session can be suspended and then resumed.
+ */
+ boolean isSuspendable;
+
+ /**
+ * Whether AP (TWT responder) intends to go to doze state outside of TWT Service Periods.
+ *
+ * Refer IEEE 802.11 spec, Section 10.47.7 (TWT Sleep Setup).
+ */
+ boolean isResponderPmModeEnabled;
+}
diff --git a/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl b/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl
new file mode 100644
index 0000000..ba70426
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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;
+
+/**
+ * Target Wake Time (TWT) Session Stats
+ */
+@VintfStability
+parcelable TwtSessionStats {
+ /**
+ * Average number of Tx packets in each wake duration.
+ */
+ int avgTxPktCount;
+
+ /**
+ * Average number of Rx packets in each wake duration.
+ */
+ int avgRxPktCount;
+
+ /**
+ * Average bytes per Tx packets in each wake duration.
+ */
+ int avgTxPktSize;
+
+ /**
+ * Average bytes per Rx packets in each wake duration.
+ */
+ int avgRxPktSize;
+
+ /**
+ * Average End of Service period in microseconds.
+ */
+ int avgEospDurationUs;
+
+ /**
+ * Count of early terminations.
+ */
+ int eospCount;
+}
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 8ecfcea..836ce1a 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -2741,9 +2741,8 @@
if (!convertAidlRttConfigToLegacy(aidl_config, &(legacy_config->rtt_config))) {
return false;
}
- legacy_config->tx_ltf_repetition_count = aidl_config.txLtfRepetitionCount;
- legacy_config->ntb_min_measurement_time_millis = aidl_config.ntbMinMeasurementTimeMillis;
- legacy_config->ntb_max_measurement_time_millis = aidl_config.ntbMaxMeasurementTimeMillis;
+ legacy_config->ntb_min_measurement_time = aidl_config.ntbMinMeasurementTime;
+ legacy_config->ntb_max_measurement_time = aidl_config.ntbMaxMeasurementTime;
return true;
}
@@ -2887,11 +2886,10 @@
aidl_capabilities->bwSupport = convertLegacyRttBwBitmapToAidl(legacy_capabilities.bw_support);
aidl_capabilities->mcVersion = legacy_capabilities.mc_version;
// Initialize 11az parameters to default
- aidl_capabilities->azPreambleSupport = RttPreamble::INVALID;
- aidl_capabilities->azBwSupport = RttBw::BW_UNSPECIFIED;
+ aidl_capabilities->azPreambleSupport = (int)RttPreamble::INVALID;
+ aidl_capabilities->azBwSupport = (int)RttBw::BW_UNSPECIFIED;
aidl_capabilities->ntbInitiatorSupported = false;
aidl_capabilities->ntbResponderSupported = false;
- aidl_capabilities->maxTxLtfRepetitionCount = 0;
return true;
}
@@ -2914,12 +2912,11 @@
convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.rtt_capab.bw_support);
aidl_capabilities->mcVersion = legacy_capabilities_v3.rtt_capab.mc_version;
aidl_capabilities->azPreambleSupport =
- convertLegacyRttPreambleBitmapToAidl(legacy_capabilities_v3.az_preamble_support);
+ (int)convertLegacyRttPreambleBitmapToAidl(legacy_capabilities_v3.az_preamble_support);
aidl_capabilities->azBwSupport =
- convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.az_bw_support);
+ (int)convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.az_bw_support);
aidl_capabilities->ntbInitiatorSupported = legacy_capabilities_v3.ntb_initiator_supported;
aidl_capabilities->ntbResponderSupported = legacy_capabilities_v3.ntb_responder_supported;
- aidl_capabilities->maxTxLtfRepetitionCount = legacy_capabilities_v3.max_tx_ltf_repetition_count;
return true;
}
@@ -2994,9 +2991,10 @@
}
aidl_result.channelFreqMHz = 0;
aidl_result.packetBw = RttBw::BW_UNSPECIFIED;
- aidl_result.txLtfRepetitionCount = 0;
- aidl_result.ntbMinMeasurementTimeMillis = 0;
- aidl_result.ntbMaxMeasurementTimeMillis = 0;
+ aidl_result.i2rTxLtfRepetitionCount = 0;
+ aidl_result.r2iTxLtfRepetitionCount = 0;
+ aidl_result.ntbMinMeasurementTime = 0;
+ aidl_result.ntbMaxMeasurementTime = 0;
aidl_results->push_back(aidl_result);
}
return true;
@@ -3017,9 +3015,10 @@
aidl_result.channelFreqMHz =
legacy_result->frequency != UNSPECIFIED ? legacy_result->frequency : 0;
aidl_result.packetBw = convertLegacyRttBwToAidl(legacy_result->packet_bw);
- aidl_result.txLtfRepetitionCount = 0;
- aidl_result.ntbMinMeasurementTimeMillis = 0;
- aidl_result.ntbMaxMeasurementTimeMillis = 0;
+ aidl_result.i2rTxLtfRepetitionCount = 0;
+ aidl_result.r2iTxLtfRepetitionCount = 0;
+ aidl_result.ntbMinMeasurementTime = 0;
+ aidl_result.ntbMaxMeasurementTime = 0;
aidl_results->push_back(aidl_result);
}
return true;
@@ -3041,9 +3040,10 @@
? legacy_result->rtt_result.frequency
: 0;
aidl_result.packetBw = convertLegacyRttBwToAidl(legacy_result->rtt_result.packet_bw);
- aidl_result.txLtfRepetitionCount = legacy_result->tx_ltf_repetition_count;
- aidl_result.ntbMinMeasurementTimeMillis = legacy_result->ntb_min_measurement_time_millis;
- aidl_result.ntbMaxMeasurementTimeMillis = legacy_result->ntb_max_measurement_time_millis;
+ aidl_result.i2rTxLtfRepetitionCount = legacy_result->i2r_tx_ltf_repetition_count;
+ aidl_result.r2iTxLtfRepetitionCount = legacy_result->r2i_tx_ltf_repetition_count;
+ aidl_result.ntbMinMeasurementTime = legacy_result->ntb_min_measurement_time;
+ aidl_result.ntbMaxMeasurementTime = legacy_result->ntb_max_measurement_time;
aidl_results->push_back(aidl_result);
}
return true;
@@ -3576,6 +3576,132 @@
return WifiRatePreamble::OFDM;
}
+bool convertTwtCapabilitiesToAidl(legacy_hal::wifi_twt_capabilities legacy_twt_capabs,
+ TwtCapabilities* aidl_twt_capabs) {
+ if (!aidl_twt_capabs) {
+ return false;
+ }
+ aidl_twt_capabs->isTwtRequesterSupported = legacy_twt_capabs.is_twt_requester_supported;
+ aidl_twt_capabs->isTwtResponderSupported = legacy_twt_capabs.is_twt_responder_supported;
+ aidl_twt_capabs->isBroadcastTwtSupported = legacy_twt_capabs.is_flexible_twt_supported;
+ if (legacy_twt_capabs.min_wake_duration_micros > legacy_twt_capabs.max_wake_duration_micros) {
+ return false;
+ }
+ aidl_twt_capabs->minWakeDurationUs = legacy_twt_capabs.min_wake_duration_micros;
+ aidl_twt_capabs->maxWakeDurationUs = legacy_twt_capabs.max_wake_duration_micros;
+ if (legacy_twt_capabs.min_wake_interval_micros > legacy_twt_capabs.max_wake_interval_micros) {
+ return false;
+ }
+ aidl_twt_capabs->minWakeIntervalUs = legacy_twt_capabs.min_wake_interval_micros;
+ aidl_twt_capabs->maxWakeIntervalUs = legacy_twt_capabs.max_wake_interval_micros;
+ return true;
+}
+
+bool convertAidlTwtRequestToLegacy(const TwtRequest aidl_twt_request,
+ legacy_hal::wifi_twt_request* legacy_twt_request) {
+ if (legacy_twt_request == nullptr) {
+ return false;
+ }
+ legacy_twt_request->mlo_link_id = aidl_twt_request.mloLinkId;
+ if (aidl_twt_request.minWakeDurationUs > aidl_twt_request.maxWakeDurationUs) {
+ return false;
+ }
+ legacy_twt_request->min_wake_duration_micros = aidl_twt_request.minWakeDurationUs;
+ legacy_twt_request->max_wake_duration_micros = aidl_twt_request.maxWakeDurationUs;
+ if (aidl_twt_request.minWakeIntervalUs > aidl_twt_request.maxWakeIntervalUs) {
+ return false;
+ }
+ legacy_twt_request->min_wake_interval_micros = aidl_twt_request.minWakeIntervalUs;
+ legacy_twt_request->max_wake_interval_micros = aidl_twt_request.maxWakeIntervalUs;
+ return true;
+}
+
+IWifiStaIfaceEventCallback::TwtErrorCode convertLegacyHalTwtErrorCodeToAidl(
+ legacy_hal::wifi_twt_error_code legacy_error_code) {
+ switch (legacy_error_code) {
+ case WIFI_TWT_ERROR_CODE_TIMEOUT:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::TIMEOUT;
+ case WIFI_TWT_ERROR_CODE_PEER_REJECTED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::PEER_REJECTED;
+ case WIFI_TWT_ERROR_CODE_PEER_NOT_SUPPORTED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::PEER_NOT_SUPPORTED;
+ case WIFI_TWT_ERROR_CODE_NOT_SUPPORTED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::NOT_SUPPORTED;
+ case WIFI_TWT_ERROR_CODE_NOT_AVAILABLE:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::NOT_AVAILABLE;
+ case WIFI_TWT_ERROR_CODE_MAX_SESSION_REACHED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::MAX_SESSION_REACHED;
+ case WIFI_TWT_ERROR_CODE_INVALID_PARAMS:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::INVALID_PARAMS;
+ case WIFI_TWT_ERROR_CODE_ALREADY_SUSPENDED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::ALREADY_SUSPENDED;
+ case WIFI_TWT_ERROR_CODE_ALREADY_RESUMED:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::ALREADY_RESUMED;
+ default:
+ return IWifiStaIfaceEventCallback::TwtErrorCode::FAILURE_UNKNOWN;
+ }
+}
+
+IWifiStaIfaceEventCallback::TwtTeardownReasonCode convertLegacyHalTwtReasonCodeToAidl(
+ legacy_hal::wifi_twt_teardown_reason_code legacy_reason_code) {
+ switch (legacy_reason_code) {
+ case WIFI_TWT_TEARDOWN_REASON_CODE_LOCALLY_REQUESTED:
+ return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::LOCALLY_REQUESTED;
+ case WIFI_TWT_TEARDOWN_REASON_CODE_INTERNALLY_INITIATED:
+ return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::INTERNALLY_INITIATED;
+ case WIFI_TWT_TEARDOWN_REASON_CODE_PEER_INITIATED:
+ return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::PEER_INITIATED;
+ default:
+ return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::UNKNOWN;
+ }
+}
+
+bool convertLegacyHalTwtSessionToAidl(legacy_hal::wifi_twt_session twt_session,
+ TwtSession* aidl_twt_session) {
+ if (aidl_twt_session == nullptr) {
+ return false;
+ }
+
+ aidl_twt_session->sessionId = twt_session.session_id;
+ aidl_twt_session->mloLinkId = twt_session.mlo_link_id;
+ aidl_twt_session->wakeDurationUs = twt_session.wake_duration_micros;
+ aidl_twt_session->wakeIntervalUs = twt_session.wake_interval_micros;
+ switch (twt_session.negotiation_type) {
+ case WIFI_TWT_NEGO_TYPE_INDIVIDUAL:
+ aidl_twt_session->negotiationType = TwtSession::TwtNegotiationType::INDIVIDUAL;
+ break;
+ case WIFI_TWT_NEGO_TYPE_BROADCAST:
+ aidl_twt_session->negotiationType = TwtSession::TwtNegotiationType::BROADCAST;
+ break;
+ default:
+ return false;
+ }
+ aidl_twt_session->isTriggerEnabled = twt_session.is_trigger_enabled;
+ aidl_twt_session->isAnnounced = twt_session.is_announced;
+ aidl_twt_session->isImplicit = twt_session.is_implicit;
+ aidl_twt_session->isProtected = twt_session.is_protected;
+ aidl_twt_session->isUpdatable = twt_session.is_updatable;
+ aidl_twt_session->isSuspendable = twt_session.is_suspendable;
+ aidl_twt_session->isResponderPmModeEnabled = twt_session.is_responder_pm_mode_enabled;
+ return true;
+}
+
+bool convertLegacyHalTwtSessionStatsToAidl(legacy_hal::wifi_twt_session_stats twt_stats,
+ TwtSessionStats* aidl_twt_stats) {
+ if (aidl_twt_stats == nullptr) {
+ return false;
+ }
+
+ aidl_twt_stats->avgTxPktCount = twt_stats.avg_pkt_num_tx;
+ aidl_twt_stats->avgRxPktCount = twt_stats.avg_pkt_num_rx;
+ aidl_twt_stats->avgTxPktSize = twt_stats.avg_tx_pkt_size;
+ aidl_twt_stats->avgRxPktSize = twt_stats.avg_rx_pkt_size;
+ aidl_twt_stats->avgEospDurationUs = twt_stats.avg_eosp_dur_us;
+ aidl_twt_stats->eospCount = twt_stats.eosp_count;
+
+ return true;
+}
+
} // namespace aidl_struct_util
} // namespace wifi
} // namespace hardware
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index 1942b5f..7089363 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -218,6 +218,18 @@
bool convertCachedScanResultToAidl(const legacy_hal::wifi_cached_scan_result& legacy_scan_result,
uint64_t ts_us, CachedScanResult* aidl_scan_result);
WifiRatePreamble convertScanResultFlagsToPreambleType(int flags);
+bool convertTwtCapabilitiesToAidl(const legacy_hal::wifi_twt_capabilities legacy_twt_capabs,
+ TwtCapabilities* aidl_twt_capabs);
+bool convertAidlTwtRequestToLegacy(const TwtRequest aidl_twt_request,
+ legacy_hal::wifi_twt_request* legacy_twt_request);
+IWifiStaIfaceEventCallback::TwtErrorCode convertLegacyHalTwtErrorCodeToAidl(
+ legacy_hal::wifi_twt_error_code legacy_error_code);
+IWifiStaIfaceEventCallback::TwtTeardownReasonCode convertLegacyHalTwtReasonCodeToAidl(
+ legacy_hal::wifi_twt_teardown_reason_code legacy_reason_code);
+bool convertLegacyHalTwtSessionToAidl(legacy_hal::wifi_twt_session twt_session,
+ TwtSession* aidl_twt_session);
+bool convertLegacyHalTwtSessionStatsToAidl(legacy_hal::wifi_twt_session_stats twt_stats,
+ TwtSessionStats* aidl_twt_stats);
} // namespace aidl_struct_util
} // namespace wifi
} // namespace hardware
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index 2e80183..55d6f59 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -457,6 +457,76 @@
}
}
+// Callback to be invoked for TWT failure
+std::function<void((wifi_request_id, wifi_twt_error_code error_code))>
+ on_twt_failure_internal_callback;
+void onAsyncTwtError(wifi_request_id id, wifi_twt_error_code error_code) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_failure_internal_callback) {
+ on_twt_failure_internal_callback(id, error_code);
+ }
+}
+
+// Callback to be invoked for TWT session creation
+std::function<void((wifi_request_id, wifi_twt_session twt_session))>
+ on_twt_session_create_internal_callback;
+void onAsyncTwtSessionCreate(wifi_request_id id, wifi_twt_session twt_session) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_create_internal_callback) {
+ on_twt_session_create_internal_callback(id, twt_session);
+ }
+}
+
+// Callback to be invoked for TWT session update
+std::function<void((wifi_request_id, wifi_twt_session twt_session))>
+ on_twt_session_update_internal_callback;
+void onAsyncTwtSessionUpdate(wifi_request_id id, wifi_twt_session twt_session) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_update_internal_callback) {
+ on_twt_session_update_internal_callback(id, twt_session);
+ }
+}
+
+// Callback to be invoked for TWT session teardown
+std::function<void(
+ (wifi_request_id, int twt_session_id, wifi_twt_teardown_reason_code reason_code))>
+ on_twt_session_teardown_internal_callback;
+void onAsyncTwtSessionTeardown(wifi_request_id id, int twt_session_id,
+ wifi_twt_teardown_reason_code reason_code) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_teardown_internal_callback) {
+ on_twt_session_teardown_internal_callback(id, twt_session_id, reason_code);
+ }
+}
+
+// Callback to be invoked for TWT session get stats
+std::function<void((wifi_request_id, int twt_session_id, wifi_twt_session_stats stats))>
+ on_twt_session_stats_internal_callback;
+void onAsyncTwtSessionStats(wifi_request_id id, int twt_session_id, wifi_twt_session_stats stats) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_stats_internal_callback) {
+ on_twt_session_stats_internal_callback(id, twt_session_id, stats);
+ }
+}
+
+// Callback to be invoked for TWT session suspend
+std::function<void((wifi_request_id, int twt_session_id))> on_twt_session_suspend_internal_callback;
+void onAsyncTwtSessionSuspend(wifi_request_id id, int twt_session_id) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_suspend_internal_callback) {
+ on_twt_session_suspend_internal_callback(id, twt_session_id);
+ }
+}
+
+// Callback to be invoked for TWT session resume
+std::function<void((wifi_request_id, int twt_session_id))> on_twt_session_resume_internal_callback;
+void onAsyncTwtSessionResume(wifi_request_id id, int twt_session_id) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_session_resume_internal_callback) {
+ on_twt_session_resume_internal_callback(id, twt_session_id);
+ }
+}
+
// End of the free-standing "C" style callbacks.
WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
@@ -1789,6 +1859,103 @@
return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode);
}
+std::pair<wifi_twt_capabilities, wifi_error> WifiLegacyHal::twtGetCapabilities(
+ const std::string& ifaceName) {
+ wifi_twt_capabilities capabs = {};
+ wifi_error status =
+ global_func_table_.wifi_twt_get_capabilities(getIfaceHandle(ifaceName), &capabs);
+ return {capabs, status};
+}
+
+wifi_error WifiLegacyHal::twtSessionSetup(
+ const std::string& ifaceName, uint32_t cmdId, const wifi_twt_request& request,
+ const on_twt_failure& on_twt_failure_user_callback,
+ const on_twt_session_create& on_twt_session_create_user_callback,
+ const on_twt_session_update& on_twt_session_update_user_callback,
+ const on_twt_session_teardown& on_twt_session_teardown_user_callback,
+ const on_twt_session_stats& on_twt_session_stats_user_callback,
+ const on_twt_session_suspend& on_twt_session_suspend_user_callback,
+ const on_twt_session_resume& on_twt_session_resume_user_callback) {
+ if (on_twt_failure_internal_callback || on_twt_session_create_internal_callback ||
+ on_twt_session_update_internal_callback || on_twt_session_teardown_internal_callback ||
+ on_twt_session_stats_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ on_twt_failure_internal_callback = [on_twt_failure_user_callback](
+ wifi_request_id id, wifi_twt_error_code error_code) {
+ on_twt_failure_user_callback(id, error_code);
+ };
+
+ on_twt_session_create_internal_callback = [on_twt_session_create_user_callback](
+ wifi_request_id id,
+ wifi_twt_session twt_session) {
+ on_twt_session_create_user_callback(id, twt_session);
+ };
+
+ on_twt_session_update_internal_callback = [on_twt_session_update_user_callback](
+ wifi_request_id id,
+ wifi_twt_session twt_session) {
+ on_twt_session_update_user_callback(id, twt_session);
+ };
+
+ on_twt_session_teardown_internal_callback = [on_twt_session_teardown_user_callback](
+ wifi_request_id id, int session_id,
+ wifi_twt_teardown_reason_code reason_code) {
+ on_twt_session_teardown_user_callback(id, session_id, reason_code);
+ };
+
+ on_twt_session_stats_internal_callback = [on_twt_session_stats_user_callback](
+ wifi_request_id id, int session_id,
+ wifi_twt_session_stats stats) {
+ on_twt_session_stats_user_callback(id, session_id, stats);
+ };
+
+ on_twt_session_suspend_internal_callback = [on_twt_session_suspend_user_callback](
+ wifi_request_id id, int session_id) {
+ on_twt_session_suspend_user_callback(id, session_id);
+ };
+
+ on_twt_session_resume_internal_callback = [on_twt_session_resume_user_callback](
+ wifi_request_id id, int session_id) {
+ on_twt_session_resume_user_callback(id, session_id);
+ };
+
+ return global_func_table_.wifi_twt_session_setup(
+ cmdId, getIfaceHandle(ifaceName), request,
+ {onAsyncTwtError, onAsyncTwtSessionCreate, onAsyncTwtSessionUpdate,
+ onAsyncTwtSessionTeardown, onAsyncTwtSessionStats, onAsyncTwtSessionSuspend,
+ onAsyncTwtSessionResume});
+}
+
+wifi_error WifiLegacyHal::twtSessionUpdate(const std::string& ifaceName, uint32_t cmdId,
+ uint32_t sessionId, const wifi_twt_request& request) {
+ return global_func_table_.wifi_twt_session_update(cmdId, getIfaceHandle(ifaceName), sessionId,
+ request);
+}
+
+wifi_error WifiLegacyHal::twtSessionSuspend(const std::string& ifaceName, uint32_t cmdId,
+ uint32_t sessionId) {
+ return global_func_table_.wifi_twt_session_suspend(cmdId, getIfaceHandle(ifaceName), sessionId);
+}
+
+wifi_error WifiLegacyHal::twtSessionResume(const std::string& ifaceName, uint32_t cmdId,
+ uint32_t sessionId) {
+ return global_func_table_.wifi_twt_session_resume(cmdId, getIfaceHandle(ifaceName), sessionId);
+}
+
+wifi_error WifiLegacyHal::twtSessionTeardown(const std::string& ifaceName, uint32_t cmdId,
+ uint32_t sessionId) {
+ return global_func_table_.wifi_twt_session_teardown(cmdId, getIfaceHandle(ifaceName),
+ sessionId);
+}
+
+wifi_error WifiLegacyHal::twtSessionGetStats(const std::string& ifaceName, uint32_t cmdId,
+ uint32_t sessionId) {
+ return global_func_table_.wifi_twt_session_get_stats(cmdId, getIfaceHandle(ifaceName),
+ sessionId);
+}
+
wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name,
const TwtCallbackHandlers& user_callbacks) {
on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index 17509df..121d1b5 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -376,6 +376,13 @@
using ::WIFI_SCAN_FLAG_INTERRUPTED;
using ::wifi_scan_result;
using ::WIFI_SUCCESS;
+using ::wifi_twt_capabilities;
+using ::wifi_twt_error_code;
+using ::wifi_twt_events;
+using ::wifi_twt_request;
+using ::wifi_twt_session;
+using ::wifi_twt_session_stats;
+using ::wifi_twt_teardown_reason_code;
using ::wifi_tx_packet_fate;
using ::wifi_tx_report;
using ::wifi_usable_channel;
@@ -555,6 +562,16 @@
std::function<void(wifi_cached_scan_report*)> on_cached_scan_results;
};
+using on_twt_failure = std::function<void(wifi_request_id id, wifi_twt_error_code error_code)>;
+using on_twt_session_create = std::function<void(wifi_request_id id, wifi_twt_session twt_session)>;
+using on_twt_session_update = std::function<void(wifi_request_id id, wifi_twt_session twt_session)>;
+using on_twt_session_teardown = std::function<void(wifi_request_id id, int session_id,
+ wifi_twt_teardown_reason_code reason_code)>;
+using on_twt_session_stats =
+ std::function<void(wifi_request_id id, int session_id, wifi_twt_session_stats stats)>;
+using on_twt_session_suspend = std::function<void(wifi_request_id id, int session_id)>;
+using on_twt_session_resume = std::function<void(wifi_request_id id, int session_id)>;
+
/**
* Class that encapsulates all legacy HAL interactions.
* This class manages the lifetime of the event loop thread used by legacy HAL.
@@ -761,19 +778,39 @@
wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
+ // TWT functions
+ std::pair<wifi_twt_capabilities, wifi_error> twtGetCapabilities(const std::string& ifaceName);
+ wifi_error twtSessionSetup(const std::string& ifaceName, uint32_t cmdId,
+ const wifi_twt_request& request,
+ const on_twt_failure& on_twt_failure_user_callback,
+ const on_twt_session_create& on_twt_session_create_user_callback,
+ const on_twt_session_update& on_twt_session_update_user_callback,
+ const on_twt_session_teardown& on_twt_session_teardown_user_callback,
+ const on_twt_session_stats& on_twt_session_stats_user_callback,
+ const on_twt_session_suspend& on_twt_session_suspend_user_callback,
+ const on_twt_session_resume& on_twt_session_resume_user_callback);
+ wifi_error twtSessionUpdate(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId,
+ const wifi_twt_request& request);
+ wifi_error twtSessionSuspend(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId);
+ wifi_error twtSessionResume(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId);
+ wifi_error twtSessionTeardown(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId);
+ wifi_error twtSessionGetStats(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId);
+
+ // Note: Following TWT functions are deprecated
+ // Deprecated
wifi_error twtRegisterHandler(const std::string& iface_name,
const TwtCallbackHandlers& handler);
-
+ // Deprecated by twtGetCapabilities
std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(const std::string& iface_name);
-
+ // Deprecated by twtSessionSetup
wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg);
-
+ // Deprecated by twtSessionTeardown
wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg);
-
+ // Deprecated by twtSessionSuspend and twtSessionResume
wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg);
-
+ // Deprecated by twtSessionGetStats
std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name, uint8_t configId);
-
+ // Deprecated
wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
wifi_error setScanMode(const std::string& iface_name, bool enable);
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index 3d59c65..3e4afd0 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -181,6 +181,13 @@
populateStubFor(&hal_fn->wifi_get_supported_iface_concurrency_matrix);
populateStubFor(&hal_fn->wifi_get_rtt_capabilities_v3);
populateStubFor(&hal_fn->wifi_rtt_range_request_v3);
+ populateStubFor(&hal_fn->wifi_twt_get_capabilities);
+ populateStubFor(&hal_fn->wifi_twt_session_setup);
+ populateStubFor(&hal_fn->wifi_twt_session_update);
+ populateStubFor(&hal_fn->wifi_twt_session_suspend);
+ populateStubFor(&hal_fn->wifi_twt_session_resume);
+ populateStubFor(&hal_fn->wifi_twt_session_teardown);
+ populateStubFor(&hal_fn->wifi_twt_session_get_stats);
return true;
}
diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp
index 0ae428f..f0509dc 100644
--- a/wifi/aidl/default/wifi_sta_iface.cpp
+++ b/wifi/aidl/default/wifi_sta_iface.cpp
@@ -224,6 +224,44 @@
&WifiStaIface::getCachedScanDataInternal, _aidl_return);
}
+ndk::ScopedAStatus WifiStaIface::twtGetCapabilities(TwtCapabilities* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtGetCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionSetup(int32_t in_cmdId,
+ const TwtRequest& in_twtRequest) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionSetupInternal, in_cmdId, in_twtRequest);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionUpdate(int32_t in_cmdId, int32_t in_sessionId,
+ const TwtRequest& in_twtRequest) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionUpdateInternal, in_cmdId, in_sessionId,
+ in_twtRequest);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionSuspend(int32_t in_cmdId, int32_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionSuspendInternal, in_cmdId, in_sessionId);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionResume(int32_t in_cmdId, int32_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionResumeInternal, in_cmdId, in_sessionId);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionTeardown(int32_t in_cmdId, int32_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionTeardownInternal, in_cmdId, in_sessionId);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionGetStats(int32_t in_cmdId, int32_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::twtSessionGetStatsInternal, in_cmdId, in_sessionId);
+}
+
std::pair<std::string, ndk::ScopedAStatus> WifiStaIface::getNameInternal() {
return {ifname_, ndk::ScopedAStatus::ok()};
}
@@ -560,6 +598,194 @@
return {aidl_scan_data, ndk::ScopedAStatus::ok()};
}
+std::pair<TwtCapabilities, ndk::ScopedAStatus> WifiStaIface::twtGetCapabilitiesInternal() {
+ legacy_hal::wifi_twt_capabilities legacyHaltwtCapabilities;
+ legacy_hal::wifi_error legacy_status;
+ std::tie(legacyHaltwtCapabilities, legacy_status) =
+ legacy_hal_.lock()->twtGetCapabilities(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {TwtCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ TwtCapabilities aidlTwtCapabilities;
+ if (!aidl_struct_util::convertTwtCapabilitiesToAidl(legacyHaltwtCapabilities,
+ &aidlTwtCapabilities)) {
+ return {TwtCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {aidlTwtCapabilities, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionSetupInternal(int32_t cmdId,
+ const TwtRequest& aidlTwtRequest) {
+ legacy_hal::wifi_twt_request legacyHalTwtRequest;
+ if (!aidl_struct_util::convertAidlTwtRequestToLegacy(aidlTwtRequest, &legacyHalTwtRequest)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ std::weak_ptr<WifiStaIface> weak_ptr_this = weak_ptr_this_;
+
+ // onTwtFailure callback
+ const auto& on_twt_failure = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ legacy_hal::wifi_twt_error_code error_code) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ IWifiStaIfaceEventCallback::TwtErrorCode aidl_error_code =
+ aidl_struct_util::convertLegacyHalTwtErrorCodeToAidl(error_code);
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtFailure(id, aidl_error_code).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtFailure callback";
+ }
+ }
+ };
+ // onTwtSessionCreate callback
+ const auto& on_twt_session_create = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ legacy_hal::wifi_twt_session twt_session) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ TwtSession aidl_twt_session;
+ if (!aidl_struct_util::convertLegacyHalTwtSessionToAidl(twt_session, &aidl_twt_session)) {
+ LOG(ERROR) << "convertLegacyHalTwtSessionToAidl failed";
+ return;
+ }
+
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionCreate(id, aidl_twt_session).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionCreate callback";
+ }
+ }
+ };
+ // onTwtSessionUpdate callback
+ const auto& on_twt_session_update = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ legacy_hal::wifi_twt_session twt_session) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ TwtSession aidl_twt_session;
+ if (!aidl_struct_util::convertLegacyHalTwtSessionToAidl(twt_session, &aidl_twt_session)) {
+ LOG(ERROR) << "convertLegacyHalTwtSessionToAidl failed";
+ return;
+ }
+
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionUpdate(id, aidl_twt_session).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionUpdate callback";
+ }
+ }
+ };
+ // onTwtSessionTeardown callback
+ const auto& on_twt_session_teardown =
+ [weak_ptr_this](legacy_hal::wifi_request_id id, int session_id,
+ legacy_hal::wifi_twt_teardown_reason_code reason_code) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ IWifiStaIfaceEventCallback::TwtTeardownReasonCode aidl_reason_code =
+ aidl_struct_util::convertLegacyHalTwtReasonCodeToAidl(reason_code);
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionTeardown(id, session_id, aidl_reason_code).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionTeardown callback";
+ }
+ }
+ };
+ // onTwtSessionStats callback
+ const auto& on_twt_session_stats = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ int session_id,
+ legacy_hal::wifi_twt_session_stats stats) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ TwtSessionStats aidl_session_stats;
+ if (!aidl_struct_util::convertLegacyHalTwtSessionStatsToAidl(stats, &aidl_session_stats)) {
+ LOG(ERROR) << "convertLegacyHalTwtSessionStatsToAidl failed";
+ return;
+ }
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionStats(id, session_id, aidl_session_stats).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionStats callback";
+ }
+ }
+ };
+ // onTwtSessionSuspend callback
+ const auto& on_twt_session_suspend = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ int session_id) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionSuspend(id, session_id).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionSuspend callback";
+ }
+ }
+ };
+ // onTwtSessionResume callback
+ const auto& on_twt_session_resume = [weak_ptr_this](legacy_hal::wifi_request_id id,
+ int session_id) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onTwtSessionResume(id, session_id).isOk()) {
+ LOG(ERROR) << "Failed to invoke onTwtSessionResume callback";
+ }
+ }
+ };
+
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->twtSessionSetup(
+ ifname_, cmdId, legacyHalTwtRequest, on_twt_failure, on_twt_session_create,
+ on_twt_session_update, on_twt_session_teardown, on_twt_session_stats,
+ on_twt_session_suspend, on_twt_session_resume);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionUpdateInternal(int32_t cmdId, int32_t sessionId,
+ const TwtRequest& aidlTwtRequest) {
+ legacy_hal::wifi_twt_request legacyHalTwtRequest;
+ if (!aidl_struct_util::convertAidlTwtRequestToLegacy(aidlTwtRequest, &legacyHalTwtRequest)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->twtSessionUpdate(ifname_, cmdId, sessionId, legacyHalTwtRequest);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionSuspendInternal(int32_t cmdId, int32_t sessionId) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->twtSessionSuspend(ifname_, cmdId, sessionId);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionResumeInternal(int32_t cmdId, int32_t sessionId) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->twtSessionResume(ifname_, cmdId, sessionId);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionTeardownInternal(int32_t cmdId, int32_t sessionId) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->twtSessionTeardown(ifname_, cmdId, sessionId);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::twtSessionGetStatsInternal(int32_t cmdId, int32_t sessionId) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->twtSessionGetStats(ifname_, cmdId, sessionId);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/aidl/default/wifi_sta_iface.h b/wifi/aidl/default/wifi_sta_iface.h
index fe05c21..eb8f745 100644
--- a/wifi/aidl/default/wifi_sta_iface.h
+++ b/wifi/aidl/default/wifi_sta_iface.h
@@ -91,6 +91,14 @@
ndk::ScopedAStatus setScanMode(bool in_enable) override;
ndk::ScopedAStatus setDtimMultiplier(int32_t in_multiplier) override;
ndk::ScopedAStatus getCachedScanData(CachedScanData* _aidl_return) override;
+ ndk::ScopedAStatus twtGetCapabilities(TwtCapabilities* _aidl_return) override;
+ ndk::ScopedAStatus twtSessionSetup(int in_cmdId, const TwtRequest& in_twtRequest) override;
+ ndk::ScopedAStatus twtSessionUpdate(int in_cmdId, int32_t in_sessionId,
+ const TwtRequest& in_twtRequest) override;
+ ndk::ScopedAStatus twtSessionSuspend(int in_cmdId, int32_t in_sessionId) override;
+ ndk::ScopedAStatus twtSessionResume(int in_cmdId, int32_t in_sessionId) override;
+ ndk::ScopedAStatus twtSessionTeardown(int in_cmdId, int32_t in_sessionId) override;
+ ndk::ScopedAStatus twtSessionGetStats(int in_cmdId, int32_t in_sessionId) override;
private:
// Corresponding worker functions for the AIDL methods.
@@ -132,6 +140,14 @@
ndk::ScopedAStatus setScanModeInternal(bool enable);
ndk::ScopedAStatus setDtimMultiplierInternal(const int multiplier);
std::pair<CachedScanData, ndk::ScopedAStatus> getCachedScanDataInternal();
+ std::pair<TwtCapabilities, ndk::ScopedAStatus> twtGetCapabilitiesInternal();
+ ndk::ScopedAStatus twtSessionSetupInternal(int cmdId, const TwtRequest& twtRequest);
+ ndk::ScopedAStatus twtSessionUpdateInternal(int cmdId, int32_t sessionId,
+ const TwtRequest& twtRequest);
+ ndk::ScopedAStatus twtSessionSuspendInternal(int cmdId, int32_t sessionId);
+ ndk::ScopedAStatus twtSessionResumeInternal(int cmdId, int32_t sessionId);
+ ndk::ScopedAStatus twtSessionTeardownInternal(int cmdId, int32_t sessionId);
+ ndk::ScopedAStatus twtSessionGetStatsInternal(int cmdId, int32_t sessionId);
void setWeakPtr(std::weak_ptr<WifiStaIface> ptr);
diff --git a/wifi/aidl/vts/functional/Android.bp b/wifi/aidl/vts/functional/Android.bp
index 1277182..6896110 100644
--- a/wifi/aidl/vts/functional/Android.bp
+++ b/wifi/aidl/vts/functional/Android.bp
@@ -39,7 +39,8 @@
],
static_libs: [
"VtsHalWifiTargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
test_suites: [
@@ -64,7 +65,8 @@
],
static_libs: [
"VtsHalWifiTargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
test_suites: [
@@ -89,7 +91,8 @@
],
static_libs: [
"VtsHalWifiTargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
test_suites: [
@@ -114,7 +117,8 @@
],
static_libs: [
"VtsHalWifiTargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
test_suites: [
@@ -139,7 +143,8 @@
],
static_libs: [
"VtsHalWifiTargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
test_suites: [
@@ -163,7 +168,8 @@
"libnativehelper",
],
static_libs: [
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system-iface",
],
}
diff --git a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
index 740f833..a1b9ce1 100644
--- a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
@@ -872,6 +872,36 @@
EXPECT_EQ(instances_after_remove.size(), 1);
}
+/*
+ * SetVoipMode_off
+ * Tests the setVoipMode() API with VoIP mode OFF.
+ */
+TEST_P(WifiChipAidlTest, SetVoipMode_off) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t features = getChipFeatureSet(wifi_chip_);
+ if (features & static_cast<int32_t>(IWifiChip::FeatureSetMask::SET_VOIP_MODE)) {
+ auto status = wifi_chip_->setVoipMode(IWifiChip::VoipMode::OFF);
+ EXPECT_TRUE(status.isOk());
+ } else {
+ GTEST_SKIP() << "setVoipMode() is not supported by vendor.";
+ }
+}
+
+/*
+ * SetVoipMode_voice
+ * Tests the setVoipMode() API with VoIP mode VOICE.
+ */
+TEST_P(WifiChipAidlTest, SetVoipMode_voice) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t features = getChipFeatureSet(wifi_chip_);
+ if (features & static_cast<int32_t>(IWifiChip::FeatureSetMask::SET_VOIP_MODE)) {
+ auto status = wifi_chip_->setVoipMode(IWifiChip::VoipMode::VOICE);
+ EXPECT_TRUE(status.isOk());
+ } else {
+ GTEST_SKIP() << "setVoipMode() is not supported by vendor.";
+ }
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipAidlTest);
INSTANTIATE_TEST_SUITE_P(WifiTest, WifiChipAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index ff35056..87eee82 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -36,7 +36,8 @@
"android.hardware.wifi@1.4",
"android.hardware.wifi@1.5",
"android.hardware.wifi@1.6",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"libwifi-system",
"libwifi-system-iface",
"VtsHalWifiTargetTestUtil",
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
index 0729646..05a7548 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -42,6 +42,9 @@
void cancelConnect();
void cancelServiceDiscovery(in long identifier);
void cancelWps(in String groupIfName);
+ /**
+ * @deprecated This method is deprecated from AIDL v3, newer HALs should use configureExtListenWithParams.
+ */
void configureExtListen(in int periodInMillis, in int intervalInMillis);
/**
* @deprecated This method is deprecated from AIDL v3, newer HALs should use connectWithParams.
@@ -111,4 +114,5 @@
void configureEapolIpAddressAllocationParams(in int ipAddressGo, in int ipAddressMask, in int ipAddressStart, in int ipAddressEnd);
String connectWithParams(in android.hardware.wifi.supplicant.P2pConnectInfo connectInfo);
void findWithParams(in android.hardware.wifi.supplicant.P2pDiscoveryInfo discoveryInfo);
+ void configureExtListenWithParams(in android.hardware.wifi.supplicant.P2pExtListenInfo extListenInfo);
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
index 851e851..4811565 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -35,7 +35,7 @@
@VintfStability
interface ISupplicantP2pIfaceCallback {
/**
- * @deprecated This callback is deprecated from AIDL v2, newer HAL should call onDeviceFoundWithParams.
+ * @deprecated This callback is deprecated from AIDL v3, newer HAL should call onDeviceFoundWithParams.
*/
oneway void onDeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress, in byte[] primaryDeviceType, in String deviceName, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in byte deviceCapabilities, in android.hardware.wifi.supplicant.P2pGroupCapabilityMask groupCapabilities, in byte[] wfdDeviceInfo);
oneway void onDeviceLost(in byte[] p2pDeviceAddress);
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index 1f3aa48..917668e 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -101,5 +101,7 @@
android.hardware.wifi.supplicant.SignalPollResult[] getSignalPollResults();
android.hardware.wifi.supplicant.QosPolicyScsRequestStatus[] addQosPolicyRequestForScs(in android.hardware.wifi.supplicant.QosPolicyScsData[] qosPolicyData);
android.hardware.wifi.supplicant.QosPolicyScsRequestStatus[] removeQosPolicyForScs(in byte[] scsPolicyIds);
+ void configureMscs(in android.hardware.wifi.supplicant.MscsParams params);
+ void disableMscs();
const int MAX_POLICIES_PER_QOS_SCS_REQUEST = 16;
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 898c2d4..9fa8f56 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -54,7 +54,7 @@
oneway void onExtRadioWorkTimeout(in int id);
oneway void onHs20DeauthImminentNotice(in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
/**
- * @deprecated No longer in use.
+ * @deprecated This callback is deprecated from AIDL v3.
*/
oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
oneway void onHs20SubscriptionRemediation(in byte[] bssid, in android.hardware.wifi.supplicant.OsuMethod osuMethod, in String url);
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MscsParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MscsParams.aidl
new file mode 100644
index 0000000..aeed408
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MscsParams.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable MscsParams {
+ byte upBitmap;
+ byte upLimit;
+ int streamTimeoutUs;
+ byte frameClassifierMask;
+ @Backing(type="int") @VintfStability
+ enum FrameClassifierFields {
+ IP_VERSION = (1 << 0) /* 1 */,
+ SRC_IP_ADDR = (1 << 1) /* 2 */,
+ DST_IP_ADDR = (1 << 2) /* 4 */,
+ SRC_PORT = (1 << 3) /* 8 */,
+ DST_PORT = (1 << 4) /* 16 */,
+ DSCP = (1 << 5) /* 32 */,
+ PROTOCOL_NEXT_HDR = (1 << 6) /* 64 */,
+ FLOW_LABEL = (1 << 7) /* 128 */,
+ }
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl
new file mode 100644
index 0000000..b4d8e9d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable P2pExtListenInfo {
+ int periodMs;
+ int intervalMs;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
index 5465a86..e19ae44 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
@@ -45,4 +45,5 @@
byte[6] goInterfaceAddress;
boolean isP2pClientEapolIpAddressInfoPresent;
android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo p2pClientIpInfo;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
index 90e9f5e..5c7c393 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
@@ -37,4 +37,5 @@
String groupInterfaceName;
byte[6] clientInterfaceAddress;
byte[6] clientDeviceAddress;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
index 800f5b3..40c8ff6 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
@@ -38,4 +38,5 @@
byte[6] clientInterfaceAddress;
byte[6] clientDeviceAddress;
int clientIpAddress;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
index 587c7c6..46366cc 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
@@ -37,7 +37,8 @@
byte[6] p2pDeviceAddress;
boolean isRequest;
android.hardware.wifi.supplicant.P2pProvDiscStatusCode status;
- android.hardware.wifi.supplicant.WpsConfigMethods configMethods;
+ int configMethods;
String generatedPin;
String groupInterfaceName;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
index 983ed15..8b78a4a 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -24,6 +24,7 @@
import android.hardware.wifi.supplicant.MiracastMode;
import android.hardware.wifi.supplicant.P2pConnectInfo;
import android.hardware.wifi.supplicant.P2pDiscoveryInfo;
+import android.hardware.wifi.supplicant.P2pExtListenInfo;
import android.hardware.wifi.supplicant.P2pFrameTypeMask;
import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
import android.hardware.wifi.supplicant.WpsConfigMethods;
@@ -165,6 +166,9 @@
* (with interval obviously having to be larger than or equal to duration).
* If the P2P module is not idle at the time the Extended Listen Timing
* timeout occurs, the Listen State operation must be skipped.
+ * <p>
+ * @deprecated This method is deprecated from AIDL v3, newer HALs should use
+ * configureExtListenWithParams.
*
* @param periodInMillis Period in milliseconds.
* @param intervalInMillis Interval in milliseconds.
@@ -882,4 +886,21 @@
* |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
*/
void findWithParams(in P2pDiscoveryInfo discoveryInfo);
+
+ /**
+ * Configure Extended Listen Timing.
+ *
+ * If enabled, listen state must be entered every |intervalMs| for at
+ * least |periodMs|. Both values have acceptable range of 1-65535
+ * (note that the interval must be larger than or equal to the duration).
+ * If the P2P module is not idle at the time the Extended Listen Timing
+ * timeout occurs, the Listen State operation must be skipped.
+ *
+ * @param extListenInfo Parameters to configure extended listening timing.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void configureExtListenWithParams(in P2pExtListenInfo extListenInfo);
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
index 11cd867..b9273a8 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -40,7 +40,7 @@
/**
* Used to indicate that a P2P device has been found.
* <p>
- * @deprecated This callback is deprecated from AIDL v2, newer HAL should call
+ * @deprecated This callback is deprecated from AIDL v3, newer HAL should call
* onDeviceFoundWithParams.
*
* @param srcAddress MAC address of the device found. This must either
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index d7b4e62..fb1673e 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -29,6 +29,7 @@
import android.hardware.wifi.supplicant.IfaceType;
import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.MloLinksInfo;
+import android.hardware.wifi.supplicant.MscsParams;
import android.hardware.wifi.supplicant.QosPolicyScsData;
import android.hardware.wifi.supplicant.QosPolicyScsRequestStatus;
import android.hardware.wifi.supplicant.QosPolicyStatus;
@@ -852,4 +853,28 @@
* being processed. Supplicant will only handle one request at a time.
*/
QosPolicyScsRequestStatus[] removeQosPolicyForScs(in byte[] scsPolicyIds);
+
+ /**
+ * Enable Mirrored Stream Classification Service (MSCS) and configure using
+ * the provided configuration values.
+ *
+ * If MSCS has already been enabled/configured, this will overwrite the
+ * existing configuration.
+ *
+ * @param params |MscsParams| object containing the configuration.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID| if the configuration is invalid.
+ * |SupplicantStatusCode.FAILURE_UNKNOWN| if the configuration could not be set.
+ */
+ void configureMscs(in MscsParams params);
+
+ /**
+ * Disable Mirrored Stream Classification Service (MSCS).
+ *
+ * If MSCS is enabled/configured, this will send a remove request to the AP.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void disableMscs();
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 58893eb..172fcda 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -198,7 +198,7 @@
/**
* Used to indicate the result of Hotspot 2.0 Icon query.
*
- * @deprecated No longer in use.
+ * @deprecated This callback is deprecated from AIDL v3.
*
* @param bssid BSSID of the access point.
* @param fileName Name of the file that was requested.
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MscsParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MscsParams.aidl
new file mode 100644
index 0000000..b1731ac
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MscsParams.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.supplicant;
+
+/**
+ * Mirrored Stream Classification Service (MSCS) parameters.
+ * Refer to section 3.1 of the Wi-Fi QoS Management Specification v3.0.
+ */
+@VintfStability
+parcelable MscsParams {
+ /**
+ * Bitmap indicating which User Priorities should be classified using MSCS.
+ * The least significant bit corresponds to UP 0, and the most significant
+ * bit to UP 7. Setting a bit to 1 indicates that UP should be used.
+ */
+ byte upBitmap;
+
+ /**
+ * Maximum user priority that can be assigned using the MSCS service.
+ * Value must be between 0 and 7 (inclusive).
+ */
+ byte upLimit;
+
+ /**
+ * Stream timeout in μs. Must be equivalent to 60 sec or less.
+ */
+ int streamTimeoutUs;
+
+ /**
+ * Bitmask of available fields for a Type 4 TCLAS frame classifier.
+ * See Figures 9-309 and 9-310 in the IEEE Std 802.11-2020 Standard.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum FrameClassifierFields {
+ IP_VERSION = 1 << 0,
+ SRC_IP_ADDR = 1 << 1,
+ DST_IP_ADDR = 1 << 2,
+ SRC_PORT = 1 << 3,
+ DST_PORT = 1 << 4,
+ DSCP = 1 << 5,
+ /** Indicates Protocol if using IPv4, or Next Header if using IPv6. */
+ PROTOCOL_NEXT_HDR = 1 << 6,
+ /** Only applicable if using IPv6. */
+ FLOW_LABEL = 1 << 7,
+ }
+
+ /**
+ * Bitmask of |FrameClassifierFields| for a Type 4 TCLAS frame classifier.
+ */
+ byte frameClassifierMask;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl
new file mode 100644
index 0000000..1086c94
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pExtListenInfo.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2023 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.supplicant;
+
+import android.hardware.wifi.common.OuiKeyedData;
+
+/**
+ * Parameters used to configure the P2P Extended Listen Interval.
+ */
+@VintfStability
+parcelable P2pExtListenInfo {
+ /**
+ * Period in milliseconds.
+ */
+ int periodMs;
+ /**
+ * Interval in milliseconds.
+ */
+ int intervalMs;
+ /**
+ * Optional vendor-specific parameters. Null value indicates
+ * that no vendor data is provided.
+ */
+ @nullable OuiKeyedData[] vendorData;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
index 96f1e16..9db7a1e 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
@@ -16,6 +16,7 @@
package android.hardware.wifi.supplicant;
+import android.hardware.wifi.common.OuiKeyedData;
import android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo;
/**
@@ -63,4 +64,10 @@
* The value is undefined if isP2pClientEapolIpAddressInfoPresent is false.
*/
P2pClientEapolIpAddressInfo p2pClientIpInfo;
+
+ /**
+ * Optional vendor-specific parameters. Null value indicates
+ * that no vendor data is provided.
+ */
+ @nullable OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
index 936efd1..6e3350f 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientDisconnectedEventParams.aidl
@@ -16,6 +16,8 @@
package android.hardware.wifi.supplicant;
+import android.hardware.wifi.common.OuiKeyedData;
+
/**
* Parameters passed as a part of P2P peer client disconnected event.
*/
@@ -29,4 +31,10 @@
/** P2P device interface MAC address of the client that disconnected. */
byte[6] clientDeviceAddress;
+
+ /**
+ * Optional vendor-specific parameters. Null value indicates
+ * that no vendor data is provided.
+ */
+ @nullable OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
index 7eae2e5..4f46d70 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl
@@ -16,6 +16,8 @@
package android.hardware.wifi.supplicant;
+import android.hardware.wifi.common.OuiKeyedData;
+
/**
* Parameters passed as a part of P2P peer client joined event.
*/
@@ -39,4 +41,10 @@
* The value is set to zero if the IP address is not allocated via EAPOL exchange.
*/
int clientIpAddress;
+
+ /**
+ * Optional vendor-specific parameters. Null value indicates
+ * that no vendor data is provided.
+ */
+ @nullable OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
index 7fa7f22..05152a9 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl
@@ -16,8 +16,8 @@
package android.hardware.wifi.supplicant;
+import android.hardware.wifi.common.OuiKeyedData;
import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
-import android.hardware.wifi.supplicant.WpsConfigMethods;
/**
* Parameters passed as a part of P2P provision discovery frame notification.
@@ -33,8 +33,8 @@
boolean isRequest;
/** Status of the provision discovery */
P2pProvDiscStatusCode status;
- /** Mask of WPS configuration methods supported */
- WpsConfigMethods configMethods;
+ /** Mask of |WpsConfigMethods| indicating the supported methods */
+ int configMethods;
/** 8-digit pin generated */
String generatedPin;
/**
@@ -45,4 +45,9 @@
* Refer to WFA Wi-Fi_Direct_Specification_v1.9 section 3.2.1 for more details.
*/
String groupInterfaceName;
+ /**
+ * Optional vendor-specific parameters. Null value indicates
+ * that no vendor data is provided.
+ */
+ @nullable OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
index b2356a0..96c13e7 100644
--- a/wifi/supplicant/aidl/vts/functional/Android.bp
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -51,7 +51,8 @@
"VtsHalWifiV1_0TargetTestUtil",
"VtsHalWifiV1_5TargetTestUtil",
"VtsHalWifiSupplicantV1_0TargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"VtsHalWifiTargetTestUtil",
],
test_suites: [
@@ -88,7 +89,8 @@
"VtsHalWifiV1_0TargetTestUtil",
"VtsHalWifiV1_5TargetTestUtil",
"VtsHalWifiSupplicantV1_0TargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"VtsHalWifiTargetTestUtil",
],
test_suites: [
@@ -125,7 +127,8 @@
"VtsHalWifiV1_0TargetTestUtil",
"VtsHalWifiV1_5TargetTestUtil",
"VtsHalWifiSupplicantV1_0TargetTestUtil",
- "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.common-V1-ndk",
+ "android.hardware.wifi-V2-ndk",
"VtsHalWifiTargetTestUtil",
],
test_suites: [
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
index 7574141..e5e9735 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -110,6 +110,7 @@
initializeService();
supplicant_ = getSupplicant(GetParam().c_str());
ASSERT_NE(supplicant_, nullptr);
+ ASSERT_TRUE(supplicant_->getInterfaceVersion(&interface_version_).isOk());
ASSERT_TRUE(supplicant_
->setDebugParams(DebugLevel::EXCESSIVE,
true, // show timestamps
@@ -131,6 +132,7 @@
std::shared_ptr<ISupplicant> supplicant_;
std::shared_ptr<ISupplicantStaIface> sta_iface_;
std::shared_ptr<ISupplicantStaNetwork> sta_network_;
+ int interface_version_;
void removeNetwork() {
ASSERT_NE(sta_iface_, nullptr);
@@ -826,6 +828,9 @@
* disableEht
*/
TEST_P(SupplicantStaNetworkAidlTest, DisableEht) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "disableEht is available as of Supplicant V3";
+ }
EXPECT_TRUE(sta_network_->disableEht().isOk());
}