Merge "Add the new RIL requests to start/stop network scan"
diff --git a/audio/2.0/default/Device.cpp b/audio/2.0/default/Device.cpp
index da79238..280d320 100644
--- a/audio/2.0/default/Device.cpp
+++ b/audio/2.0/default/Device.cpp
@@ -1,18 +1,18 @@
- /*
- * Copyright (C) 2016 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.
- */
+/*
+* Copyright (C) 2016 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 "DeviceHAL"
//#define LOG_NDEBUG 0
@@ -30,6 +30,7 @@
#include "HidlUtils.h"
#include "StreamIn.h"
#include "StreamOut.h"
+#include "Util.h"
namespace android {
namespace hardware {
@@ -92,7 +93,8 @@
Device::~Device() {
int status = audio_hw_device_close(mDevice);
- ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
+ ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice,
+ strerror(-status));
mDevice = nullptr;
}
@@ -101,12 +103,18 @@
ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
}
switch (status) {
- case 0: return Result::OK;
- case -EINVAL: return Result::INVALID_ARGUMENTS;
- case -ENODATA: return Result::INVALID_STATE;
- case -ENODEV: return Result::NOT_INITIALIZED;
- case -ENOSYS: return Result::NOT_SUPPORTED;
- default: return Result::INVALID_STATE;
+ case 0:
+ return Result::OK;
+ case -EINVAL:
+ return Result::INVALID_ARGUMENTS;
+ case -ENODATA:
+ return Result::INVALID_STATE;
+ case -ENODEV:
+ return Result::NOT_INITIALIZED;
+ case -ENOSYS:
+ return Result::NOT_SUPPORTED;
+ default:
+ return Result::INVALID_STATE;
}
}
@@ -129,59 +137,67 @@
}
// Methods from ::android::hardware::audio::V2_0::IDevice follow.
-Return<Result> Device::initCheck() {
+Return<Result> Device::initCheck() {
return analyzeStatus("init_check", mDevice->init_check(mDevice));
}
-Return<Result> Device::setMasterVolume(float volume) {
- Result retval(Result::NOT_SUPPORTED);
- if (mDevice->set_master_volume != NULL) {
- retval = analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+Return<Result> Device::setMasterVolume(float volume) {
+ if (mDevice->set_master_volume == NULL) {
+ return Result::NOT_SUPPORTED;
}
- return retval;
+ if (!isGainNormalized(volume)) {
+ ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
+ return Result::INVALID_ARGUMENTS;
+ }
+ return analyzeStatus("set_master_volume",
+ mDevice->set_master_volume(mDevice, volume));
}
-Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
+Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
float volume = 0;
if (mDevice->get_master_volume != NULL) {
- retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+ retval = analyzeStatus("get_master_volume",
+ mDevice->get_master_volume(mDevice, &volume));
}
_hidl_cb(retval, volume);
return Void();
}
-Return<Result> Device::setMicMute(bool mute) {
+Return<Result> Device::setMicMute(bool mute) {
return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
}
-Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
+Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
bool mute = false;
- Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+ Result retval =
+ analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
_hidl_cb(retval, mute);
return Void();
}
-Return<Result> Device::setMasterMute(bool mute) {
+Return<Result> Device::setMasterMute(bool mute) {
Result retval(Result::NOT_SUPPORTED);
if (mDevice->set_master_mute != NULL) {
- retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+ retval = analyzeStatus("set_master_mute",
+ mDevice->set_master_mute(mDevice, mute));
}
return retval;
}
-Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
+Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
bool mute = false;
if (mDevice->get_master_mute != NULL) {
- retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+ retval = analyzeStatus("get_master_mute",
+ mDevice->get_master_mute(mDevice, &mute));
}
_hidl_cb(retval, mute);
return Void();
}
-Return<void> Device::getInputBufferSize(
- const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
+Return<void> Device::getInputBufferSize(const AudioConfig& config,
+ getInputBufferSize_cb _hidl_cb) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
@@ -195,29 +211,25 @@
return Void();
}
-Return<void> Device::openOutputStream(
- int32_t ioHandle,
- const DeviceAddress& device,
- const AudioConfig& config,
- AudioOutputFlag flags,
- openOutputStream_cb _hidl_cb) {
+Return<void> Device::openOutputStream(int32_t ioHandle,
+ const DeviceAddress& device,
+ const AudioConfig& config,
+ AudioOutputFlag flags,
+ openOutputStream_cb _hidl_cb) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
- audio_stream_out_t *halStream;
- ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
- "srate: %d format %#x channels %x address %s",
- ioHandle,
- static_cast<audio_devices_t>(device.device), static_cast<audio_output_flags_t>(flags),
- halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
- deviceAddressToHal(device).c_str());
+ audio_stream_out_t* halStream;
+ ALOGV(
+ "open_output_stream handle: %d devices: %x flags: %#x "
+ "srate: %d format %#x channels %x address %s",
+ ioHandle, static_cast<audio_devices_t>(device.device),
+ static_cast<audio_output_flags_t>(flags), halConfig.sample_rate,
+ halConfig.format, halConfig.channel_mask,
+ deviceAddressToHal(device).c_str());
int status = mDevice->open_output_stream(
- mDevice,
- ioHandle,
- static_cast<audio_devices_t>(device.device),
- static_cast<audio_output_flags_t>(flags),
- &halConfig,
- &halStream,
- deviceAddressToHal(device).c_str());
+ mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
+ static_cast<audio_output_flags_t>(flags), &halConfig, &halStream,
+ deviceAddressToHal(device).c_str());
ALOGV("open_output_stream status %d stream %p", status, halStream);
sp<IStreamOut> streamOut;
if (status == OK) {
@@ -225,35 +237,32 @@
}
AudioConfig suggestedConfig;
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
- _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
+ _hidl_cb(analyzeStatus("open_output_stream", status), streamOut,
+ suggestedConfig);
return Void();
}
-Return<void> Device::openInputStream(
- int32_t ioHandle,
- const DeviceAddress& device,
- const AudioConfig& config,
- AudioInputFlag flags,
- AudioSource source,
- openInputStream_cb _hidl_cb) {
+Return<void> Device::openInputStream(int32_t ioHandle,
+ const DeviceAddress& device,
+ const AudioConfig& config,
+ AudioInputFlag flags, AudioSource source,
+ openInputStream_cb _hidl_cb) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
- audio_stream_in_t *halStream;
- ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
- "srate: %d format %#x channels %x address %s source %d",
- ioHandle,
- static_cast<audio_devices_t>(device.device), static_cast<audio_input_flags_t>(flags),
- halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
- deviceAddressToHal(device).c_str(), static_cast<audio_source_t>(source));
+ audio_stream_in_t* halStream;
+ ALOGV(
+ "open_input_stream handle: %d devices: %x flags: %#x "
+ "srate: %d format %#x channels %x address %s source %d",
+ ioHandle, static_cast<audio_devices_t>(device.device),
+ static_cast<audio_input_flags_t>(flags), halConfig.sample_rate,
+ halConfig.format, halConfig.channel_mask,
+ deviceAddressToHal(device).c_str(),
+ static_cast<audio_source_t>(source));
int status = mDevice->open_input_stream(
- mDevice,
- ioHandle,
- static_cast<audio_devices_t>(device.device),
- &halConfig,
- &halStream,
- static_cast<audio_input_flags_t>(flags),
- deviceAddressToHal(device).c_str(),
- static_cast<audio_source_t>(source));
+ mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
+ &halConfig, &halStream, static_cast<audio_input_flags_t>(flags),
+ deviceAddressToHal(device).c_str(),
+ static_cast<audio_source_t>(source));
ALOGV("open_input_stream status %d stream %p", status, halStream);
sp<IStreamIn> streamIn;
if (status == OK) {
@@ -261,7 +270,8 @@
}
AudioConfig suggestedConfig;
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
- _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
+ _hidl_cb(analyzeStatus("open_input_stream", status), streamIn,
+ suggestedConfig);
return Void();
}
@@ -269,23 +279,21 @@
return version() >= AUDIO_DEVICE_API_VERSION_3_0;
}
-Return<void> Device::createAudioPatch(
- const hidl_vec<AudioPortConfig>& sources,
- const hidl_vec<AudioPortConfig>& sinks,
- createAudioPatch_cb _hidl_cb) {
+Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
+ const hidl_vec<AudioPortConfig>& sinks,
+ createAudioPatch_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
AudioPatchHandle patch = 0;
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
- std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
+ std::unique_ptr<audio_port_config[]> halSources(
+ HidlUtils::audioPortConfigsToHal(sources));
+ std::unique_ptr<audio_port_config[]> halSinks(
+ HidlUtils::audioPortConfigsToHal(sinks));
audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
retval = analyzeStatus(
- "create_audio_patch",
- mDevice->create_audio_patch(
- mDevice,
- sources.size(), &halSources[0],
- sinks.size(), &halSinks[0],
- &halPatch));
+ "create_audio_patch",
+ mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
+ sinks.size(), &halSinks[0], &halPatch));
if (retval == Result::OK) {
patch = static_cast<AudioPatchHandle>(halPatch);
}
@@ -294,19 +302,22 @@
return Void();
}
-Return<Result> Device::releaseAudioPatch(int32_t patch) {
+Return<Result> Device::releaseAudioPatch(int32_t patch) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
return analyzeStatus(
- "release_audio_patch",
- mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
+ "release_audio_patch",
+ mDevice->release_audio_patch(
+ mDevice, static_cast<audio_patch_handle_t>(patch)));
}
return Result::NOT_SUPPORTED;
}
-Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
+Return<void> Device::getAudioPort(const AudioPort& port,
+ getAudioPort_cb _hidl_cb) {
audio_port halPort;
HidlUtils::audioPortToHal(port, &halPort);
- Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
+ Result retval = analyzeStatus("get_audio_port",
+ mDevice->get_audio_port(mDevice, &halPort));
AudioPort resultPort = port;
if (retval == Result::OK) {
HidlUtils::audioPortFromHal(halPort, &resultPort);
@@ -315,36 +326,39 @@
return Void();
}
-Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
+Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
struct audio_port_config halPortConfig;
HidlUtils::audioPortConfigToHal(config, &halPortConfig);
return analyzeStatus(
- "set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
+ "set_audio_port_config",
+ mDevice->set_audio_port_config(mDevice, &halPortConfig));
}
return Result::NOT_SUPPORTED;
}
-Return<AudioHwSync> Device::getHwAvSync() {
+Return<AudioHwSync> Device::getHwAvSync() {
int halHwAvSync;
Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
}
-Return<Result> Device::setScreenState(bool turnedOn) {
+Return<Result> Device::setScreenState(bool turnedOn) {
return setParam(AudioParameter::keyScreenState, turnedOn);
}
-Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys,
+ getParameters_cb _hidl_cb) {
getParametersImpl(keys, _hidl_cb);
return Void();
}
-Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
+Return<Result> Device::setParameters(
+ const hidl_vec<ParameterValue>& parameters) {
return setParametersImpl(parameters);
}
-Return<void> Device::debugDump(const hidl_handle& fd) {
+Return<void> Device::debugDump(const hidl_handle& fd) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
}
diff --git a/audio/2.0/default/ParametersUtil.cpp b/audio/2.0/default/ParametersUtil.cpp
index 75a60b9..5cc60db 100644
--- a/audio/2.0/default/ParametersUtil.cpp
+++ b/audio/2.0/default/ParametersUtil.cpp
@@ -22,11 +22,31 @@
namespace V2_0 {
namespace implementation {
+// Static method and not private method to avoid leaking status_t dependency
+static Result getHalStatusToResult(status_t status) {
+ switch (status) {
+ case OK:
+ return Result::OK;
+ case BAD_VALUE: // Nothing was returned, probably because the HAL does
+ // not handle it
+ return Result::NOT_SUPPORTED;
+ case INVALID_OPERATION: // Conversion from string to the requested type
+ // failed
+ return Result::INVALID_ARGUMENTS;
+ default: // Should not happen
+ ALOGW("Unexpected status returned by getParam: %u", status);
+ return Result::INVALID_ARGUMENTS;
+ }
+}
+
Result ParametersUtil::getParam(const char* name, bool* value) {
String8 halValue;
Result retval = getParam(name, &halValue);
*value = false;
if (retval == Result::OK) {
+ if (halValue.empty()) {
+ return Result::NOT_SUPPORTED;
+ }
*value = !(halValue == AudioParameter::valueOff);
}
return retval;
@@ -37,8 +57,7 @@
AudioParameter keys;
keys.addKey(halName);
std::unique_ptr<AudioParameter> params = getParams(keys);
- status_t halStatus = params->getInt(halName, *value);
- return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+ return getHalStatusToResult(params->getInt(halName, *value));
}
Result ParametersUtil::getParam(const char* name, String8* value) {
@@ -46,42 +65,41 @@
AudioParameter keys;
keys.addKey(halName);
std::unique_ptr<AudioParameter> params = getParams(keys);
- status_t halStatus = params->get(halName, *value);
- return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+ return getHalStatusToResult(params->get(halName, *value));
}
void ParametersUtil::getParametersImpl(
- const hidl_vec<hidl_string>& keys,
- std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb) {
+ const hidl_vec<hidl_string>& keys,
+ std::function<void(Result retval,
+ const hidl_vec<ParameterValue>& parameters)>
+ cb) {
AudioParameter halKeys;
for (size_t i = 0; i < keys.size(); ++i) {
halKeys.addKey(String8(keys[i].c_str()));
}
std::unique_ptr<AudioParameter> halValues = getParams(halKeys);
- Result retval(Result::INVALID_ARGUMENTS);
+ Result retval =
+ halValues->size() == keys.size() ? Result::OK : Result::NOT_SUPPORTED;
hidl_vec<ParameterValue> result;
- if (halValues->size() > 0) {
- result.resize(halValues->size());
- String8 halKey, halValue;
- for (size_t i = 0; i < halValues->size(); ++i) {
- status_t status = halValues->getAt(i, halKey, halValue);
- if (status != OK) {
- result.resize(0);
- break;
- }
- result[i].key = halKey.string();
- result[i].value = halValue.string();
+ result.resize(halValues->size());
+ String8 halKey, halValue;
+ for (size_t i = 0; i < halValues->size(); ++i) {
+ status_t status = halValues->getAt(i, halKey, halValue);
+ if (status != OK) {
+ result.resize(0);
+ retval = getHalStatusToResult(status);
+ break;
}
- if (result.size() != 0) {
- retval = Result::OK;
- }
+ result[i].key = halKey.string();
+ result[i].value = halValue.string();
}
cb(retval, result);
}
-std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
+std::unique_ptr<AudioParameter> ParametersUtil::getParams(
+ const AudioParameter& keys) {
String8 paramsAndValues;
- char *halValues = halGetParameters(keys.keysToString().string());
+ char* halValues = halGetParameters(keys.keysToString().string());
if (halValues != NULL) {
paramsAndValues.setTo(halValues);
free(halValues);
@@ -93,7 +111,8 @@
Result ParametersUtil::setParam(const char* name, bool value) {
AudioParameter param;
- param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
+ param.add(String8(name), String8(value ? AudioParameter::valueOn
+ : AudioParameter::valueOff));
return setParams(param);
}
@@ -109,10 +128,12 @@
return setParams(param);
}
-Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& parameters) {
+Result ParametersUtil::setParametersImpl(
+ const hidl_vec<ParameterValue>& parameters) {
AudioParameter params;
for (size_t i = 0; i < parameters.size(); ++i) {
- params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
+ params.add(String8(parameters[i].key.c_str()),
+ String8(parameters[i].value.c_str()));
}
return setParams(params);
}
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/2.0/default/PrimaryDevice.cpp
index af0b249..4e8f30f 100644
--- a/audio/2.0/default/PrimaryDevice.cpp
+++ b/audio/2.0/default/PrimaryDevice.cpp
@@ -30,56 +30,52 @@
PrimaryDevice::~PrimaryDevice() {}
// Methods from ::android::hardware::audio::V2_0::IDevice follow.
-Return<Result> PrimaryDevice::initCheck() {
+Return<Result> PrimaryDevice::initCheck() {
return mDevice->initCheck();
}
-Return<Result> PrimaryDevice::setMasterVolume(float volume) {
+Return<Result> PrimaryDevice::setMasterVolume(float volume) {
return mDevice->setMasterVolume(volume);
}
-Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
+Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
return mDevice->getMasterVolume(_hidl_cb);
}
-Return<Result> PrimaryDevice::setMicMute(bool mute) {
+Return<Result> PrimaryDevice::setMicMute(bool mute) {
return mDevice->setMicMute(mute);
}
-Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
+Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
return mDevice->getMicMute(_hidl_cb);
}
-Return<Result> PrimaryDevice::setMasterMute(bool mute) {
+Return<Result> PrimaryDevice::setMasterMute(bool mute) {
return mDevice->setMasterMute(mute);
}
-Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
+Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
return mDevice->getMasterMute(_hidl_cb);
}
-Return<void> PrimaryDevice::getInputBufferSize(
- const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
+Return<void> PrimaryDevice::getInputBufferSize(const AudioConfig& config,
+ getInputBufferSize_cb _hidl_cb) {
return mDevice->getInputBufferSize(config, _hidl_cb);
}
-Return<void> PrimaryDevice::openOutputStream(
- int32_t ioHandle,
- const DeviceAddress& device,
- const AudioConfig& config,
- AudioOutputFlag flags,
- openOutputStream_cb _hidl_cb) {
+Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle,
+ const DeviceAddress& device,
+ const AudioConfig& config,
+ AudioOutputFlag flags,
+ openOutputStream_cb _hidl_cb) {
return mDevice->openOutputStream(ioHandle, device, config, flags, _hidl_cb);
}
Return<void> PrimaryDevice::openInputStream(
- int32_t ioHandle,
- const DeviceAddress& device,
- const AudioConfig& config,
- AudioInputFlag flags,
- AudioSource source,
- openInputStream_cb _hidl_cb) {
- return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
+ int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+ AudioInputFlag flags, AudioSource source, openInputStream_cb _hidl_cb) {
+ return mDevice->openInputStream(ioHandle, device, config, flags, source,
+ _hidl_cb);
}
Return<bool> PrimaryDevice::supportsAudioPatches() {
@@ -87,82 +83,97 @@
}
Return<void> PrimaryDevice::createAudioPatch(
- const hidl_vec<AudioPortConfig>& sources,
- const hidl_vec<AudioPortConfig>& sinks,
- createAudioPatch_cb _hidl_cb) {
+ const hidl_vec<AudioPortConfig>& sources,
+ const hidl_vec<AudioPortConfig>& sinks, createAudioPatch_cb _hidl_cb) {
return mDevice->createAudioPatch(sources, sinks, _hidl_cb);
}
-Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch) {
+Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch) {
return mDevice->releaseAudioPatch(patch);
}
-Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
+Return<void> PrimaryDevice::getAudioPort(const AudioPort& port,
+ getAudioPort_cb _hidl_cb) {
return mDevice->getAudioPort(port, _hidl_cb);
}
-Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
+Return<Result> PrimaryDevice::setAudioPortConfig(
+ const AudioPortConfig& config) {
return mDevice->setAudioPortConfig(config);
}
-Return<AudioHwSync> PrimaryDevice::getHwAvSync() {
+Return<AudioHwSync> PrimaryDevice::getHwAvSync() {
return mDevice->getHwAvSync();
}
-Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
+Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
return mDevice->setScreenState(turnedOn);
}
-Return<void> PrimaryDevice::getParameters(
- const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+Return<void> PrimaryDevice::getParameters(const hidl_vec<hidl_string>& keys,
+ getParameters_cb _hidl_cb) {
return mDevice->getParameters(keys, _hidl_cb);
}
-Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& parameters) {
+Return<Result> PrimaryDevice::setParameters(
+ const hidl_vec<ParameterValue>& parameters) {
return mDevice->setParameters(parameters);
}
-Return<void> PrimaryDevice::debugDump(const hidl_handle& fd) {
+Return<void> PrimaryDevice::debugDump(const hidl_handle& fd) {
return mDevice->debugDump(fd);
}
-
// Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
-Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
+Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
return mDevice->analyzeStatus(
- "set_voice_volume",
- mDevice->device()->set_voice_volume(mDevice->device(), volume));
+ "set_voice_volume",
+ mDevice->device()->set_voice_volume(mDevice->device(), volume));
}
-Return<Result> PrimaryDevice::setMode(AudioMode mode) {
+Return<Result> PrimaryDevice::setMode(AudioMode mode) {
+ // INVALID, CURRENT, CNT, MAX are reserved for internal use.
+ // TODO: remove the values from the HIDL interface
+ switch (mode) {
+ case AudioMode::NORMAL:
+ case AudioMode::RINGTONE:
+ case AudioMode::IN_CALL:
+ case AudioMode::IN_COMMUNICATION:
+ break; // Valid values
+ default:
+ return Result::INVALID_ARGUMENTS;
+ };
+
return mDevice->analyzeStatus(
- "set_mode",
- mDevice->device()->set_mode(mDevice->device(), static_cast<audio_mode_t>(mode)));
+ "set_mode", mDevice->device()->set_mode(
+ mDevice->device(), static_cast<audio_mode_t>(mode)));
}
-Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
+Return<void> PrimaryDevice::getBtScoNrecEnabled(
+ getBtScoNrecEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
-Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
+Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
return mDevice->setParam(AudioParameter::keyBtNrec, enabled);
}
-Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) {
+Return<void> PrimaryDevice::getBtScoWidebandEnabled(
+ getBtScoWidebandEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
-Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
+Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, enabled);
}
-Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
+Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
int halMode;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_TTY_MODE, &halMode);
TtyMode mode = retval == Result::OK ? TtyMode(halMode) : TtyMode::OFF;
@@ -170,18 +181,19 @@
return Void();
}
-Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
- return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, static_cast<int>(mode));
+Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
+ return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE,
+ static_cast<int>(mode));
}
-Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
+Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HAC, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
-Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
+Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled);
}
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
index e5a1a55..abd0497 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/2.0/default/StreamIn.cpp
@@ -20,10 +20,11 @@
#include <android/log.h>
#include <hardware/audio.h>
-#include <memory>
#include <utils/Trace.h>
+#include <memory>
#include "StreamIn.h"
+#include "Util.h"
using ::android::hardware::audio::V2_0::MessageQueueFlagBits;
@@ -38,30 +39,26 @@
namespace {
class ReadThread : public Thread {
- public:
+ public:
// ReadThread's lifespan never exceeds StreamIn's lifespan.
- ReadThread(std::atomic<bool>* stop,
- audio_stream_in_t* stream,
- StreamIn::CommandMQ* commandMQ,
- StreamIn::DataMQ* dataMQ,
- StreamIn::StatusMQ* statusMQ,
- EventFlag* efGroup)
- : Thread(false /*canCallJava*/),
- mStop(stop),
- mStream(stream),
- mCommandMQ(commandMQ),
- mDataMQ(dataMQ),
- mStatusMQ(statusMQ),
- mEfGroup(efGroup),
- mBuffer(nullptr) {
- }
+ ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream,
+ StreamIn::CommandMQ* commandMQ, StreamIn::DataMQ* dataMQ,
+ StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
+ : Thread(false /*canCallJava*/),
+ mStop(stop),
+ mStream(stream),
+ mCommandMQ(commandMQ),
+ mDataMQ(dataMQ),
+ mStatusMQ(statusMQ),
+ mEfGroup(efGroup),
+ mBuffer(nullptr) {}
bool init() {
- mBuffer.reset(new(std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
+ mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
return mBuffer != nullptr;
}
virtual ~ReadThread() {}
- private:
+ private:
std::atomic<bool>* mStop;
audio_stream_in_t* mStream;
StreamIn::CommandMQ* mCommandMQ;
@@ -82,8 +79,10 @@
size_t availableToWrite = mDataMQ->availableToWrite();
size_t requestedToRead = mParameters.params.read;
if (requestedToRead > availableToWrite) {
- ALOGW("truncating read data from %d to %d due to insufficient data queue space",
- (int32_t)requestedToRead, (int32_t)availableToWrite);
+ ALOGW(
+ "truncating read data from %d to %d due to insufficient data queue "
+ "space",
+ (int32_t)requestedToRead, (int32_t)availableToWrite);
requestedToRead = availableToWrite;
}
ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
@@ -101,16 +100,20 @@
void ReadThread::doGetCapturePosition() {
mStatus.retval = StreamIn::getCapturePositionImpl(
- mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
+ mStream, &mStatus.reply.capturePosition.frames,
+ &mStatus.reply.capturePosition.time);
}
bool ReadThread::threadLoop() {
- // This implementation doesn't return control back to the Thread until it decides to stop,
+ // This implementation doesn't return control back to the Thread until it
+ // decides to stop,
// as the Thread uses mutexes, and this can lead to priority inversion.
- while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+ while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
uint32_t efState = 0;
- mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
- if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
+ mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL),
+ &efState);
+ if (!(efState &
+ static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
continue; // Nothing to do.
}
if (!mCommandMQ->read(&mParameters)) {
@@ -125,7 +128,8 @@
doGetCapturePosition();
break;
default:
- ALOGE("Unknown read thread command code %d", mParameters.command);
+ ALOGE("Unknown read thread command code %d",
+ mParameters.command);
mStatus.retval = Result::NOT_SUPPORTED;
break;
}
@@ -141,11 +145,13 @@
} // namespace
StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
- : mIsClosed(false), mDevice(device), mStream(stream),
- mStreamCommon(new Stream(&stream->common)),
- mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
- mEfGroup(nullptr), mStopReadThread(false) {
-}
+ : mIsClosed(false),
+ mDevice(device),
+ mStream(stream),
+ mStreamCommon(new Stream(&stream->common)),
+ mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
+ mEfGroup(nullptr),
+ mStopReadThread(false) {}
StreamIn::~StreamIn() {
ATRACE_CALL();
@@ -157,102 +163,108 @@
}
if (mEfGroup) {
status_t status = EventFlag::deleteEventFlag(&mEfGroup);
- ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
+ ALOGE_IF(status, "read MQ event flag deletion error: %s",
+ strerror(-status));
}
mDevice->closeInputStream(mStream);
mStream = nullptr;
}
// Methods from ::android::hardware::audio::V2_0::IStream follow.
-Return<uint64_t> StreamIn::getFrameSize() {
+Return<uint64_t> StreamIn::getFrameSize() {
return audio_stream_in_frame_size(mStream);
}
-Return<uint64_t> StreamIn::getFrameCount() {
+Return<uint64_t> StreamIn::getFrameCount() {
return mStreamCommon->getFrameCount();
}
-Return<uint64_t> StreamIn::getBufferSize() {
+Return<uint64_t> StreamIn::getBufferSize() {
return mStreamCommon->getBufferSize();
}
-Return<uint32_t> StreamIn::getSampleRate() {
+Return<uint32_t> StreamIn::getSampleRate() {
return mStreamCommon->getSampleRate();
}
-Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
+Return<void> StreamIn::getSupportedSampleRates(
+ getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(_hidl_cb);
}
-Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
+Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
return mStreamCommon->setSampleRate(sampleRateHz);
}
-Return<AudioChannelMask> StreamIn::getChannelMask() {
+Return<AudioChannelMask> StreamIn::getChannelMask() {
return mStreamCommon->getChannelMask();
}
-Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
+Return<void> StreamIn::getSupportedChannelMasks(
+ getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
}
-Return<Result> StreamIn::setChannelMask(AudioChannelMask mask) {
+Return<Result> StreamIn::setChannelMask(AudioChannelMask mask) {
return mStreamCommon->setChannelMask(mask);
}
-Return<AudioFormat> StreamIn::getFormat() {
+Return<AudioFormat> StreamIn::getFormat() {
return mStreamCommon->getFormat();
}
-Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
+Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
return mStreamCommon->getSupportedFormats(_hidl_cb);
}
-Return<Result> StreamIn::setFormat(AudioFormat format) {
+Return<Result> StreamIn::setFormat(AudioFormat format) {
return mStreamCommon->setFormat(format);
}
-Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
+Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
return mStreamCommon->getAudioProperties(_hidl_cb);
}
-Return<Result> StreamIn::addEffect(uint64_t effectId) {
+Return<Result> StreamIn::addEffect(uint64_t effectId) {
return mStreamCommon->addEffect(effectId);
}
-Return<Result> StreamIn::removeEffect(uint64_t effectId) {
+Return<Result> StreamIn::removeEffect(uint64_t effectId) {
return mStreamCommon->removeEffect(effectId);
}
-Return<Result> StreamIn::standby() {
+Return<Result> StreamIn::standby() {
return mStreamCommon->standby();
}
-Return<AudioDevice> StreamIn::getDevice() {
+Return<AudioDevice> StreamIn::getDevice() {
return mStreamCommon->getDevice();
}
-Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
+Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
return mStreamCommon->setDevice(address);
}
-Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
+Return<Result> StreamIn::setConnectedState(const DeviceAddress& address,
+ bool connected) {
return mStreamCommon->setConnectedState(address, connected);
}
-Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
+Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
return mStreamCommon->setHwAvSync(hwAvSync);
}
-Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys,
+ getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(keys, _hidl_cb);
}
-Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
+Return<Result> StreamIn::setParameters(
+ const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(parameters);
}
-Return<void> StreamIn::debugDump(const hidl_handle& fd) {
+Return<void> StreamIn::debugDump(const hidl_handle& fd) {
return mStreamCommon->debugDump(fd);
}
@@ -264,16 +276,17 @@
return mStreamMmap->stop();
}
-Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames,
+ createMmapBuffer_cb _hidl_cb) {
return mStreamMmap->createMmapBuffer(
- minSizeFrames, audio_stream_in_frame_size(mStream), _hidl_cb);
+ minSizeFrames, audio_stream_in_frame_size(mStream), _hidl_cb);
}
Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
return mStreamMmap->getMmapPosition(_hidl_cb);
}
-Return<Result> StreamIn::close() {
+Return<Result> StreamIn::close() {
if (mIsClosed) return Result::INVALID_STATE;
mIsClosed = true;
if (mReadThread.get()) {
@@ -286,9 +299,10 @@
}
// Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
-Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
+Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
int halSource;
- Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
+ Result retval =
+ mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
AudioSource source(AudioSource::DEFAULT);
if (retval == Result::OK) {
source = AudioSource(halSource);
@@ -297,68 +311,89 @@
return Void();
}
-Return<Result> StreamIn::setGain(float gain) {
+Return<Result> StreamIn::setGain(float gain) {
+ if (!isGainNormalized(gain)) {
+ ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
+ return Result::INVALID_ARGUMENTS;
+ }
return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
}
-Return<void> StreamIn::prepareForReading(
- uint32_t frameSize, uint32_t framesCount, prepareForReading_cb _hidl_cb) {
+Return<void> StreamIn::prepareForReading(uint32_t frameSize,
+ uint32_t framesCount,
+ prepareForReading_cb _hidl_cb) {
status_t status;
- ThreadInfo threadInfo = { 0, 0 };
+ ThreadInfo threadInfo = {0, 0};
+
+ // Wrap the _hidl_cb to return an error
+ auto sendError = [this, &threadInfo, &_hidl_cb](Result result) {
+ _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(),
+ StatusMQ::Descriptor(), threadInfo);
+
+ };
+
// Create message queues.
if (mDataMQ) {
ALOGE("the client attempts to call prepareForReading twice");
- _hidl_cb(Result::INVALID_STATE,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_STATE);
return Void();
}
std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
- if (frameSize > std::numeric_limits<size_t>::max() / framesCount) {
- ALOGE("Requested buffer is too big, %d*%d can not fit in size_t", frameSize, framesCount);
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+
+ // Check frameSize and framesCount
+ if (frameSize == 0 || framesCount == 0) {
+ ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize,
+ framesCount);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
- std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
+ // A message queue asserts if it can not handle the requested buffer,
+ // thus the client has to guess the maximum size it can handle
+ // Choose an arbitrary margin for the overhead of a message queue
+ size_t metadataOverhead = 100000;
+ if (frameSize >
+ (std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
+ ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
+ frameSize, framesCount);
+ sendError(Result::INVALID_ARGUMENTS);
+ return Void();
+ }
+ std::unique_ptr<DataMQ> tempDataMQ(
+ new DataMQ(frameSize * framesCount, true /* EventFlag */));
std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
- if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+ if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() ||
+ !tempStatusMQ->isValid()) {
ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
EventFlag* tempRawEfGroup{};
- status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
- std::unique_ptr<EventFlag, void(*)(EventFlag*)> tempElfGroup(tempRawEfGroup, [](auto *ef) {
- EventFlag::deleteEventFlag(&ef); });
+ status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(),
+ &tempRawEfGroup);
+ std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
+ tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
if (status != OK || !tempElfGroup) {
ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
// Create and launch the thread.
auto tempReadThread = std::make_unique<ReadThread>(
- &mStopReadThread,
- mStream,
- tempCommandMQ.get(),
- tempDataMQ.get(),
- tempStatusMQ.get(),
- tempElfGroup.get());
+ &mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+ tempStatusMQ.get(), tempElfGroup.get());
if (!tempReadThread->init()) {
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ ALOGW("failed to start reader thread: %s", strerror(-status));
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO);
if (status != OK) {
ALOGW("failed to start reader thread: %s", strerror(-status));
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
@@ -369,28 +404,27 @@
mEfGroup = tempElfGroup.release();
threadInfo.pid = getpid();
threadInfo.tid = mReadThread->getTid();
- _hidl_cb(Result::OK,
- *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
- threadInfo);
+ _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(),
+ *mStatusMQ->getDesc(), threadInfo);
return Void();
}
-Return<uint32_t> StreamIn::getInputFramesLost() {
+Return<uint32_t> StreamIn::getInputFramesLost() {
return mStream->get_input_frames_lost(mStream);
}
// static
-Result StreamIn::getCapturePositionImpl(
- audio_stream_in_t *stream, uint64_t *frames, uint64_t *time) {
+Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream,
+ uint64_t* frames, uint64_t* time) {
Result retval(Result::NOT_SUPPORTED);
if (stream->get_capture_position != NULL) return retval;
int64_t halFrames, halTime;
retval = Stream::analyzeStatus(
- "get_capture_position",
- stream->get_capture_position(stream, &halFrames, &halTime),
- // HAL may have a stub function, always returning ENOSYS, don't
- // spam the log in this case.
- ENOSYS);
+ "get_capture_position",
+ stream->get_capture_position(stream, &halFrames, &halTime),
+ // HAL may have a stub function, always returning ENOSYS, don't
+ // spam the log in this case.
+ ENOSYS);
if (retval == Result::OK) {
*frames = halFrames;
*time = halTime;
@@ -398,14 +432,14 @@
return retval;
};
-Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
+Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
uint64_t frames = 0, time = 0;
Result retval = getCapturePositionImpl(mStream, &frames, &time);
_hidl_cb(retval, frames, time);
return Void();
}
-} // namespace implementation
+} // namespace implementation
} // namespace V2_0
} // namespace audio
} // namespace hardware
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 3339b63..e48497f 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -25,6 +25,7 @@
#include <utils/Trace.h>
#include "StreamOut.h"
+#include "Util.h"
namespace android {
namespace hardware {
@@ -37,30 +38,26 @@
namespace {
class WriteThread : public Thread {
- public:
+ public:
// WriteThread's lifespan never exceeds StreamOut's lifespan.
- WriteThread(std::atomic<bool>* stop,
- audio_stream_out_t* stream,
- StreamOut::CommandMQ* commandMQ,
- StreamOut::DataMQ* dataMQ,
- StreamOut::StatusMQ* statusMQ,
- EventFlag* efGroup)
- : Thread(false /*canCallJava*/),
- mStop(stop),
- mStream(stream),
- mCommandMQ(commandMQ),
- mDataMQ(dataMQ),
- mStatusMQ(statusMQ),
- mEfGroup(efGroup),
- mBuffer(nullptr) {
- }
+ WriteThread(std::atomic<bool>* stop, audio_stream_out_t* stream,
+ StreamOut::CommandMQ* commandMQ, StreamOut::DataMQ* dataMQ,
+ StreamOut::StatusMQ* statusMQ, EventFlag* efGroup)
+ : Thread(false /*canCallJava*/),
+ mStop(stop),
+ mStream(stream),
+ mCommandMQ(commandMQ),
+ mDataMQ(dataMQ),
+ mStatusMQ(statusMQ),
+ mEfGroup(efGroup),
+ mBuffer(nullptr) {}
bool init() {
- mBuffer.reset(new(std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
+ mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
return mBuffer != nullptr;
}
virtual ~WriteThread() {}
- private:
+ private:
std::atomic<bool>* mStop;
audio_stream_out_t* mStream;
StreamOut::CommandMQ* mCommandMQ;
@@ -93,9 +90,8 @@
void WriteThread::doGetPresentationPosition() {
mStatus.retval = StreamOut::getPresentationPositionImpl(
- mStream,
- &mStatus.reply.presentationPosition.frames,
- &mStatus.reply.presentationPosition.timeStamp);
+ mStream, &mStatus.reply.presentationPosition.frames,
+ &mStatus.reply.presentationPosition.timeStamp);
}
void WriteThread::doGetLatency() {
@@ -104,12 +100,15 @@
}
bool WriteThread::threadLoop() {
- // This implementation doesn't return control back to the Thread until it decides to stop,
+ // This implementation doesn't return control back to the Thread until it
+ // decides to stop,
// as the Thread uses mutexes, and this can lead to priority inversion.
- while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+ while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
uint32_t efState = 0;
- mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
- if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
+ mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY),
+ &efState);
+ if (!(efState &
+ static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
continue; // Nothing to do.
}
if (!mCommandMQ->read(&mStatus.replyTo)) {
@@ -142,11 +141,13 @@
} // namespace
StreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream)
- : mIsClosed(false), mDevice(device), mStream(stream),
- mStreamCommon(new Stream(&stream->common)),
- mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
- mEfGroup(nullptr), mStopWriteThread(false) {
-}
+ : mIsClosed(false),
+ mDevice(device),
+ mStream(stream),
+ mStreamCommon(new Stream(&stream->common)),
+ mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
+ mEfGroup(nullptr),
+ mStopWriteThread(false) {}
StreamOut::~StreamOut() {
ATRACE_CALL();
@@ -158,7 +159,8 @@
}
if (mEfGroup) {
status_t status = EventFlag::deleteEventFlag(&mEfGroup);
- ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
+ ALOGE_IF(status, "write MQ event flag deletion error: %s",
+ strerror(-status));
}
mCallback.clear();
mDevice->closeOutputStream(mStream);
@@ -166,100 +168,104 @@
}
// Methods from ::android::hardware::audio::V2_0::IStream follow.
-Return<uint64_t> StreamOut::getFrameSize() {
+Return<uint64_t> StreamOut::getFrameSize() {
return audio_stream_out_frame_size(mStream);
}
-Return<uint64_t> StreamOut::getFrameCount() {
+Return<uint64_t> StreamOut::getFrameCount() {
return mStreamCommon->getFrameCount();
}
-Return<uint64_t> StreamOut::getBufferSize() {
+Return<uint64_t> StreamOut::getBufferSize() {
return mStreamCommon->getBufferSize();
}
-Return<uint32_t> StreamOut::getSampleRate() {
+Return<uint32_t> StreamOut::getSampleRate() {
return mStreamCommon->getSampleRate();
}
-Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
+Return<void> StreamOut::getSupportedSampleRates(
+ getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(_hidl_cb);
}
-Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) {
+Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) {
return mStreamCommon->setSampleRate(sampleRateHz);
}
-Return<AudioChannelMask> StreamOut::getChannelMask() {
+Return<AudioChannelMask> StreamOut::getChannelMask() {
return mStreamCommon->getChannelMask();
}
-Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
+Return<void> StreamOut::getSupportedChannelMasks(
+ getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
}
-Return<Result> StreamOut::setChannelMask(AudioChannelMask mask) {
+Return<Result> StreamOut::setChannelMask(AudioChannelMask mask) {
return mStreamCommon->setChannelMask(mask);
}
-Return<AudioFormat> StreamOut::getFormat() {
+Return<AudioFormat> StreamOut::getFormat() {
return mStreamCommon->getFormat();
}
-Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
+Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
return mStreamCommon->getSupportedFormats(_hidl_cb);
}
-Return<Result> StreamOut::setFormat(AudioFormat format) {
+Return<Result> StreamOut::setFormat(AudioFormat format) {
return mStreamCommon->setFormat(format);
}
-Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) {
+Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) {
return mStreamCommon->getAudioProperties(_hidl_cb);
}
-Return<Result> StreamOut::addEffect(uint64_t effectId) {
+Return<Result> StreamOut::addEffect(uint64_t effectId) {
return mStreamCommon->addEffect(effectId);
}
-Return<Result> StreamOut::removeEffect(uint64_t effectId) {
+Return<Result> StreamOut::removeEffect(uint64_t effectId) {
return mStreamCommon->removeEffect(effectId);
}
-Return<Result> StreamOut::standby() {
+Return<Result> StreamOut::standby() {
return mStreamCommon->standby();
}
-Return<AudioDevice> StreamOut::getDevice() {
+Return<AudioDevice> StreamOut::getDevice() {
return mStreamCommon->getDevice();
}
-Return<Result> StreamOut::setDevice(const DeviceAddress& address) {
+Return<Result> StreamOut::setDevice(const DeviceAddress& address) {
return mStreamCommon->setDevice(address);
}
-Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
+Return<Result> StreamOut::setConnectedState(const DeviceAddress& address,
+ bool connected) {
return mStreamCommon->setConnectedState(address, connected);
}
-Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
+Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
return mStreamCommon->setHwAvSync(hwAvSync);
}
-Return<void> StreamOut::getParameters(
- const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+Return<void> StreamOut::getParameters(const hidl_vec<hidl_string>& keys,
+ getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(keys, _hidl_cb);
}
-Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) {
+Return<Result> StreamOut::setParameters(
+ const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(parameters);
}
-Return<void> StreamOut::debugDump(const hidl_handle& fd) {
+Return<void> StreamOut::debugDump(const hidl_handle& fd) {
return mStreamCommon->debugDump(fd);
}
-Return<Result> StreamOut::close() {
+Return<Result> StreamOut::close() {
if (mIsClosed) return Result::INVALID_STATE;
mIsClosed = true;
if (mWriteThread.get()) {
@@ -272,78 +278,98 @@
}
// Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
-Return<uint32_t> StreamOut::getLatency() {
+Return<uint32_t> StreamOut::getLatency() {
return mStream->get_latency(mStream);
}
-Return<Result> StreamOut::setVolume(float left, float right) {
- Result retval(Result::NOT_SUPPORTED);
- if (mStream->set_volume != NULL) {
- retval = Stream::analyzeStatus(
- "set_volume", mStream->set_volume(mStream, left, right));
+Return<Result> StreamOut::setVolume(float left, float right) {
+ if (mStream->set_volume == NULL) {
+ return Result::NOT_SUPPORTED;
}
- return retval;
+ if (!isGainNormalized(left)) {
+ ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left,
+ right);
+ return Result::INVALID_ARGUMENTS;
+ }
+ return Stream::analyzeStatus("set_volume",
+ mStream->set_volume(mStream, left, right));
}
-Return<void> StreamOut::prepareForWriting(
- uint32_t frameSize, uint32_t framesCount, prepareForWriting_cb _hidl_cb) {
+Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
+ uint32_t framesCount,
+ prepareForWriting_cb _hidl_cb) {
status_t status;
- ThreadInfo threadInfo = { 0, 0 };
+ ThreadInfo threadInfo = {0, 0};
+
+ // Wrap the _hidl_cb to return an error
+ auto sendError = [this, &threadInfo, &_hidl_cb](Result result) {
+ _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(),
+ StatusMQ::Descriptor(), threadInfo);
+
+ };
+
// Create message queues.
if (mDataMQ) {
ALOGE("the client attempts to call prepareForWriting twice");
- _hidl_cb(Result::INVALID_STATE,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_STATE);
return Void();
}
std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
- if (frameSize > std::numeric_limits<size_t>::max() / framesCount) {
- ALOGE("Requested buffer is too big, %d*%d can not fit in size_t", frameSize, framesCount);
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ // Check frameSize and framesCount
+ if (frameSize == 0 || framesCount == 0) {
+ ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize,
+ framesCount);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
- std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
+ // A message queue asserts if it can not handle the requested buffer,
+ // thus the client has to guess the maximum size it can handle
+ size_t metadataOverhead =
+ 100000; // Arbitrary margin for the overhead of a message queue
+ if (frameSize >
+ (std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
+ ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
+ frameSize, framesCount);
+ sendError(Result::INVALID_ARGUMENTS);
+ return Void();
+ }
+ std::unique_ptr<DataMQ> tempDataMQ(
+ new DataMQ(frameSize * framesCount, true /* EventFlag */));
std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
- if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+ if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() ||
+ !tempStatusMQ->isValid()) {
ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
EventFlag* tempRawEfGroup{};
- status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
- std::unique_ptr<EventFlag, void(*)(EventFlag*)> tempElfGroup(tempRawEfGroup,[](auto *ef) {
- EventFlag::deleteEventFlag(&ef); });
+ status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(),
+ &tempRawEfGroup);
+ std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
+ tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
if (status != OK || !tempElfGroup) {
ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
// Create and launch the thread.
auto tempWriteThread = std::make_unique<WriteThread>(
- &mStopWriteThread,
- mStream,
- tempCommandMQ.get(),
- tempDataMQ.get(),
- tempStatusMQ.get(),
- tempElfGroup.get());
+ &mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+ tempStatusMQ.get(), tempElfGroup.get());
if (!tempWriteThread->init()) {
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ ALOGW("failed to start writer thread: %s", strerror(-status));
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
status = tempWriteThread->run("writer", PRIORITY_URGENT_AUDIO);
if (status != OK) {
ALOGW("failed to start writer thread: %s", strerror(-status));
- _hidl_cb(Result::INVALID_ARGUMENTS,
- CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
+ sendError(Result::INVALID_ARGUMENTS);
return Void();
}
@@ -354,33 +380,34 @@
mEfGroup = tempElfGroup.release();
threadInfo.pid = getpid();
threadInfo.tid = mWriteThread->getTid();
- _hidl_cb(Result::OK,
- *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
- threadInfo);
+ _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(),
+ *mStatusMQ->getDesc(), threadInfo);
return Void();
}
-Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
+Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
uint32_t halDspFrames;
Result retval = Stream::analyzeStatus(
- "get_render_position", mStream->get_render_position(mStream, &halDspFrames));
+ "get_render_position",
+ mStream->get_render_position(mStream, &halDspFrames));
_hidl_cb(retval, halDspFrames);
return Void();
}
-Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) {
+Return<void> StreamOut::getNextWriteTimestamp(
+ getNextWriteTimestamp_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
int64_t timestampUs = 0;
if (mStream->get_next_write_timestamp != NULL) {
retval = Stream::analyzeStatus(
- "get_next_write_timestamp",
- mStream->get_next_write_timestamp(mStream, ×tampUs));
+ "get_next_write_timestamp",
+ mStream->get_next_write_timestamp(mStream, ×tampUs));
}
_hidl_cb(retval, timestampUs);
return Void();
}
-Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
+Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this);
if (result == 0) {
@@ -389,14 +416,15 @@
return Stream::analyzeStatus("set_callback", result);
}
-Return<Result> StreamOut::clearCallback() {
+Return<Result> StreamOut::clearCallback() {
if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
mCallback.clear();
return Result::OK;
}
// static
-int StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
+int StreamOut::asyncCallback(stream_callback_event_t event, void*,
+ void* cookie) {
wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie));
sp<StreamOut> self = weakSelf.promote();
if (self == nullptr || self->mCallback == nullptr) return 0;
@@ -418,53 +446,57 @@
return 0;
}
-Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) {
+Return<void> StreamOut::supportsPauseAndResume(
+ supportsPauseAndResume_cb _hidl_cb) {
_hidl_cb(mStream->pause != NULL, mStream->resume != NULL);
return Void();
}
-Return<Result> StreamOut::pause() {
- return mStream->pause != NULL ?
- Stream::analyzeStatus("pause", mStream->pause(mStream)) :
- Result::NOT_SUPPORTED;
+Return<Result> StreamOut::pause() {
+ return mStream->pause != NULL
+ ? Stream::analyzeStatus("pause", mStream->pause(mStream))
+ : Result::NOT_SUPPORTED;
}
-Return<Result> StreamOut::resume() {
- return mStream->resume != NULL ?
- Stream::analyzeStatus("resume", mStream->resume(mStream)) :
- Result::NOT_SUPPORTED;
+Return<Result> StreamOut::resume() {
+ return mStream->resume != NULL
+ ? Stream::analyzeStatus("resume", mStream->resume(mStream))
+ : Result::NOT_SUPPORTED;
}
-Return<bool> StreamOut::supportsDrain() {
+Return<bool> StreamOut::supportsDrain() {
return mStream->drain != NULL;
}
-Return<Result> StreamOut::drain(AudioDrain type) {
- return mStream->drain != NULL ?
- Stream::analyzeStatus(
- "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) :
- Result::NOT_SUPPORTED;
+Return<Result> StreamOut::drain(AudioDrain type) {
+ return mStream->drain != NULL
+ ? Stream::analyzeStatus(
+ "drain",
+ mStream->drain(mStream,
+ static_cast<audio_drain_type_t>(type)))
+ : Result::NOT_SUPPORTED;
}
-Return<Result> StreamOut::flush() {
- return mStream->flush != NULL ?
- Stream::analyzeStatus("flush", mStream->flush(mStream)) :
- Result::NOT_SUPPORTED;
+Return<Result> StreamOut::flush() {
+ return mStream->flush != NULL
+ ? Stream::analyzeStatus("flush", mStream->flush(mStream))
+ : Result::NOT_SUPPORTED;
}
// static
-Result StreamOut::getPresentationPositionImpl(
- audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp) {
+Result StreamOut::getPresentationPositionImpl(audio_stream_out_t* stream,
+ uint64_t* frames,
+ TimeSpec* timeStamp) {
Result retval(Result::NOT_SUPPORTED);
if (stream->get_presentation_position == NULL) return retval;
struct timespec halTimeStamp;
retval = Stream::analyzeStatus(
- "get_presentation_position",
- stream->get_presentation_position(stream, frames, &halTimeStamp),
- // Don't logspam on EINVAL--it's normal for get_presentation_position
- // to return it sometimes. EAGAIN may be returned by A2DP audio HAL
- // implementation.
- EINVAL, EAGAIN);
+ "get_presentation_position",
+ stream->get_presentation_position(stream, frames, &halTimeStamp),
+ // Don't logspam on EINVAL--it's normal for get_presentation_position
+ // to return it sometimes. EAGAIN may be returned by A2DP audio HAL
+ // implementation.
+ EINVAL, EAGAIN);
if (retval == Result::OK) {
timeStamp->tvSec = halTimeStamp.tv_sec;
timeStamp->tvNSec = halTimeStamp.tv_nsec;
@@ -472,9 +504,10 @@
return retval;
}
-Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
+Return<void> StreamOut::getPresentationPosition(
+ getPresentationPosition_cb _hidl_cb) {
uint64_t frames = 0;
- TimeSpec timeStamp = { 0, 0 };
+ TimeSpec timeStamp = {0, 0};
Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp);
_hidl_cb(retval, frames, timeStamp);
return Void();
@@ -488,9 +521,10 @@
return mStreamMmap->stop();
}
-Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames,
+ createMmapBuffer_cb _hidl_cb) {
return mStreamMmap->createMmapBuffer(
- minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb);
+ minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb);
}
Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
diff --git a/audio/2.0/default/Util.h b/audio/2.0/default/Util.h
new file mode 100644
index 0000000..72eea50
--- /dev/null
+++ b/audio/2.0/default/Util.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+/** @return true if gain is between 0 and 1 included. */
+constexpr bool isGainNormalized(float gain) {
+ return gain >= 0.0 && gain <= 1.0;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace audio
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_AUDIO_V2_0_UTIL_H
diff --git a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 074903f..83a1db0 100644
--- a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -36,9 +36,9 @@
#include <android/hardware/audio/2.0/types.h>
#include <android/hardware/audio/common/2.0/types.h>
-#include "utility/ReturnIn.h"
#include "utility/AssertOk.h"
#include "utility/PrettyPrintAudioTypes.h"
+#include "utility/ReturnIn.h"
using std::string;
using std::to_string;
@@ -59,7 +59,8 @@
using ::android::hardware::audio::V2_0::IStream;
using ::android::hardware::audio::V2_0::IStreamIn;
using ::android::hardware::audio::V2_0::TimeSpec;
-using ReadParameters = ::android::hardware::audio::V2_0::IStreamIn::ReadParameters;
+using ReadParameters =
+ ::android::hardware::audio::V2_0::IStreamIn::ReadParameters;
using ReadStatus = ::android::hardware::audio::V2_0::IStreamIn::ReadStatus;
using ::android::hardware::audio::V2_0::IStreamOut;
using ::android::hardware::audio::V2_0::IStreamOutCallback;
@@ -82,35 +83,51 @@
using utility::returnIn;
+const char* getTestName() {
+ return ::testing::UnitTest::GetInstance()->current_test_info()->name();
+}
+
namespace doc {
/** Document the current test case.
- * Eg: calling `doc::test("Dump the state of the hal")` in the "debugDump" test will output:
- * <testcase name="debugDump" status="run" time="6" classname="AudioPrimaryHidlTest"
- description="Dump the state of the hal." />
- * see https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#logging-additional-information
+ * Eg: calling `doc::test("Dump the state of the hal")` in the "debugDump" test
+ * will output:
+ * <testcase name="debugDump" status="run" time="6"
+ * classname="AudioPrimaryHidlTest"
+ description="Dump the state of the hal." />
+ * see
+ https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#logging-additional-information
*/
void test(const std::string& testCaseDocumentation) {
::testing::Test::RecordProperty("description", testCaseDocumentation);
}
-/** Document why a test was not fully run. Usually due to an optional feature not implemented. */
+/** Document why a test was not fully run. Usually due to an optional feature
+ * not implemented. */
void partialTest(const std::string& reason) {
+ LOG(INFO) << "Test " << getTestName() << " partially run: " << reason;
::testing::Test::RecordProperty("partialyRunTest", reason);
}
+
+/** Add a note to the test. */
+void note(const std::string& note) {
+ LOG(INFO) << "Test " << getTestName() << " noted: " << note;
+ ::testing::Test::RecordProperty("note", note);
+}
}
// Register callback for static object destruction
// Avoid destroying static objects after main return.
-// Post main return destruction leads to incorrect gtest timing measurements as well as harder
+// Post main return destruction leads to incorrect gtest timing measurements as
+// well as harder
// debuging if anything goes wrong during destruction.
class Environment : public ::testing::Environment {
-public:
- using TearDownFunc = std::function<void ()>;
- void registerTearDown(TearDownFunc&& tearDown) {
- tearDowns.push_back(std::move(tearDown));
+ public:
+ using TearDownFunc = std::function<void()>;
+ void registerTearDown(TearDownFunc&& tearDown) {
+ tearDowns.push_back(std::move(tearDown));
}
-private:
+ private:
void TearDown() override {
// Call the tear downs in reverse order of insertion
for (auto& tearDown : tearDowns) {
@@ -123,7 +140,7 @@
static Environment* environment;
class HidlTest : public ::testing::VtsHalHidlTargetTestBase {
-protected:
+ protected:
// Convenient member to store results
Result res;
};
@@ -134,18 +151,19 @@
// Test all audio devices
class AudioHidlTest : public HidlTest {
-public:
+ public:
void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base
+ ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base
if (devicesFactory == nullptr) {
- environment->registerTearDown([]{ devicesFactory.clear(); });
- devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<IDevicesFactory>();
+ environment->registerTearDown([] { devicesFactory.clear(); });
+ devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<
+ IDevicesFactory>();
}
ASSERT_TRUE(devicesFactory != nullptr);
}
-protected:
+ protected:
// Cache the devicesFactory retrieval to speed up each test by ~0.5s
static sp<IDevicesFactory> devicesFactory;
};
@@ -171,26 +189,27 @@
// Test the primary device
class AudioPrimaryHidlTest : public AudioHidlTest {
-public:
+ public:
/** Primary HAL test are NOT thread safe. */
void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base
+ ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base
if (device == nullptr) {
IDevicesFactory::Result result;
sp<IDevice> baseDevice;
- ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY,
- returnIn(result, baseDevice)));
+ ASSERT_OK(
+ devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY,
+ returnIn(result, baseDevice)));
ASSERT_OK(result);
ASSERT_TRUE(baseDevice != nullptr);
- environment->registerTearDown([]{ device.clear(); });
+ environment->registerTearDown([] { device.clear(); });
device = IPrimaryDevice::castFrom(baseDevice);
ASSERT_TRUE(device != nullptr);
}
}
-protected:
+ protected:
// Cache the device opening to speed up each test by ~0.5s
static sp<IPrimaryDevice> device;
};
@@ -211,15 +230,15 @@
template <class Property>
class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
-protected:
-
+ protected:
/** Test a property getter and setter. */
template <class Getter, class Setter>
- void testAccessors(const string& propertyName, const vector<Property>& valuesToTest,
- Setter setter, Getter getter,
+ void testAccessors(const string& propertyName,
+ const vector<Property>& valuesToTest, Setter setter,
+ Getter getter,
const vector<Property>& invalidValues = {}) {
-
- Property initialValue; // Save initial value to restore it at the end of the test
+ Property initialValue; // Save initial value to restore it at the end
+ // of the test
ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
ASSERT_OK(res);
@@ -235,17 +254,21 @@
}
for (Property invalidValue : invalidValues) {
- SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
+ SCOPED_TRACE("Try to set " + propertyName +
+ " with the invalid value " +
testing::PrintToString(invalidValue));
- EXPECT_RESULT(Result::INVALID_ARGUMENTS, (device.get()->*setter)(invalidValue));
+ EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+ (device.get()->*setter)(invalidValue));
}
- ASSERT_OK((device.get()->*setter)(initialValue)); // restore initial value
+ ASSERT_OK(
+ (device.get()->*setter)(initialValue)); // restore initial value
}
/** Test the getter and setter of an optional feature. */
template <class Getter, class Setter>
- void testOptionalAccessors(const string& propertyName, const vector<Property>& valuesToTest,
+ void testOptionalAccessors(const string& propertyName,
+ const vector<Property>& valuesToTest,
Setter setter, Getter getter,
const vector<Property>& invalidValues = {}) {
doc::test("Test the optional " + propertyName + " getters and setter");
@@ -257,10 +280,11 @@
doc::partialTest(propertyName + " getter is not supported");
return;
}
- ASSERT_OK(res); // If it is supported it must succeed
+ ASSERT_OK(res); // If it is supported it must succeed
}
// The feature is supported, test it
- testAccessors(propertyName, valuesToTest, setter, getter, invalidValues);
+ testAccessors(propertyName, valuesToTest, setter, getter,
+ invalidValues);
}
};
@@ -268,12 +292,15 @@
TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) {
doc::test("Check that the mic can be muted and unmuted");
- testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, &IDevice::getMicMute);
+ testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute,
+ &IDevice::getMicMute);
// TODO: check that the mic is really muted (all sample are 0)
}
TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
- doc::test("If master mute is supported, try to mute and unmute the master output");
+ doc::test(
+ "If master mute is supported, try to mute and unmute the master "
+ "output");
testOptionalAccessors("master mute", {true, false, true},
&IDevice::setMasterMute, &IDevice::getMasterMute);
// TODO: check that the master volume is really muted
@@ -282,7 +309,7 @@
using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>;
TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) {
doc::test("Test the master volume if supported");
- testOptionalAccessors("master volume", {0, 0.5, 1},
+ testOptionalAccessors("master volume", {0, 0.5, 1},
&IDevice::setMasterVolume, &IDevice::getMasterVolume,
{-0.1, 1.1, NAN, INFINITY, -INFINITY,
1 + std::numeric_limits<float>::epsilon()});
@@ -294,10 +321,10 @@
//////////////////////////////////////////////////////////////////////////////
class AudioPatchPrimaryHidlTest : public AudioPrimaryHidlTest {
-protected:
+ protected:
bool areAudioPatchesSupported() {
auto result = device->supportsAudioPatches();
- EXPECT_TRUE(result.isOk());
+ EXPECT_IS_OK(result);
return result;
}
};
@@ -311,27 +338,30 @@
// TODO: test audio patches
}
-
//////////////////////////////////////////////////////////////////////////////
//////////////// Required and recommended audio format support ///////////////
-// From: https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
-// From: https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
+// From:
+// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
+// From:
+// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
/////////// TODO: move to the beginning of the file for easier update ////////
//////////////////////////////////////////////////////////////////////////////
class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest {
-public:
+ public:
// Cache result ?
static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
- return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
- {8000, 11025, 16000, 22050, 32000, 44100},
- {AudioFormat::PCM_16_BIT});
+ return combineAudioConfig(
+ {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
+ {8000, 11025, 16000, 22050, 32000, 44100},
+ {AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
- return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
- {24000, 48000},
- {AudioFormat::PCM_16_BIT});
+ static const vector<AudioConfig>
+ getRecommendedSupportPlaybackAudioConfig() {
+ return combineAudioConfig(
+ {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
+ {24000, 48000}, {AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
@@ -346,8 +376,7 @@
{AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
- return combineAudioConfig({AudioChannelMask::IN_STEREO},
- {22050, 48000},
+ return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
{AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
@@ -355,13 +384,13 @@
// as declared in the policy configuration
return {};
}
-private:
+
+ private:
static const vector<AudioConfig> combineAudioConfig(
- vector<AudioChannelMask> channelMasks,
- vector<uint32_t> sampleRates,
- vector<AudioFormat> formats) {
+ vector<AudioChannelMask> channelMasks, vector<uint32_t> sampleRates,
+ vector<AudioFormat> formats) {
vector<AudioConfig> configs;
- for (auto channelMask: channelMasks) {
+ for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {
for (auto format : formats) {
AudioConfig config{};
@@ -383,28 +412,34 @@
* As the only parameter changing are channel mask and sample rate,
* only print those ones in the test name.
*/
-static string generateTestName(const testing::TestParamInfo<AudioConfig>& info) {
+static string generateTestName(
+ const testing::TestParamInfo<AudioConfig>& info) {
const AudioConfig& config = info.param;
- return to_string(info.index) + "__" + to_string(config.sampleRateHz)+ "_" +
- // "MONO" is more clear than "FRONT_LEFT"
- ((config.channelMask == AudioChannelMask::OUT_MONO ||
- config.channelMask == AudioChannelMask::IN_MONO) ?
- "MONO" : toString(config.channelMask));
+ return to_string(info.index) + "__" + to_string(config.sampleRateHz) + "_" +
+ // "MONO" is more clear than "FRONT_LEFT"
+ ((config.channelMask == AudioChannelMask::OUT_MONO ||
+ config.channelMask == AudioChannelMask::IN_MONO)
+ ? "MONO"
+ : toString(config.channelMask));
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////// getInputBufferSize /////////////////////////////
//////////////////////////////////////////////////////////////////////////////
-// FIXME: execute input test only if platform declares android.hardware.microphone
+// FIXME: execute input test only if platform declares
+// android.hardware.microphone
// how to get this value ? is it a property ???
-class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
- public ::testing::WithParamInterface<AudioConfig> {
-protected:
- void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
+class AudioCaptureConfigPrimaryTest
+ : public AudioConfigPrimaryTest,
+ public ::testing::WithParamInterface<AudioConfig> {
+ protected:
+ void inputBufferSizeTest(const AudioConfig& audioConfig,
+ bool supportRequired) {
uint64_t bufferSize;
- ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
+ ASSERT_OK(
+ device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
switch (res) {
case Result::INVALID_ARGUMENTS:
@@ -416,36 +451,46 @@
EXPECT_GT(bufferSize, uint64_t(0));
break;
default:
- FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
+ FAIL() << "Invalid return status: "
+ << ::testing::PrintToString(res);
}
}
};
-// Test that the required capture config and those declared in the policy are indeed supported
+// Test that the required capture config and those declared in the policy are
+// indeed supported
class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
- doc::test("Input buffer size must be retrievable for a format with required support.");
+ doc::test(
+ "Input buffer size must be retrievable for a format with required "
+ "support.");
inputBufferSizeTest(GetParam(), true);
}
INSTANTIATE_TEST_CASE_P(
- RequiredInputBufferSize, RequiredInputBufferSizeTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
- &generateTestName);
+ RequiredInputBufferSize, RequiredInputBufferSizeTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+ &generateTestName);
INSTANTIATE_TEST_CASE_P(
- SupportedInputBufferSize, RequiredInputBufferSizeTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
- &generateTestName);
+ SupportedInputBufferSize, RequiredInputBufferSizeTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+ &generateTestName);
-// Test that the recommended capture config are supported or lead to a INVALID_ARGUMENTS return
+// Test that the recommended capture config are supported or lead to a
+// INVALID_ARGUMENTS return
class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
- doc::test("Input buffer size should be retrievable for a format with recommended support.");
+ doc::test(
+ "Input buffer size should be retrievable for a format with recommended "
+ "support.");
inputBufferSizeTest(GetParam(), false);
}
INSTANTIATE_TEST_CASE_P(
- RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
- &generateTestName);
+ RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+ &generateTestName);
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// setScreenState ///////////////////////////////
@@ -455,9 +500,10 @@
doc::test("Check that the hal can receive the screen state");
for (bool turnedOn : {false, true, true, false, false}) {
auto ret = device->setScreenState(turnedOn);
- ASSERT_TRUE(ret.isOk());
+ ASSERT_IS_OK(ret);
Result result = ret;
- ASSERT_TRUE(result == Result::OK || result == Result::NOT_SUPPORTED) << toString(result);
+ auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
+ ASSERT_RESULT(okOrNotSupported, result);
}
}
@@ -481,34 +527,41 @@
template <class DebugDump>
static void testDebugDump(DebugDump debugDump) {
+ // Dump in a temporary file
+ // Note that SELinux must be deactivate for this test to work
FILE* file = tmpfile();
ASSERT_NE(nullptr, file) << errno;
+ // Wrap the temporary file file descriptor in a native handle
auto* nativeHandle = native_handle_create(1, 0);
ASSERT_NE(nullptr, nativeHandle);
nativeHandle->data[0] = fileno(file);
+ // Wrap this native handle in a hidl handle
hidl_handle handle;
handle.setTo(nativeHandle, true /*take ownership*/);
- // TODO: debugDump does not return a Result.
- // This mean that the hal can not report that it not implementing the function.
ASSERT_OK(debugDump(handle));
- rewind(file); // can not fail
-
// Check that at least one bit was written by the hal
+ // TODO: debugDump does not return a Result.
+ // This mean that the hal can not report that it not implementing the
+ // function.
+ rewind(file); // can not fail
char buff;
- ASSERT_EQ(size_t{1}, fread(&buff, sizeof(buff), 1, file));
+ if (fread(&buff, sizeof(buff), 1, file) != 1) {
+ doc::note("debugDump does not seem implemented");
+ }
EXPECT_EQ(0, fclose(file)) << errno;
}
-TEST_F(AudioPrimaryHidlTest, debugDump) {
+TEST_F(AudioPrimaryHidlTest, DebugDump) {
doc::test("Check that the hal can dump its state without error");
- testDebugDump([this](const auto& handle){ return device->debugDump(handle); });
+ testDebugDump(
+ [this](const auto& handle) { return device->debugDump(handle); });
}
-TEST_F(AudioPrimaryHidlTest, debugDumpInvalidArguments) {
+TEST_F(AudioPrimaryHidlTest, DebugDumpInvalidArguments) {
doc::test("Check that the hal dump doesn't crash on invalid arguments");
ASSERT_OK(device->debugDump(hidl_handle()));
}
@@ -520,14 +573,16 @@
template <class Stream>
class OpenStreamTest : public AudioConfigPrimaryTest,
public ::testing::WithParamInterface<AudioConfig> {
-protected:
+ protected:
template <class Open>
void testOpen(Open openStream, const AudioConfig& config) {
// FIXME: Open a stream without an IOHandle
// This is not required to be accepted by hal implementations
- AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
+ AudioIoHandle ioHandle =
+ (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
AudioConfig suggestedConfig{};
- ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
+ ASSERT_OK(openStream(ioHandle, config,
+ returnIn(res, stream, suggestedConfig)));
// TODO: only allow failure for RecommendedPlaybackAudioConfig
switch (res) {
@@ -538,16 +593,19 @@
case Result::INVALID_ARGUMENTS:
ASSERT_TRUE(stream == nullptr);
AudioConfig suggestedConfigRetry;
- // Could not open stream with config, try again with the suggested one
- ASSERT_OK(openStream(ioHandle, suggestedConfig,
- returnIn(res, stream, suggestedConfigRetry)));
+ // Could not open stream with config, try again with the
+ // suggested one
+ ASSERT_OK(
+ openStream(ioHandle, suggestedConfig,
+ returnIn(res, stream, suggestedConfigRetry)));
// This time it must succeed
ASSERT_OK(res);
- ASSERT_TRUE(stream == nullptr);
+ ASSERT_TRUE(stream != nullptr);
audioConfig = suggestedConfig;
break;
default:
- FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
+ FAIL() << "Invalid return status: "
+ << ::testing::PrintToString(res);
}
open = true;
}
@@ -556,15 +614,15 @@
open = false;
return stream->close();
}
-private:
+
+ private:
void TearDown() override {
if (open) {
ASSERT_OK(stream->close());
}
}
-protected:
-
+ protected:
AudioConfig audioConfig;
DeviceAddress address = {};
sp<Stream> stream;
@@ -575,66 +633,84 @@
class OutputStreamTest : public OpenStreamTest<IStreamOut> {
virtual void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
+ ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
address.device = AudioDevice::OUT_DEFAULT;
const AudioConfig& config = GetParam();
- AudioOutputFlag flags = AudioOutputFlag::NONE; // TODO: test all flag combination
- testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
- { return device->openOutputStream(handle, address, config, flags, cb); },
- config);
+ AudioOutputFlag flags =
+ AudioOutputFlag::NONE; // TODO: test all flag combination
+ testOpen(
+ [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+ return device->openOutputStream(handle, address, config, flags,
+ cb);
+ },
+ config);
}
};
TEST_P(OutputStreamTest, OpenOutputStreamTest) {
- doc::test("Check that output streams can be open with the required and recommended config");
+ doc::test(
+ "Check that output streams can be open with the required and "
+ "recommended config");
// Open done in SetUp
}
INSTANTIATE_TEST_CASE_P(
- RequiredOutputStreamConfigSupport, OutputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
- &generateTestName);
+ RequiredOutputStreamConfigSupport, OutputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
+ &generateTestName);
INSTANTIATE_TEST_CASE_P(
- SupportedOutputStreamConfig, OutputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
- &generateTestName);
+ SupportedOutputStreamConfig, OutputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
+ &generateTestName);
INSTANTIATE_TEST_CASE_P(
- RecommendedOutputStreamConfigSupport, OutputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
- &generateTestName);
+ RecommendedOutputStreamConfigSupport, OutputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
+ &generateTestName);
////////////////////////////// openInputStream //////////////////////////////
class InputStreamTest : public OpenStreamTest<IStreamIn> {
-
virtual void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
+ ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
address.device = AudioDevice::IN_DEFAULT;
const AudioConfig& config = GetParam();
- AudioInputFlag flags = AudioInputFlag::NONE; // TODO: test all flag combination
- AudioSource source = AudioSource::DEFAULT; // TODO: test all flag combination
- testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
- { return device->openInputStream(handle, address, config, flags, source, cb); },
- config);
+ AudioInputFlag flags =
+ AudioInputFlag::NONE; // TODO: test all flag combination
+ AudioSource source =
+ AudioSource::DEFAULT; // TODO: test all flag combination
+ testOpen(
+ [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+ return device->openInputStream(handle, address, config, flags,
+ source, cb);
+ },
+ config);
}
};
TEST_P(InputStreamTest, OpenInputStreamTest) {
- doc::test("Check that input streams can be open with the required and recommended config");
+ doc::test(
+ "Check that input streams can be open with the required and "
+ "recommended config");
// Open done in setup
}
INSTANTIATE_TEST_CASE_P(
- RequiredInputStreamConfigSupport, InputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
- &generateTestName);
+ RequiredInputStreamConfigSupport, InputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
+ &generateTestName);
INSTANTIATE_TEST_CASE_P(
- SupportedInputStreamConfig, InputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
- &generateTestName);
+ SupportedInputStreamConfig, InputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
+ &generateTestName);
INSTANTIATE_TEST_CASE_P(
- RecommendedInputStreamConfigSupport, InputStreamTest,
- ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
- &generateTestName);
+ RecommendedInputStreamConfigSupport, InputStreamTest,
+ ::testing::ValuesIn(
+ AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
+ &generateTestName);
//////////////////////////////////////////////////////////////////////////////
////////////////////////////// IStream getters ///////////////////////////////
@@ -645,7 +721,7 @@
template <class R>
static R extract(Return<R> ret) {
if (!ret.isOk()) {
- ADD_FAILURE();
+ EXPECT_IS_OK(ret);
return R{};
}
return ret;
@@ -654,49 +730,63 @@
/* Could not find a way to write a test for two parametrized class fixure
* thus use this macro do duplicate tests for Input and Output stream */
#define TEST_IO_STREAM(test_name, documentation, code) \
- TEST_P(InputStreamTest, test_name) { \
- doc::test(documentation); \
- code; \
- } \
- TEST_P(OutputStreamTest, test_name) { \
- doc::test(documentation); \
- code; \
+ TEST_P(InputStreamTest, test_name) { \
+ doc::test(documentation); \
+ code; \
+ } \
+ TEST_P(OutputStreamTest, test_name) { \
+ doc::test(documentation); \
+ code; \
}
-TEST_IO_STREAM(GetFrameCount, "Check that the stream frame count == the one it was opened with",
- ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
+TEST_IO_STREAM(
+ GetFrameCount,
+ "Check that the stream frame count == the one it was opened with",
+ ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
-TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
- ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
+TEST_IO_STREAM(
+ GetSampleRate,
+ "Check that the stream sample rate == the one it was opened with",
+ ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
-TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with",
- ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
+TEST_IO_STREAM(
+ GetChannelMask,
+ "Check that the stream channel mask == the one it was opened with",
+ ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
-TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
+TEST_IO_STREAM(GetFormat,
+ "Check that the stream format == the one it was opened with",
ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
// TODO: for now only check that the framesize is not incoherent
-TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
+TEST_IO_STREAM(GetFrameSize,
+ "Check that the stream frame size == the one it was opened with",
ASSERT_GT(extract(stream->getFrameSize()), 0U))
-TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it was opened with",
- ASSERT_GE(extract(stream->getBufferSize()), \
- extract(stream->getFrameSize())));
+TEST_IO_STREAM(GetBufferSize,
+ "Check that the stream buffer size== the one it was opened with",
+ ASSERT_GE(extract(stream->getBufferSize()),
+ extract(stream->getFrameSize())));
template <class Property, class CapabilityGetter, class Getter, class Setter>
-static void testCapabilityGetter(const string& name, IStream* stream, Property currentValue,
- CapabilityGetter capablityGetter, Getter getter, Setter setter) {
+static void testCapabilityGetter(const string& name, IStream* stream,
+ Property currentValue,
+ CapabilityGetter capablityGetter,
+ Getter getter, Setter setter) {
hidl_vec<Property> capabilities;
ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities)));
if (capabilities.size() == 0) {
- // The default hal should probably return a NOT_SUPPORTED if the hal does not expose
- // capability retrieval. For now it returns an empty list if not implemented
+ // The default hal should probably return a NOT_SUPPORTED if the hal
+ // does not expose
+ // capability retrieval. For now it returns an empty list if not
+ // implemented
doc::partialTest(name + " is not supported");
return;
};
- // TODO: This code has never been tested on a hal that supports getSupportedSampleRates
+ // TODO: This code has never been tested on a hal that supports
+ // getSupportedSampleRates
EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
- capabilities.end())
+ capabilities.end())
<< "current " << name << " is not in the list of the supported ones "
<< toString(capabilities);
@@ -707,69 +797,88 @@
}
}
-TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
- testCapabilityGetter("getSupportedSampleRate", stream.get(), \
- extract(stream->getSampleRate()), \
- &IStream::getSupportedSampleRates, \
- &IStream::getSampleRate, &IStream::setSampleRate))
+TEST_IO_STREAM(SupportedSampleRate,
+ "Check that the stream sample rate is declared as supported",
+ testCapabilityGetter("getSupportedSampleRate", stream.get(),
+ extract(stream->getSampleRate()),
+ &IStream::getSupportedSampleRates,
+ &IStream::getSampleRate,
+ &IStream::setSampleRate))
-TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is declared as supported",
- testCapabilityGetter("getSupportedChannelMask", stream.get(), \
- extract(stream->getChannelMask()), \
- &IStream::getSupportedChannelMasks, \
- &IStream::getChannelMask, &IStream::setChannelMask))
+TEST_IO_STREAM(SupportedChannelMask,
+ "Check that the stream channel mask is declared as supported",
+ testCapabilityGetter("getSupportedChannelMask", stream.get(),
+ extract(stream->getChannelMask()),
+ &IStream::getSupportedChannelMasks,
+ &IStream::getChannelMask,
+ &IStream::setChannelMask))
-TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
- testCapabilityGetter("getSupportedFormat", stream.get(), \
- extract(stream->getFormat()), \
- &IStream::getSupportedFormats, \
+TEST_IO_STREAM(SupportedFormat,
+ "Check that the stream format is declared as supported",
+ testCapabilityGetter("getSupportedFormat", stream.get(),
+ extract(stream->getFormat()),
+ &IStream::getSupportedFormats,
&IStream::getFormat, &IStream::setFormat))
static void testGetDevice(IStream* stream, AudioDevice expectedDevice) {
+ // Unfortunately the interface does not allow the implementation to return
+ // NOT_SUPPORTED
+ // Thus allow NONE as signaling that the call is not supported.
auto ret = stream->getDevice();
- ASSERT_TRUE(ret.isOk());
+ ASSERT_IS_OK(ret);
AudioDevice device = ret;
- ASSERT_EQ(expectedDevice, device);
+ ASSERT_TRUE(device == expectedDevice || device == AudioDevice::NONE)
+ << "Expected: " << ::testing::PrintToString(expectedDevice)
+ << "\n Actual: " << ::testing::PrintToString(device);
}
-TEST_IO_STREAM(GetDevice, "Check that the stream device == the one it was opened with",
- areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported") : \
- testGetDevice(stream.get(), address.device))
+TEST_IO_STREAM(GetDevice,
+ "Check that the stream device == the one it was opened with",
+ areAudioPatchesSupported()
+ ? doc::partialTest("Audio patches are supported")
+ : testGetDevice(stream.get(), address.device))
static void testSetDevice(IStream* stream, const DeviceAddress& address) {
DeviceAddress otherAddress = address;
- otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ?
- AudioDevice::OUT_SPEAKER : AudioDevice::IN_BUILTIN_MIC;
+ otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0
+ ? AudioDevice::OUT_SPEAKER
+ : AudioDevice::IN_BUILTIN_MIC;
EXPECT_OK(stream->setDevice(otherAddress));
- ASSERT_OK(stream->setDevice(address)); // Go back to the original value
+ ASSERT_OK(stream->setDevice(address)); // Go back to the original value
}
-TEST_IO_STREAM(SetDevice, "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
- areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported") : \
- testSetDevice(stream.get(), address))
+TEST_IO_STREAM(
+ SetDevice,
+ "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
+ areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+ : testSetDevice(stream.get(), address))
-static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
+static void testGetAudioProperties(IStream* stream,
+ AudioConfig expectedConfig) {
uint32_t sampleRateHz;
AudioChannelMask mask;
AudioFormat format;
stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
- // FIXME: the qcom hal it does not currently negotiate the sampleRate & channel mask
+ // FIXME: the qcom hal it does not currently negotiate the sampleRate &
+ // channel mask
EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
EXPECT_EQ(expectedConfig.channelMask, mask);
EXPECT_EQ(expectedConfig.format, format);
}
-TEST_IO_STREAM(GetAudioProperties,
- "Check that the stream audio properties == the ones it was opened with",
- testGetAudioProperties(stream.get(), audioConfig))
+TEST_IO_STREAM(
+ GetAudioProperties,
+ "Check that the stream audio properties == the ones it was opened with",
+ testGetAudioProperties(stream.get(), audioConfig))
static void testConnectedState(IStream* stream) {
DeviceAddress address = {};
using AD = AudioDevice;
- for (auto device : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+ for (auto device :
+ {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
address.device = device;
ASSERT_OK(stream->setConnectedState(address, true));
@@ -777,52 +886,63 @@
}
}
TEST_IO_STREAM(SetConnectedState,
- "Check that the stream can be notified of device connection and deconnection",
+ "Check that the stream can be notified of device connection and "
+ "deconnection",
testConnectedState(stream.get()))
-
-static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
+static auto invalidArgsOrNotSupportedOrOK = {Result::INVALID_ARGUMENTS,
+ Result::NOT_SUPPORTED, Result::OK};
TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
- ASSERT_RESULT(invalidArgsOrNotSupported, stream->setHwAvSync(666)))
+ ASSERT_RESULT(invalidArgsOrNotSupportedOrOK,
+ stream->setHwAvSync(666)))
TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail",
- ASSERT_TRUE(device->getHwAvSync().isOk()))
+ ASSERT_IS_OK(device->getHwAvSync()));
-static void checkGetParameter(IStream* stream, hidl_vec<hidl_string> keys,
- vector<Result> expectedResults) {
+static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
+ vector<Result> expectedResults) {
hidl_vec<ParameterValue> parameters;
Result res;
ASSERT_OK(stream->getParameters(keys, returnIn(res, parameters)));
ASSERT_RESULT(expectedResults, res);
if (res == Result::OK) {
- ASSERT_EQ(0U, parameters.size());
+ for (auto& parameter : parameters) {
+ ASSERT_EQ(0U, parameter.value.size()) << toString(parameter);
+ }
}
}
-/* Get/Set parameter is intended to be an opaque channel between vendors app and their HALs.
+/* Get/Set parameter is intended to be an opaque channel between vendors app and
+ * their HALs.
* Thus can not be meaningfully tested.
- * TODO: Doc missing. Should asking for an empty set of params raise an error ?
*/
TEST_IO_STREAM(getEmptySetParameter, "Retrieve the values of an empty set",
- checkGetParameter(stream.get(), {} /* keys */,
- {Result::OK, Result::INVALID_ARGUMENTS}))
+ checkGetNoParameter(stream.get(), {} /* keys */, {Result::OK}))
+TEST_IO_STREAM(getNonExistingParameter,
+ "Retrieve the values of an non existing parameter",
+ checkGetNoParameter(stream.get(),
+ {"Non existing key"} /* keys */,
+ {Result::NOT_SUPPORTED}))
-TEST_IO_STREAM(getNonExistingParameter, "Retrieve the values of an non existing parameter",
- checkGetParameter(stream.get(), {"Non existing key"} /* keys */,
- {Result::INVALID_ARGUMENTS}))
+TEST_IO_STREAM(setEmptySetParameter,
+ "Set the values of an empty set of parameters",
+ ASSERT_RESULT(Result::OK, stream->setParameters({})))
-static vector<Result> okOrInvalidArguments = {Result::OK, Result::INVALID_ARGUMENTS};
-TEST_IO_STREAM(setEmptySetParameter, "Set the values of an empty set of parameters",
- ASSERT_RESULT(okOrInvalidArguments, stream->setParameters({})))
-
-TEST_IO_STREAM(setNonExistingParameter, "Set the values of an non existing parameter",
- ASSERT_RESULT(Result::INVALID_ARGUMENTS,
- stream->setParameters({{"non existing key", "0"}})))
+TEST_IO_STREAM(
+ setNonExistingParameter, "Set the values of an non existing parameter",
+ // Unfortunately, the set_parameter legacy interface did not return any
+ // error code when a key is not supported.
+ // To allow implementation to just wrapped the legacy one, consider OK as a
+ // valid result for setting a non existing parameter.
+ ASSERT_RESULT(invalidArgsOrNotSupportedOrOK,
+ stream->setParameters({{"non existing key", "0"}})))
TEST_IO_STREAM(DebugDump,
"Check that a stream can dump its state without error",
- testDebugDump([this](const auto& handle){ return stream->debugDump(handle); }))
+ testDebugDump([this](const auto& handle) {
+ return stream->debugDump(handle);
+ }))
TEST_IO_STREAM(DebugDumpInvalidArguments,
"Check that the stream dump doesn't crash on invalid arguments",
@@ -834,39 +954,49 @@
TEST_IO_STREAM(AddNonExistingEffect, "Adding a non existing effect should fail",
ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->addEffect(666)))
-TEST_IO_STREAM(RemoveNonExistingEffect, "Removing a non existing effect should fail",
- ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->removeEffect(666)))
+TEST_IO_STREAM(RemoveNonExistingEffect,
+ "Removing a non existing effect should fail",
+ ASSERT_RESULT(Result::INVALID_ARGUMENTS,
+ stream->removeEffect(666)))
-//TODO: positive tests
+// TODO: positive tests
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Control ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby",
- ASSERT_OK(stream->standby())) // can not fail
+ ASSERT_OK(stream->standby())) // can not fail
-static vector<Result> invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
+static vector<Result> invalidStateOrNotSupported = {Result::INVALID_STATE,
+ Result::NOT_SUPPORTED};
-TEST_IO_STREAM(startNoMmap, "Starting a mmaped stream before mapping it should fail",
+TEST_IO_STREAM(startNoMmap,
+ "Starting a mmaped stream before mapping it should fail",
ASSERT_RESULT(invalidStateOrNotSupported, stream->start()))
-TEST_IO_STREAM(stopNoMmap, "Stopping a mmaped stream before mapping it should fail",
+TEST_IO_STREAM(stopNoMmap,
+ "Stopping a mmaped stream before mapping it should fail",
ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
-TEST_IO_STREAM(getMmapPositionNoMmap, "Get a stream Mmap position before mapping it should fail",
+TEST_IO_STREAM(getMmapPositionNoMmap,
+ "Get a stream Mmap position before mapping it should fail",
ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
-TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
+TEST_IO_STREAM(close, "Make sure a stream can be closed",
+ ASSERT_OK(closeStream()))
TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
- ASSERT_OK(closeStream()); \
+ ASSERT_OK(closeStream());
ASSERT_RESULT(Result::INVALID_STATE, closeStream()))
+static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS,
+ Result::NOT_SUPPORTED};
static void testCreateTooBigMmapBuffer(IStream* stream) {
MmapBufferInfo info;
Result res;
// Assume that int max is a value too big to be allocated
- // This is true currently with a 32bit media server, but might not when it will run in 64 bit
+ // This is true currently with a 32bit media server, but might not when it
+ // will run in 64 bit
auto minSizeFrames = std::numeric_limits<int32_t>::max();
ASSERT_OK(stream->createMmapBuffer(minSizeFrames, returnIn(res, info)));
ASSERT_RESULT(invalidArgsOrNotSupported, res);
@@ -875,7 +1005,6 @@
TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer too big should fail",
testCreateTooBigMmapBuffer(stream.get()))
-
static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
Result res;
MmapPosition position;
@@ -883,71 +1012,107 @@
ASSERT_RESULT(invalidArgsOrNotSupported, res);
}
-TEST_IO_STREAM(GetMmapPositionOfNonMmapedStream,
- "Retrieving the mmap position of a non mmaped stream should fail",
- testGetMmapPositionOfNonMmapedStream(stream.get()))
+TEST_IO_STREAM(
+ GetMmapPositionOfNonMmapedStream,
+ "Retrieving the mmap position of a non mmaped stream should fail",
+ testGetMmapPositionOfNonMmapedStream(stream.get()))
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////// StreamIn ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
TEST_P(InputStreamTest, GetAudioSource) {
- doc::test("Retrieving the audio source of an input stream should always succeed");
+ doc::test(
+ "Retrieving the audio source of an input stream should always succeed");
AudioSource source;
ASSERT_OK(stream->getAudioSource(returnIn(res, source)));
+ if (res == Result::NOT_SUPPORTED) {
+ doc::partialTest("getAudioSource is not supported");
+ return;
+ }
ASSERT_OK(res);
ASSERT_EQ(AudioSource::DEFAULT, source);
}
-static void testUnitaryGain(std::function<Return<Result> (float)> setGain) {
- for (float value : {0.0, 0.01, 0.5, 0.09, 1.0}) {
+static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
+ for (float value :
+ (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(),
+ 2.0, INFINITY, NAN}) {
+ SCOPED_TRACE("value=" + to_string(value));
+ // FIXME: NAN should never be accepted
+ // FIXME: Missing api doc. What should the impl do if the volume is
+ // outside [0,1] ?
+ ASSERT_RESULT(Result::INVALID_ARGUMENTS, setGain(value));
+ }
+ // Do not consider -0.0 as an invalid value as it is == with 0.0
+ for (float value : {-0.0, 0.0, 0.01, 0.5, 0.09, 1.0 /* Restore volume*/}) {
SCOPED_TRACE("value=" + to_string(value));
ASSERT_OK(setGain(value));
}
- for (float value : (float[]){-INFINITY,-1.0, -0.0,
- 1.0 + std::numeric_limits<float>::epsilon(), 2.0, INFINITY,
- NAN}) {
- SCOPED_TRACE("value=" + to_string(value));
- // FIXME: NAN should never be accepted
- // FIXME: Missing api doc. What should the impl do if the volume is outside [0,1] ?
- ASSERT_RESULT(Result::INVALID_ARGUMENTS, setGain(value));
+}
+
+static void testOptionalUnitaryGain(
+ std::function<Return<Result>(float)> setGain, string debugName) {
+ auto result = setGain(1);
+ ASSERT_IS_OK(result);
+ if (result == Result::NOT_SUPPORTED) {
+ doc::partialTest(debugName + " is not supported");
+ return;
}
+ testUnitaryGain(setGain);
}
TEST_P(InputStreamTest, SetGain) {
doc::test("The gain of an input stream should only be set between [0,1]");
- testUnitaryGain([this](float volume) { return stream->setGain(volume); });
+ testOptionalUnitaryGain(
+ [this](float volume) { return stream->setGain(volume); },
+ "InputStream::setGain");
}
-static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize,
+ uint32_t framesCount) {
Result res;
// Ignore output parameters as the call should fail
- ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
- [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+ ASSERT_OK(stream->prepareForReading(
+ frameSize, framesCount,
+ [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
EXPECT_RESULT(invalidArgsOrNotSupported, res);
}
+TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
+ doc::test(
+ "Preparing a stream for reading with a 0 sized buffer should fail");
+ testPrepareForReading(stream.get(), 0, 0);
+}
+
TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) {
- doc::test("Preparing a stream for reading with a 2^32 sized buffer should fail");
- testPrepareForReading(stream.get(), 1, std::numeric_limits<uint32_t>::max());
+ doc::test(
+ "Preparing a stream for reading with a 2^32 sized buffer should fail");
+ testPrepareForReading(stream.get(), 1,
+ std::numeric_limits<uint32_t>::max());
}
TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
- doc::test("Preparing a stream for reading with a overflowing sized buffer should fail");
+ doc::test(
+ "Preparing a stream for reading with a overflowing sized buffer should "
+ "fail");
auto uintMax = std::numeric_limits<uint32_t>::max();
testPrepareForReading(stream.get(), uintMax, uintMax);
}
TEST_P(InputStreamTest, GetInputFramesLost) {
- doc::test("The number of frames lost on a never started stream should be 0");
+ doc::test(
+ "The number of frames lost on a never started stream should be 0");
auto ret = stream->getInputFramesLost();
- ASSERT_TRUE(ret.isOk());
+ ASSERT_IS_OK(ret);
uint32_t framesLost{ret};
ASSERT_EQ(0U, framesLost);
}
TEST_P(InputStreamTest, getCapturePosition) {
- doc::test("The capture position of a non prepared stream should not be retrievable");
+ doc::test(
+ "The capture position of a non prepared stream should not be "
+ "retrievable");
uint64_t frames;
uint64_t time;
ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
@@ -961,36 +1126,44 @@
TEST_P(OutputStreamTest, getLatency) {
doc::test("Make sure latency is over 0");
auto result = stream->getLatency();
- ASSERT_TRUE(result.isOk());
+ ASSERT_IS_OK(result);
ASSERT_GT(result, 0U);
}
TEST_P(OutputStreamTest, setVolume) {
doc::test("Try to set the output volume");
- auto result = stream->setVolume(1, 1);
- ASSERT_TRUE(result.isOk());
- if (result == Result::NOT_SUPPORTED) {
- doc::partialTest("setVolume is not supported");
- return;
- }
- testUnitaryGain([this](float volume) { return stream->setVolume(volume, volume); });
+ testOptionalUnitaryGain(
+ [this](float volume) { return stream->setVolume(volume, volume); },
+ "setVolume");
}
-static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize,
+ uint32_t framesCount) {
Result res;
// Ignore output parameters as the call should fail
- ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
- [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+ ASSERT_OK(stream->prepareForWriting(
+ frameSize, framesCount,
+ [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
EXPECT_RESULT(invalidArgsOrNotSupported, res);
}
+TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
+ doc::test(
+ "Preparing a stream for writing with a 0 sized buffer should fail");
+ testPrepareForWriting(stream.get(), 0, 0);
+}
+
TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) {
- doc::test("Preparing a stream for writing with a 2^32 sized buffer should fail");
- testPrepareForWriting(stream.get(), 1, std::numeric_limits<uint32_t>::max());
+ doc::test(
+ "Preparing a stream for writing with a 2^32 sized buffer should fail");
+ testPrepareForWriting(stream.get(), 1,
+ std::numeric_limits<uint32_t>::max());
}
TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
- doc::test("Preparing a stream for writing with a overflowing sized buffer should fail");
+ doc::test(
+ "Preparing a stream for writing with a overflowing sized buffer should "
+ "fail");
auto uintMax = std::numeric_limits<uint32_t>::max();
testPrepareForWriting(stream.get(), uintMax, uintMax);
}
@@ -999,7 +1172,7 @@
Capability(IStreamOut* stream) {
EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
auto ret = stream->supportsDrain();
- EXPECT_TRUE(ret.isOk());
+ EXPECT_IS_OK(ret);
if (ret.isOk()) {
drain = ret;
}
@@ -1010,31 +1183,44 @@
};
TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) {
- doc::test("Implementation must expose pause, resume and drain capabilities");
+ doc::test(
+ "Implementation must expose pause, resume and drain capabilities");
Capability(stream.get());
}
+template <class Value>
+static void checkInvalidStateOr0(Result res, Value value) {
+ switch (res) {
+ case Result::INVALID_STATE:
+ break;
+ case Result::OK:
+ ASSERT_EQ(0U, value);
+ break;
+ default:
+ FAIL() << "Unexpected result " << toString(res);
+ }
+}
+
TEST_P(OutputStreamTest, GetRenderPosition) {
- doc::test("The render position should be 0 on a not started");
+ doc::test("A new stream render position should be 0 or INVALID_STATE");
uint32_t dspFrames;
ASSERT_OK(stream->getRenderPosition(returnIn(res, dspFrames)));
if (res == Result::NOT_SUPPORTED) {
doc::partialTest("getRenderPosition is not supported");
return;
}
- ASSERT_OK(res);
- ASSERT_EQ(0U, dspFrames);
+ checkInvalidStateOr0(res, dspFrames);
}
TEST_P(OutputStreamTest, GetNextWriteTimestamp) {
- doc::test("The render position of a stream just created should be 0");
+ doc::test("A new stream next write timestamp should be 0 or INVALID_STATE");
uint64_t timestampUs;
ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs)));
if (res == Result::NOT_SUPPORTED) {
doc::partialTest("getNextWriteTimestamp is not supported");
return;
}
- ASSERT_EQ(Result::INVALID_STATE, res);
+ checkInvalidStateOr0(res, timestampUs);
}
/** Stub implementation of out stream callback. */
@@ -1044,16 +1230,19 @@
Return<void> onError() override { return {}; }
};
-static bool isAsyncModeSupported(IStreamOut *stream) {
+static bool isAsyncModeSupported(IStreamOut* stream) {
auto res = stream->setCallback(new MockOutCallbacks);
- stream->clearCallback(); // try to restore the no callback state, ignore any error
- auto okOrNotSupported = { Result::OK, Result::NOT_SUPPORTED };
+ stream->clearCallback(); // try to restore the no callback state, ignore
+ // any error
+ auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
EXPECT_RESULT(okOrNotSupported, res);
return res.isOk() ? res == Result::OK : false;
}
TEST_P(OutputStreamTest, SetCallback) {
- doc::test("If supported, registering callback for async operation should never fail");
+ doc::test(
+ "If supported, registering callback for async operation should never "
+ "fail");
if (!isAsyncModeSupported(stream.get())) {
doc::partialTest("The stream does not support async operations");
return;
@@ -1063,7 +1252,9 @@
}
TEST_P(OutputStreamTest, clearCallback) {
- doc::test("If supported, clearing a callback to go back to sync operation should not fail");
+ doc::test(
+ "If supported, clearing a callback to go back to sync operation should "
+ "not fail");
if (!isAsyncModeSupported(stream.get())) {
doc::partialTest("The stream does not support async operations");
return;
@@ -1074,7 +1265,9 @@
}
TEST_P(OutputStreamTest, Resume) {
- doc::test("If supported, a stream should fail to resume if not previously paused");
+ doc::test(
+ "If supported, a stream should fail to resume if not previously "
+ "paused");
if (!Capability(stream.get()).resume) {
doc::partialTest("The output stream does not support resume");
return;
@@ -1083,7 +1276,9 @@
}
TEST_P(OutputStreamTest, Pause) {
- doc::test("If supported, a stream should fail to pause if not previously started");
+ doc::test(
+ "If supported, a stream should fail to pause if not previously "
+ "started");
if (!Capability(stream.get()).pause) {
doc::partialTest("The output stream does not support pause");
return;
@@ -1091,7 +1286,7 @@
ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
}
-static void testDrain(IStreamOut *stream, AudioDrain type) {
+static void testDrain(IStreamOut* stream, AudioDrain type) {
if (!Capability(stream).drain) {
doc::partialTest("The output stream does not support drain");
return;
@@ -1112,7 +1307,7 @@
TEST_P(OutputStreamTest, FlushStop) {
doc::test("If supported, a stream should always succeed to flush");
auto ret = stream->flush();
- ASSERT_TRUE(ret.isOk());
+ ASSERT_IS_OK(ret);
if (ret == Result::NOT_SUPPORTED) {
doc::partialTest("Flush is not supported");
return;
@@ -1121,7 +1316,9 @@
}
TEST_P(OutputStreamTest, GetPresentationPositionStop) {
- doc::test("If supported, a stream should always succeed to retrieve the presentation position");
+ doc::test(
+ "If supported, a stream should always succeed to retrieve the "
+ "presentation position");
uint64_t frames;
TimeSpec mesureTS;
ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS)));
@@ -1131,66 +1328,81 @@
}
ASSERT_EQ(0U, frames);
+ if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) {
+ // As the stream has never written a frame yet,
+ // the timestamp does not really have a meaning, allow to return 0
+ return;
+ }
+
+ // Make sure the return measure is not more than 1s old.
struct timespec currentTS;
ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤tTS)) << errno;
- auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
+ auto toMicroSec = [](uint64_t sec, auto nsec) {
+ return sec * 1e+6 + nsec / 1e+3;
+ };
auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec);
- ASSERT_PRED2([](auto c, auto m){ return c - m < 1e+6; }, currentTime, mesureTime);
+ ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime,
+ mesureTime);
}
-
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// PrimaryDevice ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
-
TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
- testUnitaryGain([this](float volume) { return device->setVoiceVolume(volume); });
+ testUnitaryGain(
+ [this](float volume) { return device->setVoiceVolume(volume); });
}
TEST_F(AudioPrimaryHidlTest, setMode) {
- doc::test("Make sure setMode always succeeds if mode is valid");
- for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION,
- AudioMode::RINGTONE, AudioMode::CURRENT,
- AudioMode::NORMAL /* Make sure to leave the test in normal mode */ }) {
+ doc::test(
+ "Make sure setMode always succeeds if mode is valid "
+ "and fails otherwise");
+ // Test Invalid values
+ for (AudioMode mode :
+ {AudioMode::INVALID, AudioMode::CURRENT, AudioMode::CNT}) {
+ SCOPED_TRACE("mode=" + toString(mode));
+ ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(mode));
+ }
+ // Test valid values
+ for (AudioMode mode :
+ {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
+ AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) {
SCOPED_TRACE("mode=" + toString(mode));
ASSERT_OK(device->setMode(mode));
}
-
- // FIXME: Missing api doc. What should the impl do if the mode is invalid ?
- ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode::INVALID));
}
-
TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
doc::test("Query and set the BT SCO NR&EC state");
testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
- &IPrimaryDevice::setBtScoNrecEnabled,
- &IPrimaryDevice::getBtScoNrecEnabled);
+ &IPrimaryDevice::setBtScoNrecEnabled,
+ &IPrimaryDevice::getBtScoNrecEnabled);
}
TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
doc::test("Query and set the SCO whideband state");
testOptionalAccessors("BtScoWideband", {true, false, true},
- &IPrimaryDevice::setBtScoWidebandEnabled,
- &IPrimaryDevice::getBtScoWidebandEnabled);
+ &IPrimaryDevice::setBtScoWidebandEnabled,
+ &IPrimaryDevice::getBtScoWidebandEnabled);
}
using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
doc::test("Query and set the TTY mode state");
- testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
- &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
+ testOptionalAccessors(
+ "TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
+ &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
}
TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
doc::test("Query and set the HAC state");
- testAccessors("HAC", {true, false, true},
- &IPrimaryDevice::setHacEnabled,
- &IPrimaryDevice::getHacEnabled);
+ testOptionalAccessors("HAC", {true, false, true},
+ &IPrimaryDevice::setHacEnabled,
+ &IPrimaryDevice::getHacEnabled);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/audio/2.0/vts/functional/utility/AssertOk.h b/audio/2.0/vts/functional/utility/AssertOk.h
index 10b088c..4c8440e 100644
--- a/audio/2.0/vts/functional/utility/AssertOk.h
+++ b/audio/2.0/vts/functional/utility/AssertOk.h
@@ -14,58 +14,105 @@
* limitations under the License.
*/
-#include <vector>
#include <algorithm>
+#include <vector>
#include <hidl/Status.h>
namespace detail {
-// This is a detail namespace, thus it is OK to import a class as nobody else is allowed to use it
+// This is a detail namespace, thus it is OK to import a class as nobody else is
+// allowed to use it
using ::android::hardware::Return;
using ::android::hardware::audio::V2_0::Result;
-inline void assertResult(Result expected, Result result) {
- ASSERT_EQ(expected, result);
+template <class T>
+inline ::testing::AssertionResult assertIsOk(const char* expr,
+ const Return<T>& ret) {
+ return ::testing::AssertionResult(ret.isOk())
+ << "Expected: " << expr
+ << "\n to be an OK Return but it is not: " << ret.description();
}
-inline void assertResult(Result expected, const Return<Result> &ret) {
- ASSERT_TRUE(ret.isOk());
- Result result = ret;
- assertResult(expected, result);
+// Call continuation if the provided result isOk
+template <class T, class Continuation>
+inline ::testing::AssertionResult continueIfIsOk(const char* expr,
+ const Return<T>& ret,
+ Continuation continuation) {
+ auto isOkStatus = assertIsOk(expr, ret);
+ return !isOkStatus ? isOkStatus : continuation();
}
-inline void assertResult(const std::vector<Result> &expected, Result result) {
+// Expect two equal Results
+inline ::testing::AssertionResult assertResult(const char* e_expr,
+ const char* r_expr,
+ Result expected, Result result) {
+ return ::testing::AssertionResult(expected == result)
+ << "Value of: " << r_expr
+ << "\n Actual: " << ::testing::PrintToString(result)
+ << "\nExpected: " << e_expr
+ << "\nWhich is: " << ::testing::PrintToString(expected);
+}
+
+// Expect two equal Results one being wrapped in an OK Return
+inline ::testing::AssertionResult assertResult(const char* e_expr,
+ const char* r_expr,
+ Result expected,
+ const Return<Result>& ret) {
+ return continueIfIsOk(r_expr, ret, [&] {
+ return assertResult(e_expr, r_expr, expected, Result{ret});
+ });
+}
+
+// Expect a Result to be part of a list of Results
+inline ::testing::AssertionResult assertResult(
+ const char* e_expr, const char* r_expr, const std::vector<Result>& expected,
+ Result result) {
if (std::find(expected.begin(), expected.end(), result) != expected.end()) {
- return; // result is in expected
+ return ::testing::AssertionSuccess(); // result is in expected
}
- FAIL() << "Expected result " << ::testing::PrintToString(result)
- << " to be one of " << ::testing::PrintToString(expected);
+ return ::testing::AssertionFailure()
+ << "Value of: " << r_expr
+ << "\n Actual: " << ::testing::PrintToString(result)
+ << "\nExpected one of: " << e_expr
+ << "\n Which is: " << ::testing::PrintToString(expected);
}
-inline void assertResult(const std::vector<Result> &expected, const Return<Result> &ret) {
- ASSERT_TRUE(ret.isOk());
- Result result = ret;
- assertResult(expected, result);
+// Expect a Result wrapped in an OK Return to be part of a list of Results
+inline ::testing::AssertionResult assertResult(
+ const char* e_expr, const char* r_expr, const std::vector<Result>& expected,
+ const Return<Result>& ret) {
+ return continueIfIsOk(r_expr, ret, [&] {
+ return assertResult(e_expr, r_expr, expected, Result{ret});
+ });
}
-inline void assertOk(const Return<void> &ret) {
- ASSERT_TRUE(ret.isOk());
+inline ::testing::AssertionResult assertOk(const char* expr,
+ const Return<void>& ret) {
+ return assertIsOk(expr, ret);
}
-inline void assertOk(Result result) {
- assertResult(Result::OK, result);
+inline ::testing::AssertionResult assertOk(const char* expr, Result result) {
+ return ::testing::AssertionResult(result == Result::OK)
+ << "Expected success: " << expr
+ << "\nActual: " << ::testing::PrintToString(result);
}
-inline void assertOk(const Return<Result> &ret) {
- assertResult(Result::OK, ret);
+inline ::testing::AssertionResult assertOk(const char* expr,
+ const Return<Result>& ret) {
+ return continueIfIsOk(expr, ret,
+ [&] { return assertOk(expr, Result{ret}); });
+}
}
-}
+#define ASSERT_IS_OK(ret) ASSERT_PRED_FORMAT1(detail::assertIsOk, ret)
+#define EXPECT_IS_OK(ret) EXPECT_PRED_FORMAT1(detail::assertIsOk, ret)
// Test anything provided is and contains only OK
-#define ASSERT_OK(ret) ASSERT_NO_FATAL_FAILURE(detail::assertOk(ret))
-#define EXPECT_OK(ret) EXPECT_NO_FATAL_FAILURE(detail::assertOk(ret))
+#define ASSERT_OK(ret) ASSERT_PRED_FORMAT1(detail::assertOk, ret)
+#define EXPECT_OK(ret) EXPECT_PRED_FORMAT1(detail::assertOk, ret)
-#define ASSERT_RESULT(expected, ret) ASSERT_NO_FATAL_FAILURE(detail::assertResult(expected, ret))
-#define EXPECT_RESULT(expected, ret) EXPECT_NO_FATAL_FAILURE(detail::assertResult(expected, ret))
+#define ASSERT_RESULT(expected, ret) \
+ ASSERT_PRED_FORMAT2(detail::assertResult, expected, ret)
+#define EXPECT_RESULT(expected, ret) \
+ EXPECT_PRED_FORMAT2(detail::assertResult, expected, ret)
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/RecurrentTimer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/RecurrentTimer.h
index be25adc..0ed8742 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/RecurrentTimer.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/RecurrentTimer.h
@@ -26,6 +26,7 @@
#include <set>
#include <thread>
#include <unordered_map>
+#include <vector>
/**
* This class allows to specify multiple time intervals to receive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 009485d..c25e083 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -25,14 +25,11 @@
#include <utils/SystemClock.h>
-#include "VehicleHalProto.pb.h"
-
#include <vhal_v2_0/RecurrentTimer.h>
#include <vhal_v2_0/VehicleHal.h>
#include "vhal_v2_0/VehiclePropertyStore.h"
#include "DefaultConfig.h"
-#include "VehicleHalProto.pb.h"
#include "VehicleEmulator.h"
#include "FakeValueGenerator.h"
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
index 1d19aa2..46e062b 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
@@ -23,7 +23,6 @@
#include <algorithm>
#include "EmulatedVehicleHal.h"
-#include "VehicleHalProto.pb.h"
#define DEBUG_SOCKET (33452)
diff --git a/bluetooth/1.0/default/service.cpp b/bluetooth/1.0/default/service.cpp
index fa5106f..a588c37 100644
--- a/bluetooth/1.0/default/service.cpp
+++ b/bluetooth/1.0/default/service.cpp
@@ -20,10 +20,13 @@
#include <hidl/LegacySupport.h>
+// Add an extra thread for calls to the scheduler service.
+static const size_t kMaxThreads = 2;
+
// Generated HIDL files
using android::hardware::bluetooth::V1_0::IBluetoothHci;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
- return defaultPassthroughServiceImplementation<IBluetoothHci>();
+ return defaultPassthroughServiceImplementation<IBluetoothHci>(kMaxThreads);
}
diff --git a/compatibility_matrix.xml b/compatibility_matrix.xml
index c643fc7..51a096c 100644
--- a/compatibility_matrix.xml
+++ b/compatibility_matrix.xml
@@ -8,6 +8,14 @@
<version>2.0</version>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.automotive.evs</name>
+ <version>1.0</version>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.vehicle</name>
+ <version>2.1</version>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>2.1</version>
</hal>
diff --git a/configstore/utils/include/configstore/Utils.h b/configstore/utils/include/configstore/Utils.h
index a54ce85..c9c830b 100644
--- a/configstore/utils/include/configstore/Utils.h
+++ b/configstore/utils/include/configstore/Utils.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
#define ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.0/types.h>
#include <hidl/Status.h>
#include <sstream>
@@ -34,7 +34,14 @@
} // namespace details
namespace configstore {
-using namespace android::hardware::configstore::V1_0;
+// import types from V1_0
+using ::android::hardware::configstore::V1_0::OptionalBool;
+using ::android::hardware::configstore::V1_0::OptionalInt32;
+using ::android::hardware::configstore::V1_0::OptionalUInt32;
+using ::android::hardware::configstore::V1_0::OptionalInt64;
+using ::android::hardware::configstore::V1_0::OptionalUInt64;
+using ::android::hardware::configstore::V1_0::OptionalString;
+
// arguments V: type for the value (i.e., OptionalXXX)
// I: interface class name
// func: member function pointer
diff --git a/graphics/composer/2.1/default/service.cpp b/graphics/composer/2.1/default/service.cpp
index aa0604a..82a33f6 100644
--- a/graphics/composer/2.1/default/service.cpp
+++ b/graphics/composer/2.1/default/service.cpp
@@ -40,5 +40,5 @@
ALOGE("Couldn't set SCHED_FIFO: %d", errno);
}
- return defaultPassthroughServiceImplementation<IComposer>();
+ return defaultPassthroughServiceImplementation<IComposer>(4);
}