Merge changes from topic "HWC3-V3-VRR" into main
* changes:
[Composer VTS] Adds VTS for the vrr configuration
[Composer-HAL-AIDL] Adds vrr interface configuration
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 5478633..eb9cbc3 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -675,7 +675,7 @@
nullptr, nullptr, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamIn> stream;
- RETURN_STATUS_IF_ERROR(createInputStream(in_args.sinkMetadata, std::move(context),
+ RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
mConfig->microphones, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
@@ -721,7 +721,7 @@
in_args.eventCallback, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamOut> stream;
- RETURN_STATUS_IF_ERROR(createOutputStream(in_args.sourceMetadata, std::move(context),
+ RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata,
in_args.offloadInfo, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
index cbb6730..d8ea9e7 100644
--- a/audio/aidl/default/ModulePrimary.cpp
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -38,22 +38,23 @@
mTelephony = ndk::SharedRefBase::make<Telephony>();
}
*_aidl_return = mTelephony.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
+ LOG(DEBUG) << __func__
+ << ": returning instance of ITelephony: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus ModulePrimary::createInputStream(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
+ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
+ const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
- return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
+ return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModulePrimary::createOutputStream(
- const SourceMetadata& sourceMetadata, StreamContext&& context,
+ StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
- return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
+ return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
offloadInfo);
}
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 215de94..f4194d2 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -47,13 +47,19 @@
desc->reply = mReplyMQ->dupeDesc();
}
if (mDataMQ) {
- const size_t frameSize = getFrameSize();
- desc->frameSizeBytes = frameSize;
- desc->bufferSizeFrames = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / frameSize;
+ desc->frameSizeBytes = getFrameSize();
+ desc->bufferSizeFrames = getBufferSizeInFrames();
desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
}
}
+size_t StreamContext::getBufferSizeInFrames() const {
+ if (mDataMQ) {
+ return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize();
+ }
+ return 0;
+}
+
size_t StreamContext::getFrameSize() const {
return getFrameSizeInBytes(mFormat, mChannelLayout);
}
@@ -597,18 +603,16 @@
ndk::ScopedAStatus StreamCommonImpl::initInstance(
const std::shared_ptr<StreamCommonInterface>& delegate) {
mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
- mCommonBinder = mCommon->asBinder();
- AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
return mWorker->start() ? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
std::shared_ptr<IStreamCommon>* _aidl_return) {
- if (mCommon == nullptr) {
+ if (!mCommon) {
LOG(FATAL) << __func__ << ": the common interface was not created";
}
- *_aidl_return = mCommon;
+ *_aidl_return = mCommon.getPtr();
LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -659,7 +663,7 @@
LOG(DEBUG) << __func__ << ": joining the worker thread...";
mWorker->stop();
LOG(DEBUG) << __func__ << ": worker thread joined";
- mContext.reset();
+ onClose();
mWorker->setClosed();
return ndk::ScopedAStatus::ok();
} else {
@@ -723,11 +727,15 @@
}
} // namespace
-StreamIn::StreamIn(const std::vector<MicrophoneInfo>& microphones)
- : mMicrophones(transformMicrophones(microphones)) {
+StreamIn::StreamIn(StreamContext&& context, const std::vector<MicrophoneInfo>& microphones)
+ : mContext(std::move(context)), mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
+void StreamIn::defaultOnClose() {
+ mContext.reset();
+}
+
ndk::ScopedAStatus StreamIn::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
std::vector<MicrophoneDynamicInfo> result;
@@ -780,11 +788,15 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-StreamOut::StreamOut(const std::optional<AudioOffloadInfo>& offloadInfo)
- : mOffloadInfo(offloadInfo) {
+StreamOut::StreamOut(StreamContext&& context, const std::optional<AudioOffloadInfo>& offloadInfo)
+ : mContext(std::move(context)), mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
+void StreamOut::defaultOnClose() {
+ mContext.reset();
+}
+
ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
const AudioOffloadMetadata& in_offloadMetadata) {
LOG(DEBUG) << __func__;
diff --git a/audio/aidl/default/alsa/Mixer.cpp b/audio/aidl/default/alsa/Mixer.cpp
index f0393e3..126c033 100644
--- a/audio/aidl/default/alsa/Mixer.cpp
+++ b/audio/aidl/default/alsa/Mixer.cpp
@@ -14,44 +14,17 @@
* limitations under the License.
*/
-#define LOG_TAG "AHAL_AlsaMixer"
-#include <android-base/logging.h>
-
+#include <algorithm>
#include <cmath>
+#define LOG_TAG "AHAL_AlsaMixer"
+#include <android-base/logging.h>
#include <android/binder_status.h>
#include "Mixer.h"
namespace aidl::android::hardware::audio::core::alsa {
-//-----------------------------------------------------------------------------
-
-MixerControl::MixerControl(struct mixer_ctl* ctl)
- : mCtl(ctl),
- mNumValues(mixer_ctl_get_num_values(ctl)),
- mMinValue(mixer_ctl_get_range_min(ctl)),
- mMaxValue(mixer_ctl_get_range_max(ctl)) {}
-
-unsigned int MixerControl::getNumValues() const {
- return mNumValues;
-}
-
-int MixerControl::getMaxValue() const {
- return mMaxValue;
-}
-
-int MixerControl::getMinValue() const {
- return mMinValue;
-}
-
-int MixerControl::setArray(const void* array, size_t count) {
- const std::lock_guard guard(mLock);
- return mixer_ctl_set_array(mCtl, array, count);
-}
-
-//-----------------------------------------------------------------------------
-
// static
const std::map<Mixer::Control, std::vector<Mixer::ControlNamesAndExpectedCtlType>>
Mixer::kPossibleControls = {
@@ -60,18 +33,20 @@
{Mixer::HW_VOLUME,
{{"Headphone Playback Volume", MIXER_CTL_TYPE_INT},
{"Headset Playback Volume", MIXER_CTL_TYPE_INT},
- {"PCM Playback Volume", MIXER_CTL_TYPE_INT}}}};
+ {"PCM Playback Volume", MIXER_CTL_TYPE_INT}}},
+ {Mixer::MIC_SWITCH, {{"Capture Switch", MIXER_CTL_TYPE_BOOL}}},
+ {Mixer::MIC_GAIN, {{"Capture Volume", MIXER_CTL_TYPE_INT}}}};
// static
-std::map<Mixer::Control, std::shared_ptr<MixerControl>> Mixer::initializeMixerControls(
- struct mixer* mixer) {
- std::map<Mixer::Control, std::shared_ptr<MixerControl>> mixerControls;
+Mixer::Controls Mixer::initializeMixerControls(struct mixer* mixer) {
+ if (mixer == nullptr) return {};
+ Controls mixerControls;
std::string mixerCtlNames;
for (const auto& [control, possibleCtls] : kPossibleControls) {
for (const auto& [ctlName, expectedCtlType] : possibleCtls) {
struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str());
if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) {
- mixerControls.emplace(control, std::make_unique<MixerControl>(ctl));
+ mixerControls.emplace(control, ctl);
if (!mixerCtlNames.empty()) {
mixerCtlNames += ",";
}
@@ -84,71 +59,141 @@
return mixerControls;
}
-Mixer::Mixer(struct mixer* mixer)
- : mMixer(mixer), mMixerControls(initializeMixerControls(mMixer)) {}
+std::ostream& operator<<(std::ostream& s, Mixer::Control c) {
+ switch (c) {
+ case Mixer::Control::MASTER_SWITCH:
+ s << "master mute";
+ break;
+ case Mixer::Control::MASTER_VOLUME:
+ s << "master volume";
+ break;
+ case Mixer::Control::HW_VOLUME:
+ s << "volume";
+ break;
+ case Mixer::Control::MIC_SWITCH:
+ s << "mic mute";
+ break;
+ case Mixer::Control::MIC_GAIN:
+ s << "mic gain";
+ break;
+ }
+ return s;
+}
+
+Mixer::Mixer(int card) : mMixer(mixer_open(card)), mMixerControls(initializeMixerControls(mMixer)) {
+ if (!isValid()) {
+ PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
+ }
+}
Mixer::~Mixer() {
- mixer_close(mMixer);
+ if (isValid()) {
+ std::lock_guard l(mMixerAccess);
+ mixer_close(mMixer);
+ }
}
-namespace {
-
-int volumeFloatToInteger(float fValue, int maxValue, int minValue) {
- return minValue + std::ceil((maxValue - minValue) * fValue);
-}
-
-} // namespace
-
ndk::ScopedAStatus Mixer::setMasterMute(bool muted) {
- auto it = mMixerControls.find(Mixer::MASTER_SWITCH);
- if (it == mMixerControls.end()) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
- }
- const int numValues = it->second->getNumValues();
- std::vector<int> values(numValues, muted ? 0 : 1);
- if (int err = it->second->setArray(values.data(), numValues); err != 0) {
- LOG(ERROR) << __func__ << ": failed to set master mute, err=" << err;
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- return ndk::ScopedAStatus::ok();
+ return setMixerControlMute(MASTER_SWITCH, muted);
}
ndk::ScopedAStatus Mixer::setMasterVolume(float volume) {
- auto it = mMixerControls.find(Mixer::MASTER_VOLUME);
- if (it == mMixerControls.end()) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
- }
- const int numValues = it->second->getNumValues();
- std::vector<int> values(numValues, volumeFloatToInteger(volume, it->second->getMaxValue(),
- it->second->getMinValue()));
- if (int err = it->second->setArray(values.data(), numValues); err != 0) {
- LOG(ERROR) << __func__ << ": failed to set master volume, err=" << err;
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- return ndk::ScopedAStatus::ok();
+ return setMixerControlVolume(MASTER_VOLUME, volume);
+}
+
+ndk::ScopedAStatus Mixer::setMicGain(float gain) {
+ return setMixerControlVolume(MIC_GAIN, gain);
+}
+
+ndk::ScopedAStatus Mixer::setMicMute(bool muted) {
+ return setMixerControlMute(MIC_SWITCH, muted);
}
ndk::ScopedAStatus Mixer::setVolumes(const std::vector<float>& volumes) {
+ if (!isValid()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
auto it = mMixerControls.find(Mixer::HW_VOLUME);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
- const int numValues = it->second->getNumValues();
- if (numValues < 0) {
- LOG(FATAL) << __func__ << ": negative number of values: " << numValues;
- }
- const int maxValue = it->second->getMaxValue();
- const int minValue = it->second->getMinValue();
- std::vector<int> values;
- size_t i = 0;
- for (; i < static_cast<size_t>(numValues) && i < values.size(); ++i) {
- values.emplace_back(volumeFloatToInteger(volumes[i], maxValue, minValue));
- }
- if (int err = it->second->setArray(values.data(), values.size()); err != 0) {
+ std::vector<int> percents;
+ std::transform(
+ volumes.begin(), volumes.end(), std::back_inserter(percents),
+ [](float volume) -> int { return std::floor(std::clamp(volume, 0.0f, 1.0f) * 100); });
+ std::lock_guard l(mMixerAccess);
+ if (int err = setMixerControlPercent(it->second, percents); err != 0) {
LOG(ERROR) << __func__ << ": failed to set volume, err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Mixer::setMixerControlMute(Mixer::Control ctl, bool muted) {
+ if (!isValid()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ auto it = mMixerControls.find(ctl);
+ if (it == mMixerControls.end()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ std::lock_guard l(mMixerAccess);
+ if (int err = setMixerControlValue(it->second, muted ? 0 : 1); err != 0) {
+ LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << muted << ", err=" << err;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Mixer::setMixerControlVolume(Control ctl, float volume) {
+ if (!isValid()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ auto it = mMixerControls.find(ctl);
+ if (it == mMixerControls.end()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ volume = std::clamp(volume, 0.0f, 1.0f);
+ std::lock_guard l(mMixerAccess);
+ if (int err = setMixerControlPercent(it->second, std::floor(volume * 100)); err != 0) {
+ LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << volume << ", err=" << err;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, int percent) {
+ int ret = 0;
+ const unsigned int n = mixer_ctl_get_num_values(ctl);
+ for (unsigned int id = 0; id < n; id++) {
+ if (int error = mixer_ctl_set_percent(ctl, id, percent); error != 0) {
+ ret = error;
+ }
+ }
+ return ret;
+}
+
+int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) {
+ int ret = 0;
+ const unsigned int n = mixer_ctl_get_num_values(ctl);
+ for (unsigned int id = 0; id < n; id++) {
+ if (int error = mixer_ctl_set_percent(ctl, id, id < percents.size() ? percents[id] : 0);
+ error != 0) {
+ ret = error;
+ }
+ }
+ return ret;
+}
+
+int Mixer::setMixerControlValue(struct mixer_ctl* ctl, int value) {
+ int ret = 0;
+ const unsigned int n = mixer_ctl_get_num_values(ctl);
+ for (unsigned int id = 0; id < n; id++) {
+ if (int error = mixer_ctl_set_value(ctl, id, value); error != 0) {
+ ret = error;
+ }
+ }
+ return ret;
+}
+
} // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/Mixer.h b/audio/aidl/default/alsa/Mixer.h
index de9e6f4..78728c2 100644
--- a/audio/aidl/default/alsa/Mixer.h
+++ b/audio/aidl/default/alsa/Mixer.h
@@ -16,6 +16,7 @@
#pragma once
+#include <iostream>
#include <map>
#include <memory>
#include <mutex>
@@ -31,34 +32,17 @@
namespace aidl::android::hardware::audio::core::alsa {
-class MixerControl {
- public:
- explicit MixerControl(struct mixer_ctl* ctl);
-
- unsigned int getNumValues() const;
- int getMaxValue() const;
- int getMinValue() const;
- int setArray(const void* array, size_t count);
-
- private:
- std::mutex mLock;
- // The mixer_ctl object is owned by ALSA and will be released when the mixer is closed.
- struct mixer_ctl* mCtl GUARDED_BY(mLock);
- const unsigned int mNumValues;
- const int mMinValue;
- const int mMaxValue;
-};
-
class Mixer {
public:
- explicit Mixer(struct mixer* mixer);
-
+ explicit Mixer(int card);
~Mixer();
bool isValid() const { return mMixer != nullptr; }
ndk::ScopedAStatus setMasterMute(bool muted);
ndk::ScopedAStatus setMasterVolume(float volume);
+ ndk::ScopedAStatus setMicGain(float gain);
+ ndk::ScopedAStatus setMicMute(bool muted);
ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes);
private:
@@ -66,17 +50,32 @@
MASTER_SWITCH,
MASTER_VOLUME,
HW_VOLUME,
+ MIC_SWITCH,
+ MIC_GAIN,
};
using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>;
- static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
- static std::map<Control, std::shared_ptr<MixerControl>> initializeMixerControls(
- struct mixer* mixer);
+ using Controls = std::map<Control, struct mixer_ctl*>;
+ friend std::ostream& operator<<(std::ostream&, Control);
+ static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
+ static Controls initializeMixerControls(struct mixer* mixer);
+
+ ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted);
+ ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume);
+
+ int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess);
+ int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents)
+ REQUIRES(mMixerAccess);
+ int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess);
+
+ // Since ALSA functions do not use internal locking, enforce thread safety at our level.
+ std::mutex mMixerAccess;
// The mixer object is owned by ALSA and will be released when the mixer is closed.
- struct mixer* mMixer;
+ struct mixer* const mMixer;
// `mMixerControls` will only be initialized in constructor. After that, it wil only be
- // read but not be modified.
- const std::map<Control, std::shared_ptr<MixerControl>> mMixerControls;
+ // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is
+ // the same as of the mixer itself.
+ const Controls mMixerControls;
};
} // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 17c7feb..c7fb022 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -27,16 +27,32 @@
namespace aidl::android::hardware::audio::core {
-StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context)
- : StreamCommonImpl(metadata, std::move(context)),
+StreamAlsa::StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries)
+ : StreamCommonImpl(context, metadata),
mFrameSizeBytes(getContext().getFrameSize()),
mIsInput(isInput(metadata)),
- mConfig(alsa::getPcmConfig(getContext(), mIsInput)) {}
+ mConfig(alsa::getPcmConfig(getContext(), mIsInput)),
+ mReadWriteRetries(readWriteRetries) {}
::android::status_t StreamAlsa::init() {
return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
}
+::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamAlsa::flush() {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamAlsa::pause() {
+ usleep(1000);
+ return ::android::OK;
+}
+
::android::status_t StreamAlsa::standby() {
mAlsaDeviceProxies.clear();
return ::android::OK;
@@ -45,27 +61,21 @@
::android::status_t StreamAlsa::start() {
decltype(mAlsaDeviceProxies) alsaDeviceProxies;
for (const auto& device : getDeviceProfiles()) {
- auto profile = alsa::readAlsaDeviceInfo(device);
- if (!profile.has_value()) {
- LOG(ERROR) << __func__ << ": unable to read device info, device address=" << device;
- return ::android::UNKNOWN_ERROR;
+ alsa::DeviceProxy proxy;
+ if (device.isExternal) {
+ // Always ask alsa configure as required since the configuration should be supported
+ // by the connected device. That is guaranteed by `setAudioPortConfig` and
+ // `setAudioPatch`.
+ proxy = alsa::openProxyForExternalDevice(
+ device, const_cast<struct pcm_config*>(&mConfig.value()),
+ true /*require_exact_match*/);
+ } else {
+ proxy = alsa::openProxyForAttachedDevice(
+ device, const_cast<struct pcm_config*>(&mConfig.value()),
+ getContext().getBufferSizeInFrames());
}
-
- auto proxy = alsa::makeDeviceProxy();
- // Always ask for alsa configure as required since the configuration should be supported
- // by the connected device. That is guaranteed by `setAudioPortConfig` and `setAudioPatch`.
- if (int err = proxy_prepare(proxy.get(), &profile.value(),
- const_cast<struct pcm_config*>(&mConfig.value()),
- true /*require_exact_match*/);
- err != 0) {
- LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device
- << " error=" << err;
- return ::android::UNKNOWN_ERROR;
- }
- if (int err = proxy_open(proxy.get()); err != 0) {
- LOG(ERROR) << __func__ << ": failed to open device, address=" << device
- << " error=" << err;
- return ::android::UNKNOWN_ERROR;
+ if (!proxy) {
+ return ::android::NO_INIT;
}
alsaDeviceProxies.push_back(std::move(proxy));
}
@@ -83,11 +93,12 @@
return ::android::NO_INIT;
}
// For input case, only support single device.
- proxy_read(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer);
+ proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer,
+ mReadWriteRetries);
maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
} else {
for (auto& proxy : mAlsaDeviceProxies) {
- proxy_write(proxy.get(), buffer, bytesToTransfer);
+ proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
}
}
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 162f852..20f7797 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -217,7 +217,8 @@
}
return DeviceProfile{.card = alsaAddress[0],
.device = alsaAddress[1],
- .direction = isInput ? PCM_IN : PCM_OUT};
+ .direction = isInput ? PCM_IN : PCM_OUT,
+ .isExternal = !audioDevice.type.connection.empty()};
}
std::optional<DeviceProfile> getDeviceProfile(
@@ -269,6 +270,57 @@
});
}
+DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
+ struct pcm_config* pcmConfig, size_t bufferFrameCount) {
+ if (deviceProfile.isExternal) {
+ LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile;
+ }
+ alsa_device_profile profile;
+ profile_init(&profile, deviceProfile.direction);
+ profile.card = deviceProfile.card;
+ profile.device = deviceProfile.device;
+ if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) {
+ LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile;
+ }
+ auto proxy = makeDeviceProxy();
+ if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) {
+ LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile
+ << " error=" << err;
+ return nullptr;
+ }
+ if (int err = proxy_open(proxy.get()); err != 0) {
+ LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
+ << " error=" << err;
+ return nullptr;
+ }
+ return proxy;
+}
+
+DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
+ struct pcm_config* pcmConfig, bool requireExactMatch) {
+ if (!deviceProfile.isExternal) {
+ LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile;
+ }
+ auto profile = readAlsaDeviceInfo(deviceProfile);
+ if (!profile.has_value()) {
+ LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
+ return nullptr;
+ }
+ auto proxy = makeDeviceProxy();
+ if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch);
+ err != 0) {
+ LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile
+ << " error=" << err;
+ return nullptr;
+ }
+ if (int err = proxy_open(proxy.get()); err != 0) {
+ LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
+ << " error=" << err;
+ return nullptr;
+ }
+ return proxy;
+}
+
std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
alsa_device_profile profile;
profile_init(&profile, deviceProfile.direction);
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index c1b9b38..615e657 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -40,6 +40,7 @@
int card;
int device;
int direction; /* PCM_OUT or PCM_IN */
+ bool isExternal;
};
std::ostream& operator<<(std::ostream& os, const DeviceProfile& device);
using DeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
@@ -60,6 +61,10 @@
std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput);
std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile);
DeviceProxy makeDeviceProxy();
+DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
+ struct pcm_config* pcmConfig, size_t bufferFrameCount);
+DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
+ struct pcm_config* pcmConfig, bool requireExactMatch);
std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
::aidl::android::media::audio::common::AudioFormatDescription
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 294cc0e..539221d 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -159,13 +159,13 @@
// The following virtual functions are intended for vendor extension via inheritance.
virtual ndk::ScopedAStatus createInputStream(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) = 0;
virtual ndk::ScopedAStatus createOutputStream(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) = 0;
diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h
index bc808ab..6264237 100644
--- a/audio/aidl/default/include/core-impl/ModulePrimary.h
+++ b/audio/aidl/default/include/core-impl/ModulePrimary.h
@@ -28,13 +28,13 @@
ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
ndk::ScopedAStatus createInputStream(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
index ccfcdd9..e87be3d 100644
--- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -33,13 +33,13 @@
// Module interfaces
ndk::ScopedAStatus createInputStream(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
diff --git a/audio/aidl/default/include/core-impl/ModuleStub.h b/audio/aidl/default/include/core-impl/ModuleStub.h
index 59c343f..4f77161 100644
--- a/audio/aidl/default/include/core-impl/ModuleStub.h
+++ b/audio/aidl/default/include/core-impl/ModuleStub.h
@@ -30,13 +30,13 @@
ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
ndk::ScopedAStatus createInputStream(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index e6b3e66..a296b8c 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -33,13 +33,13 @@
// Module interfaces
ndk::ScopedAStatus createInputStream(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index e64c578..355d3b4 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -43,6 +43,7 @@
#include <system/thread_defs.h>
#include <utils/Errors.h>
+#include "core-impl/ChildInterface.h"
#include "core-impl/utils.h"
namespace aidl::android::hardware::audio::core {
@@ -132,6 +133,7 @@
void fillDescriptor(StreamDescriptor* desc);
std::shared_ptr<IStreamCallback> getAsyncCallback() const { return mAsyncCallback; }
+ size_t getBufferSizeInFrames() const;
::aidl::android::media::audio::common::AudioChannelLayout getChannelLayout() const {
return mChannelLayout;
}
@@ -409,16 +411,17 @@
};
// The implementation of DriverInterface must be provided by each concrete stream implementation.
+// Note that StreamCommonImpl does not own the context. This is to support swapping on the fly
+// implementations of the stream while keeping the same IStreamIn/Out instance. It's that instance
+// who must be owner of the context.
class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface {
public:
- StreamCommonImpl(const Metadata& metadata, StreamContext&& context,
+ StreamCommonImpl(const StreamContext& context, const Metadata& metadata,
const StreamWorkerInterface::CreateInstance& createWorker)
- : mMetadata(metadata),
- mContext(std::move(context)),
- mWorker(createWorker(mContext, this)) {}
- StreamCommonImpl(const Metadata& metadata, StreamContext&& context)
+ : mContext(context), mMetadata(metadata), mWorker(createWorker(mContext, this)) {}
+ StreamCommonImpl(const StreamContext& context, const Metadata& metadata)
: StreamCommonImpl(
- metadata, std::move(context),
+ context, metadata,
isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
~StreamCommonImpl();
@@ -460,13 +463,13 @@
};
}
+ virtual void onClose() = 0;
void stopWorker();
+ const StreamContext& mContext;
Metadata mMetadata;
- StreamContext mContext;
std::unique_ptr<StreamWorkerInterface> mWorker;
- std::shared_ptr<StreamCommonDelegator> mCommon;
- ndk::SpAIBinder mCommonBinder;
+ ChildInterface<StreamCommonDelegator> mCommon;
ConnectedDevices mConnectedDevices;
};
@@ -474,6 +477,8 @@
// concrete input/output stream implementations.
class StreamIn : virtual public StreamCommonInterface, public BnStreamIn {
protected:
+ void defaultOnClose();
+
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
return getStreamCommonCommon(_aidl_return);
}
@@ -493,14 +498,17 @@
friend class ndk::SharedRefBase;
- explicit StreamIn(
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+ StreamIn(StreamContext&& context,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+ StreamContext mContext;
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
protected:
+ void defaultOnClose();
+
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
return getStreamCommonCommon(_aidl_return);
}
@@ -534,10 +542,12 @@
friend class ndk::SharedRefBase;
- explicit StreamOut(const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo);
+ StreamOut(StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
- std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
+ StreamContext mContext;
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
};
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index 5744d66..90d2e36 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -31,9 +31,12 @@
// provide necessary overrides for all interface methods omitted here.
class StreamAlsa : public StreamCommonImpl {
public:
- StreamAlsa(const Metadata& metadata, StreamContext&& context);
+ StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries);
// Methods of 'DriverInterface'.
::android::status_t init() override;
+ ::android::status_t drain(StreamDescriptor::DrainMode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
::android::status_t standby() override;
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
@@ -48,6 +51,7 @@
const size_t mFrameSizeBytes;
const bool mIsInput;
const std::optional<struct pcm_config> mConfig;
+ const int mReadWriteRetries;
// All fields below are only used on the worker thread.
std::vector<alsa::DeviceProxy> mAlsaDeviceProxies;
};
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index 1bca910..4c984af 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -29,7 +29,7 @@
class StreamRemoteSubmix : public StreamCommonImpl {
public:
- StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context);
+ StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata);
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -72,28 +72,32 @@
static constexpr int kReadAttemptSleepUs = 5000;
};
-class StreamInRemoteSubmix final : public StreamRemoteSubmix, public StreamIn {
+class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamInRemoteSubmix(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
+ void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
-class StreamOutRemoteSubmix final : public StreamRemoteSubmix, public StreamOut {
+class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamOutRemoteSubmix(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
+
+ private:
+ void onClose() override { defaultOnClose(); }
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index 6b1b2dd..2a92deb 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -22,7 +22,7 @@
class StreamStub : public StreamCommonImpl {
public:
- StreamStub(const Metadata& metadata, StreamContext&& context);
+ StreamStub(const StreamContext& context, const Metadata& metadata);
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -43,22 +43,28 @@
bool mIsStandby = true; // Used for validating the state machine logic.
};
-class StreamInStub final : public StreamStub, public StreamIn {
+class StreamInStub final : public StreamIn, public StreamStub {
public:
friend class ndk::SharedRefBase;
StreamInStub(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+ private:
+ void onClose() override { defaultOnClose(); }
};
-class StreamOutStub final : public StreamStub, public StreamOut {
+class StreamOutStub final : public StreamOut, public StreamStub {
public:
friend class ndk::SharedRefBase;
- StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
+ StreamOutStub(StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
+
+ private:
+ void onClose() override { defaultOnClose(); }
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 44f742a..7dc7296 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -28,11 +28,8 @@
class StreamUsb : public StreamAlsa {
public:
- StreamUsb(const Metadata& metadata, StreamContext&& context);
+ StreamUsb(const StreamContext& context, const Metadata& metadata);
// Methods of 'DriverInterface'.
- ::android::status_t drain(StreamDescriptor::DrainMode) override;
- ::android::status_t flush() override;
- ::android::status_t pause() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
@@ -47,29 +44,31 @@
std::atomic<bool> mConnectedDevicesUpdated = false;
};
-class StreamInUsb final : public StreamUsb, public StreamIn {
+class StreamInUsb final : public StreamIn, public StreamUsb {
public:
friend class ndk::SharedRefBase;
StreamInUsb(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
+ void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
-class StreamOutUsb final : public StreamUsb, public StreamOut {
+class StreamOutUsb final : public StreamOut, public StreamUsb {
public:
friend class ndk::SharedRefBase;
- StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
+ StreamOutUsb(StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
private:
+ void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index 2b79f51..9be7837 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -56,16 +56,16 @@
}
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
- const SinkMetadata& sinkMetadata, StreamContext&& context,
+ StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
- return createStreamInstance<StreamInRemoteSubmix>(result, sinkMetadata, std::move(context),
+ return createStreamInstance<StreamInRemoteSubmix>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
- const SourceMetadata& sourceMetadata, StreamContext&& context,
+ StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
- return createStreamInstance<StreamOutRemoteSubmix>(result, sourceMetadata, std::move(context),
+ return createStreamInstance<StreamOutRemoteSubmix>(result, std::move(context), sourceMetadata,
offloadInfo);
}
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index 6d5185b..53d4aa6 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -29,8 +29,8 @@
namespace aidl::android::hardware::audio::core {
-StreamRemoteSubmix::StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context)
- : StreamCommonImpl(metadata, std::move(context)),
+StreamRemoteSubmix::StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata)
+ : StreamCommonImpl(context, metadata),
mPortId(context.getPortId()),
mIsInput(isInput(metadata)) {
mStreamConfig.frameSize = context.getFrameSize();
@@ -353,10 +353,11 @@
return ::android::OK;
}
-StreamInRemoteSubmix::StreamInRemoteSubmix(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
+StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
+ const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamRemoteSubmix(sinkMetadata, std::move(context)), StreamIn(microphones) {}
+ : StreamIn(std::move(context), microphones),
+ StreamRemoteSubmix(StreamIn::mContext, sinkMetadata) {}
ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
@@ -365,9 +366,10 @@
return ndk::ScopedAStatus::ok();
}
-StreamOutRemoteSubmix::StreamOutRemoteSubmix(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
+StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
+ const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamRemoteSubmix(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
+ : StreamOut(std::move(context), offloadInfo),
+ StreamRemoteSubmix(StreamOut::mContext, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
index 8f5b8cb..ddac64d 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.cpp
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -27,7 +27,7 @@
namespace aidl::android::hardware::audio::core::r_submix {
// Verify a submix input or output stream can be opened.
-bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig streamConfig) {
+bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
// If the stream is already open, don't open it again.
// ENABLE_LEGACY_INPUT_OPEN is default behaviour
if (!isInput && isStreamOutOpen()) {
@@ -43,7 +43,7 @@
// Compare this stream config with existing pipe config, returning false if they do *not*
// match, true otherwise.
-bool SubmixRoute::isStreamConfigCompatible(const AudioConfig streamConfig) {
+bool SubmixRoute::isStreamConfigCompatible(const AudioConfig& streamConfig) {
if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
<< streamConfig.channelLayout.toString()
@@ -126,7 +126,7 @@
// If SubmixRoute doesn't exist for a port, create a pipe for the submix audio device of size
// buffer_size_frames and store config of the submix audio device.
-::android::status_t SubmixRoute::createPipe(const AudioConfig streamConfig) {
+::android::status_t SubmixRoute::createPipe(const AudioConfig& streamConfig) {
const int channelCount = getChannelCount(streamConfig.channelLayout);
const audio_format_t audioFormat = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioFormatDescription_audio_format_t(streamConfig.format));
@@ -201,9 +201,9 @@
if (isInput) {
mStreamInStandby = true;
- } else {
+ } else if (!mStreamOutStandby) {
mStreamOutStandby = true;
- mStreamOutStandbyTransition = !mStreamOutStandbyTransition;
+ mStreamOutStandbyTransition = true;
}
}
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
index 5f7ea75..1a98df2 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.h
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -93,9 +93,9 @@
return mSource;
}
- bool isStreamConfigValid(bool isInput, const AudioConfig streamConfig);
+ bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig);
void closeStream(bool isInput);
- ::android::status_t createPipe(const AudioConfig streamConfig);
+ ::android::status_t createPipe(const AudioConfig& streamConfig);
void exitStandby(bool isInput);
bool hasAtleastOneStreamOpen();
int notifyReadError();
@@ -107,7 +107,7 @@
long updateReadCounterFrames(size_t frameCount);
private:
- bool isStreamConfigCompatible(const AudioConfig streamConfig);
+ bool isStreamConfigCompatible(const AudioConfig& streamConfig);
std::mutex mLock;
diff --git a/audio/aidl/default/stub/ModuleStub.cpp b/audio/aidl/default/stub/ModuleStub.cpp
index a600752..5e4cd88 100644
--- a/audio/aidl/default/stub/ModuleStub.cpp
+++ b/audio/aidl/default/stub/ModuleStub.cpp
@@ -38,7 +38,8 @@
mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
}
*_aidl_return = mBluetooth.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get();
+ LOG(DEBUG) << __func__
+ << ": returning instance of IBluetooth: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -47,7 +48,8 @@
mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
}
*_aidl_return = mBluetoothA2dp.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+ LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: "
+ << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -56,22 +58,23 @@
mBluetoothLe = ndk::SharedRefBase::make<BluetoothLe>();
}
*_aidl_return = mBluetoothLe.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+ LOG(DEBUG) << __func__
+ << ": returning instance of IBluetoothLe: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus ModuleStub::createInputStream(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
+ndk::ScopedAStatus ModuleStub::createInputStream(StreamContext&& context,
+ const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
- return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
+ return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModuleStub::createOutputStream(
- const SourceMetadata& sourceMetadata, StreamContext&& context,
+ StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
- return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
+ return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
offloadInfo);
}
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index 2dcf4d4..e916fea 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -31,8 +31,8 @@
namespace aidl::android::hardware::audio::core {
-StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context)
- : StreamCommonImpl(metadata, std::move(context)),
+StreamStub::StreamStub(const StreamContext& context, const Metadata& metadata)
+ : StreamCommonImpl(context, metadata),
mFrameSizeBytes(getContext().getFrameSize()),
mSampleRate(getContext().getSampleRate()),
mIsAsynchronous(!!getContext().getAsyncCallback()),
@@ -118,12 +118,12 @@
mIsInitialized = false;
}
-StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
+StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {}
+ : StreamIn(std::move(context), microphones), StreamStub(StreamIn::mContext, sinkMetadata) {}
-StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context,
+StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamStub(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
+ : StreamOut(std::move(context), offloadInfo), StreamStub(StreamOut::mContext, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index a812e4d..f926e09 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -68,22 +68,22 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-ndk::ScopedAStatus ModuleUsb::createInputStream(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
+ndk::ScopedAStatus ModuleUsb::createInputStream(StreamContext&& context,
+ const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
- return createStreamInstance<StreamInUsb>(result, sinkMetadata, std::move(context), microphones);
+ return createStreamInstance<StreamInUsb>(result, std::move(context), sinkMetadata, microphones);
}
-ndk::ScopedAStatus ModuleUsb::createOutputStream(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
+ndk::ScopedAStatus ModuleUsb::createOutputStream(StreamContext&& context,
+ const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo,
std::shared_ptr<StreamOut>* result) {
if (offloadInfo.has_value()) {
LOG(ERROR) << __func__ << ": offload is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return createStreamInstance<StreamOutUsb>(result, sourceMetadata, std::move(context),
+ return createStreamInstance<StreamOutUsb>(result, std::move(context), sourceMetadata,
offloadInfo);
}
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index da0ad11..def12e0 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -35,8 +35,8 @@
namespace aidl::android::hardware::audio::core {
-StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context)
- : StreamAlsa(metadata, std::move(context)) {}
+StreamUsb::StreamUsb(const StreamContext& context, const Metadata& metadata)
+ : StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {}
ndk::ScopedAStatus StreamUsb::setConnectedDevices(
const std::vector<AudioDevice>& connectedDevices) {
@@ -55,28 +55,13 @@
}
connectedDeviceProfiles.push_back(*profile);
}
- RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
+ RETURN_STATUS_IF_ERROR(setConnectedDevices(connectedDevices));
std::lock_guard guard(mLock);
mConnectedDeviceProfiles = std::move(connectedDeviceProfiles);
mConnectedDevicesUpdated.store(true, std::memory_order_release);
return ndk::ScopedAStatus::ok();
}
-::android::status_t StreamUsb::drain(StreamDescriptor::DrainMode) {
- usleep(1000);
- return ::android::OK;
-}
-
-::android::status_t StreamUsb::flush() {
- usleep(1000);
- return ::android::OK;
-}
-
-::android::status_t StreamUsb::pause() {
- usleep(1000);
- return ::android::OK;
-}
-
::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) {
if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) {
@@ -98,9 +83,9 @@
return connectedDevices;
}
-StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
+StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamUsb(sinkMetadata, std::move(context)), StreamIn(microphones) {}
+ : StreamIn(std::move(context), microphones), StreamUsb(StreamIn::mContext, sinkMetadata) {}
ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -108,10 +93,10 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
+StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamUsb(sourceMetadata, std::move(context)),
- StreamOut(offloadInfo),
+ : StreamOut(std::move(context), offloadInfo),
+ StreamUsb(StreamOut::mContext, sourceMetadata),
mChannelCount(getChannelCount(getContext().getChannelLayout())) {}
ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
diff --git a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
index 769d739..0a49446 100644
--- a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
+++ b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
@@ -33,12 +33,10 @@
bool connected) {
LOG(DEBUG) << __func__ << ": card=" << card << ", connected=" << connected;
if (connected) {
- struct mixer* mixer = mixer_open(card);
- if (mixer == nullptr) {
- PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
+ auto alsaMixer = std::make_shared<alsa::Mixer>(card);
+ if (!alsaMixer->isValid()) {
return;
}
- auto alsaMixer = std::make_shared<alsa::Mixer>(mixer);
alsaMixer->setMasterMute(masterMuted);
alsaMixer->setMasterVolume(masterVolume);
const std::lock_guard guard(mLock);
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 9757287..9f9ca96 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -258,7 +258,7 @@
cb->onAuthenticationFailed();
mLockoutTracker.addFailedAttempt();
checkSensorLockout(cb);
- return true;
+ return false;
}
}
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index e7e8a47..bc235a6 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -269,6 +269,7 @@
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
ASSERT_TRUE(mCallback->mAuthenticateFailed);
+ ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index c0c475a..4d097c1 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -421,20 +421,26 @@
return ScopedAStatus::ok();
}
-ScopedAStatus BroadcastRadio::isConfigFlagSet(ConfigFlag flag, [[maybe_unused]] bool* returnIsSet) {
+ScopedAStatus BroadcastRadio::isConfigFlagSet(ConfigFlag flag, bool* returnIsSet) {
LOG(DEBUG) << __func__ << ": flag = " << toString(flag);
- LOG(INFO) << __func__ << ": getting ConfigFlag is not supported";
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- resultToInt(Result::NOT_SUPPORTED), "getting ConfigFlag is not supported");
+ int flagBit = static_cast<int>(flag);
+ lock_guard<mutex> lk(mMutex);
+ *returnIsSet = ((mConfigFlagValues >> flagBit) & 1) == 1;
+ return ScopedAStatus::ok();
}
ScopedAStatus BroadcastRadio::setConfigFlag(ConfigFlag flag, bool value) {
LOG(DEBUG) << __func__ << ": flag = " << toString(flag) << ", value = " << value;
- LOG(INFO) << __func__ << ": setting ConfigFlag is not supported";
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- resultToInt(Result::NOT_SUPPORTED), "setting ConfigFlag is not supported");
+ int flagBitMask = 1 << (static_cast<int>(flag));
+ lock_guard<mutex> lk(mMutex);
+ if (value) {
+ mConfigFlagValues |= flagBitMask;
+ } else {
+ mConfigFlagValues &= ~flagBitMask;
+ }
+ return ScopedAStatus::ok();
}
ScopedAStatus BroadcastRadio::setParameters(
diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h
index 1c85ddc..092776f 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -75,6 +75,9 @@
ProgramSelector mCurrentProgram GUARDED_BY(mMutex) = {};
std::shared_ptr<ITunerCallback> mCallback GUARDED_BY(mMutex);
+ // Bitmap for all ConfigFlag values
+ int mConfigFlagValues GUARDED_BY(mMutex) = 0;
+
std::optional<AmFmBandRange> getAmFmRangeLocked() const;
void cancelLocked();
ProgramInfo tuneInternalLocked(const ProgramSelector& sel);
diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
index 8bee1b2..790d60b 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -997,13 +997,12 @@
LOG(DEBUG) << "SetConfigFlags Test";
auto get = [&](ConfigFlag flag) -> bool {
- bool* gotValue = nullptr;
+ bool gotValue;
- auto halResult = mModule->isConfigFlagSet(flag, gotValue);
+ auto halResult = mModule->isConfigFlagSet(flag, &gotValue);
- EXPECT_FALSE(gotValue == nullptr);
EXPECT_TRUE(halResult.isOk());
- return *gotValue;
+ return gotValue;
};
auto notSupportedError = resultToInt(Result::NOT_SUPPORTED);
diff --git a/camera/device/default/Android.bp b/camera/device/default/Android.bp
index b577597..b9f10d6 100644
--- a/camera/device/default/Android.bp
+++ b/camera/device/default/Android.bp
@@ -25,7 +25,10 @@
cc_library_shared {
name: "camera.device-external-impl",
- defaults: ["hidl_defaults"],
+ defaults: [
+ "android.hardware.graphics.common-ndk_shared",
+ "hidl_defaults",
+ ],
proprietary: true,
srcs: [
"ExternalCameraDevice.cpp",
@@ -38,7 +41,6 @@
"android.hardware.camera.common-V1-ndk",
"android.hardware.camera.device-V1-ndk",
"android.hardware.graphics.allocator-V1-ndk",
- "android.hardware.graphics.common-V4-ndk",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
old mode 100755
new mode 100644
index 3c16d57..6ce5681
--- a/cas/aidl/default/Android.bp
+++ b/cas/aidl/default/Android.bp
@@ -68,6 +68,7 @@
defaults: ["cas_service_example_defaults"],
init_rc: ["cas-default-lazy.rc"],
cflags: ["-DLAZY_SERVICE"],
+ overrides: ["android.hardware.cas-service.example"],
}
cc_fuzz {
diff --git a/cas/aidl/default/CasImpl.cpp b/cas/aidl/default/CasImpl.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/CasImpl.h b/cas/aidl/default/CasImpl.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/DescramblerImpl.cpp b/cas/aidl/default/DescramblerImpl.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/DescramblerImpl.h b/cas/aidl/default/DescramblerImpl.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/FactoryLoader.h b/cas/aidl/default/FactoryLoader.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/MediaCasService.cpp b/cas/aidl/default/MediaCasService.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/MediaCasService.h b/cas/aidl/default/MediaCasService.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/SharedLibrary.cpp b/cas/aidl/default/SharedLibrary.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/SharedLibrary.h b/cas/aidl/default/SharedLibrary.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/TypeConvert.cpp b/cas/aidl/default/TypeConvert.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/TypeConvert.h b/cas/aidl/default/TypeConvert.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/android.hardware.cas-service.xml b/cas/aidl/default/android.hardware.cas-service.xml
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/cas-default-lazy.rc b/cas/aidl/default/cas-default-lazy.rc
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/cas-default.rc b/cas/aidl/default/cas-default.rc
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/fuzzer.cpp b/cas/aidl/default/fuzzer.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/service.cpp b/cas/aidl/default/service.cpp
old mode 100755
new mode 100644
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index 204b83b..bb7637a 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -281,9 +281,15 @@
<version>1.0</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index bbf7055..dad1558 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -319,11 +319,21 @@
<version>1.0-1</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
<version>1.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml
index 1b812ed..23f634d 100644
--- a/compatibility_matrices/compatibility_matrix.6.xml
+++ b/compatibility_matrices/compatibility_matrix.6.xml
@@ -368,11 +368,21 @@
<version>1.0-2</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
<version>1.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.7.xml b/compatibility_matrices/compatibility_matrix.7.xml
index 4419796..33c3148 100644
--- a/compatibility_matrices/compatibility_matrix.7.xml
+++ b/compatibility_matrices/compatibility_matrix.7.xml
@@ -430,11 +430,21 @@
<version>1.0-2</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
<version>1.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 4aa832b..04a4674 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -361,10 +361,20 @@
<version>1.0-2</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
+ </hal>
<hal format="aidl" optional="true">
<name>android.hardware.memtrack</name>
<version>1</version>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 559e7c2..5bcb349 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -257,9 +257,6 @@
<!-- Either the native or the HIDL mapper HAL must exist on the device -->
<hal format="hidl" optional="true">
<name>android.hardware.graphics.mapper</name>
- <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
- <version>2.1</version>
- <version>3.0</version>
<version>4.0</version>
<interface>
<name>IMapper</name>
@@ -352,10 +349,20 @@
<version>1.0-2</version>
<interface>
<name>IComponentStore</name>
+ <instance>software</instance>
<regex-instance>default[0-9]*</regex-instance>
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfigurable</name>
+ <instance>default</instance>
+ <instance>software</instance>
+ </interface>
+ </hal>
<hal format="aidl" optional="true">
<name>android.hardware.media.c2</name>
<version>1</version>
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
index ea54a89..0bd72a3 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
@@ -39,14 +39,12 @@
/**
* The stage in which dimming operations should be performed when compositing
* the client target.
+ *
* Note that with a COLORIMETRIC RenderIntent, DimmingSpace must be LINEAR. That is, dimming
- * is defined to occur in linear space.
- * However, some composer implementations may, with other vendor-defined RenderIntents,
- * configure their hardware such as image quality adjustments is intended to occur after
- * composition. In this scenario, if the dimming operation were applied in linear space,
- * then the resulting dimming operation may comepl those image quality adjustments to
- * incorrectly alter the gamma curve. To avoid this issue, those implementations must opt to
- * dim in gamma space.
+ * is defined to occur in linear space. However, some composer implementations may, with
+ * other vendor-defined RenderIntents, apply certain image quality adjustments that are
+ * sensitive to gamma shift when dimming in linear space. To avoid this issue, those
+ * implementations must opt to dim in gamma space.
*/
DimmingStage dimmingStage;
}
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index b047220..269abd1 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -129,33 +129,20 @@
return {false, graphicBuffer};
}
- uint64_t getStableDisplayId(int64_t display) {
- const auto& [status, identification] =
- mComposerClient->getDisplayIdentificationData(display);
- EXPECT_TRUE(status.isOk());
-
- if (const auto info = ::android::parseDisplayIdentificationData(
- static_cast<uint8_t>(identification.port), identification.data)) {
- return info->id.value;
- }
-
- return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
- .value;
- }
-
// Gets the per-display XML config
std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXml(int64_t display) {
- std::stringstream pathBuilder;
- pathBuilder << "/vendor/etc/displayconfig/display_id_" << getStableDisplayId(display)
- << ".xml";
- const std::string path = pathBuilder.str();
- auto document = std::make_unique<tinyxml2::XMLDocument>();
- const tinyxml2::XMLError error = document->LoadFile(path.c_str());
- if (error == tinyxml2::XML_SUCCESS) {
+
+ if (auto document = getDisplayConfigXmlByStableId(getStableDisplayId(display));
+ document != nullptr) {
return document;
- } else {
- return nullptr;
}
+
+ // Fallback to looking up a per-port config if no config exists for the full ID
+ if (auto document = getDisplayConfigXmlByPort(getPort(display)); document != nullptr) {
+ return document;
+ }
+
+ return nullptr;
}
// Gets the max display brightness for this display.
@@ -256,6 +243,53 @@
}
}
}
+
+ uint8_t getPort(int64_t display) {
+ const auto& [status, identification] =
+ mComposerClient->getDisplayIdentificationData(display);
+ EXPECT_TRUE(status.isOk());
+ return static_cast<uint8_t>(identification.port);
+ }
+
+ uint64_t getStableDisplayId(int64_t display) {
+ const auto& [status, identification] =
+ mComposerClient->getDisplayIdentificationData(display);
+ EXPECT_TRUE(status.isOk());
+
+ if (const auto info = ::android::parseDisplayIdentificationData(
+ static_cast<uint8_t>(identification.port), identification.data)) {
+ return info->id.value;
+ }
+
+ return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
+ .value;
+ }
+
+ std::unique_ptr<tinyxml2::XMLDocument> loadXml(const std::string& path) {
+ auto document = std::make_unique<tinyxml2::XMLDocument>();
+ const tinyxml2::XMLError error = document->LoadFile(path.c_str());
+ if (error != tinyxml2::XML_SUCCESS) {
+ ALOGD("%s: Failed to load config file: %s", __func__, path.c_str());
+ return nullptr;
+ }
+
+ ALOGD("%s: Successfully loaded config file: %s", __func__, path.c_str());
+ return document;
+ }
+
+ std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXmlByPort(uint8_t port) {
+ std::stringstream pathBuilder;
+ pathBuilder << "/vendor/etc/displayconfig/display_port_" << static_cast<uint32_t>(port)
+ << ".xml";
+ return loadXml(pathBuilder.str());
+ }
+
+ std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXmlByStableId(uint64_t stableId) {
+ std::stringstream pathBuilder;
+ pathBuilder << "/vendor/etc/displayconfig/display_id_" << stableId
+ << ".xml";
+ return loadXml(pathBuilder.str());
+ }
};
class GraphicsCompositionTest : public GraphicsCompositionTestBase,
diff --git a/security/rkp/README.md b/security/rkp/README.md
index f8e1d5e..8cd1582 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -52,7 +52,7 @@
* Degenerate DICE (Phase 1): A TEE root of trust key pair is used to sign
certificate requests; a single self-signed certificate signifies this phase.
* DICE (Phase 2): A hardware root of trust key pair is only accessible to ROM
- code; the boot process follows the [Android Profile for
+ or ROM extension code; the boot process follows the [Android Profile for
DICE](#android-profile-for-dice).
* SoC vendor certified DICE (Phase 3): This is identical to Phase 2, except the
SoC vendor also does the UDS\_pub extraction or certification in their
diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp
deleted file mode 100644
index cc1d284..0000000
--- a/weaver/1.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// 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.
-//
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_test {
- name: "VtsHalWeaverV1_0TargetTest",
- defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalWeaverV1_0TargetTest.cpp"],
- static_libs: ["android.hardware.weaver@1.0"],
- test_suites: ["general-tests", "vts"],
-}
diff --git a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp b/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
deleted file mode 100644
index 66465a9..0000000
--- a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * 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.
- */
-
-#include <android/hardware/weaver/1.0/IWeaver.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-#include <limits>
-
-using ::android::hardware::weaver::V1_0::IWeaver;
-using ::android::hardware::weaver::V1_0::WeaverConfig;
-using ::android::hardware::weaver::V1_0::WeaverReadStatus;
-using ::android::hardware::weaver::V1_0::WeaverReadResponse;
-using ::android::hardware::weaver::V1_0::WeaverStatus;
-using ::android::hardware::Return;
-using ::android::sp;
-
-const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
-const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
-
-struct WeaverHidlTest : public ::testing::TestWithParam<std::string> {
- virtual void SetUp() override {
- weaver = IWeaver::getService(GetParam());
- ASSERT_NE(weaver, nullptr);
- }
-
- virtual void TearDown() override {}
-
- sp<IWeaver> weaver;
-};
-
-/*
- * Checks config values are suitably large
- */
-TEST_P(WeaverHidlTest, GetConfig) {
- WeaverStatus status;
- WeaverConfig config;
-
- bool callbackCalled = false;
- auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- callbackCalled = true;
- status = s;
- config = c;
- });
- ASSERT_TRUE(ret.isOk());
- ASSERT_TRUE(callbackCalled);
- ASSERT_EQ(status, WeaverStatus::OK);
-
- EXPECT_GE(config.slots, 16u);
- EXPECT_GE(config.keySize, 16u);
- EXPECT_GE(config.valueSize, 16u);
-}
-
-/*
- * Gets the config twice and checks they are the same
- */
-TEST_P(WeaverHidlTest, GettingConfigMultipleTimesGivesSameResult) {
- WeaverConfig config1;
- WeaverConfig config2;
-
- WeaverStatus status;
- bool callbackCalled = false;
- auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- callbackCalled = true;
- status = s;
- config1 = c;
- });
- ASSERT_TRUE(ret.isOk());
- ASSERT_TRUE(callbackCalled);
- ASSERT_EQ(status, WeaverStatus::OK);
-
- callbackCalled = false;
- ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- callbackCalled = true;
- status = s;
- config2 = c;
- });
- ASSERT_TRUE(ret.isOk());
- ASSERT_TRUE(callbackCalled);
- ASSERT_EQ(status, WeaverStatus::OK);
-
- EXPECT_EQ(config1, config2);
-}
-
-/*
- * Gets the number of slots from the config and writes a key and value to the last one
- */
-TEST_P(WeaverHidlTest, WriteToLastSlot) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- const uint32_t lastSlot = config.slots - 1;
- const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
- ASSERT_TRUE(writeRet.isOk());
- ASSERT_EQ(writeRet, WeaverStatus::OK);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with the same key and receives the value that was previously written
- */
-TEST_P(WeaverHidlTest, WriteFollowedByReadGivesTheSameValue) {
- constexpr uint32_t slotId = 0;
- const auto ret = weaver->write(slotId, KEY, VALUE);
- ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(ret, WeaverStatus::OK);
-
- bool callbackCalled = false;
- WeaverReadStatus status;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- status = s;
- readValue = r.value;
- timeout = r.timeout;
- });
- ASSERT_TRUE(readRet.isOk());
- ASSERT_TRUE(callbackCalled);
- ASSERT_EQ(status, WeaverReadStatus::OK);
- EXPECT_EQ(readValue, VALUE);
- EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Overwrites the slot with a new key and value
- * Reads the slot with the new key and receives the new value
- */
-TEST_P(WeaverHidlTest, OverwritingSlotUpdatesTheValue) {
- constexpr uint32_t slotId = 0;
- const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
- ASSERT_TRUE(initialWriteRet.isOk());
- ASSERT_EQ(initialWriteRet, WeaverStatus::OK);
-
- const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
- ASSERT_TRUE(overwriteRet.isOk());
- ASSERT_EQ(overwriteRet, WeaverStatus::OK);
-
- bool callbackCalled = false;
- WeaverReadStatus status;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- status = s;
- readValue = r.value;
- timeout = r.timeout;
- });
- ASSERT_TRUE(readRet.isOk());
- ASSERT_TRUE(callbackCalled);
- ASSERT_EQ(status, WeaverReadStatus::OK);
- EXPECT_EQ(readValue, OTHER_VALUE);
- EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with a different key so does not receive the value
- */
-TEST_P(WeaverHidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
- constexpr uint32_t slotId = 0;
- const auto ret = weaver->write(slotId, KEY, VALUE);
- ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(ret, WeaverStatus::OK);
-
- bool callbackCalled = false;
- WeaverReadStatus status;
- std::vector<uint8_t> readValue;
- const auto readRet =
- weaver->read(slotId, WRONG_KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- status = s;
- readValue = r.value;
- });
- ASSERT_TRUE(callbackCalled);
- ASSERT_TRUE(readRet.isOk());
- ASSERT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
- EXPECT_TRUE(readValue.empty());
-}
-
-/*
- * Writing to an invalid slot fails
- */
-TEST_P(WeaverHidlTest, WritingToInvalidSlotFails) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- if (config.slots == std::numeric_limits<uint32_t>::max()) {
- // If there are no invalid slots then pass
- return;
- }
-
- const auto writeRet = weaver->write(config.slots, KEY, VALUE);
- ASSERT_TRUE(writeRet.isOk());
- ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Reading from an invalid slot fails rather than incorrect key
- */
-TEST_P(WeaverHidlTest, ReadingFromInvalidSlotFails) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- if (config.slots == std::numeric_limits<uint32_t>::max()) {
- // If there are no invalid slots then pass
- return;
- }
-
- bool callbackCalled = false;
- WeaverReadStatus readStatus;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- const auto readRet =
- weaver->read(config.slots, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- readStatus = s;
- readValue = r.value;
- timeout = r.timeout;
- });
- ASSERT_TRUE(callbackCalled);
- ASSERT_TRUE(readRet.isOk());
- ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
- EXPECT_TRUE(readValue.empty());
- EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writing a key that is too large fails
- */
-TEST_P(WeaverHidlTest, WriteWithTooLargeKeyFails) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- std::vector<uint8_t> bigKey(config.keySize + 1);
-
- constexpr uint32_t slotId = 0;
- const auto writeRet = weaver->write(slotId, bigKey, VALUE);
- ASSERT_TRUE(writeRet.isOk());
- ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Writing a value that is too large fails
- */
-TEST_P(WeaverHidlTest, WriteWithTooLargeValueFails) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- std::vector<uint8_t> bigValue(config.valueSize + 1);
-
- constexpr uint32_t slotId = 0;
- const auto writeRet = weaver->write(slotId, KEY, bigValue);
- ASSERT_TRUE(writeRet.isOk());
- ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Reading with a key that is loo large fails
- */
-TEST_P(WeaverHidlTest, ReadWithTooLargeKeyFails) {
- WeaverStatus status;
- WeaverConfig config;
- const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
- status = s;
- config = c;
- });
- ASSERT_TRUE(configRet.isOk());
- ASSERT_EQ(status, WeaverStatus::OK);
-
- std::vector<uint8_t> bigKey(config.keySize + 1);
-
- constexpr uint32_t slotId = 0;
- bool callbackCalled = false;
- WeaverReadStatus readStatus;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- const auto readRet =
- weaver->read(slotId, bigKey, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- readStatus = s;
- readValue = r.value;
- timeout = r.timeout;
- });
- ASSERT_TRUE(callbackCalled);
- ASSERT_TRUE(readRet.isOk());
- ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
- EXPECT_TRUE(readValue.empty());
- EXPECT_EQ(timeout, 0u);
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverHidlTest);
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, WeaverHidlTest,
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IWeaver::descriptor)),
- android::hardware::PrintInstanceNameToString);
diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
deleted file mode 100644
index f016515..0000000
--- a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <aidl/Gtest.h>
-#include <aidl/Vintf.h>
-
-#include <aidl/android/hardware/weaver/IWeaver.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-#include <limits>
-
-using ::aidl::android::hardware::weaver::IWeaver;
-using ::aidl::android::hardware::weaver::WeaverConfig;
-using ::aidl::android::hardware::weaver::WeaverReadResponse;
-using ::aidl::android::hardware::weaver::WeaverReadStatus;
-
-using ::ndk::SpAIBinder;
-
-const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
-const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
-
-struct WeaverAidlTest : public ::testing::TestWithParam<std::string> {
- virtual void SetUp() override {
- weaver = IWeaver::fromBinder(
- SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
- ASSERT_NE(weaver, nullptr);
- }
-
- virtual void TearDown() override {}
-
- std::shared_ptr<IWeaver> weaver;
-};
-
-/*
- * Checks config values are suitably large
- */
-TEST_P(WeaverAidlTest, GetConfig) {
- WeaverConfig config;
-
- auto ret = weaver->getConfig(&config);
-
- ASSERT_TRUE(ret.isOk());
-
- EXPECT_GE(config.slots, 16u);
- EXPECT_GE(config.keySize, 16u);
- EXPECT_GE(config.valueSize, 16u);
-}
-
-/*
- * Gets the config twice and checks they are the same
- */
-TEST_P(WeaverAidlTest, GettingConfigMultipleTimesGivesSameResult) {
- WeaverConfig config1;
- WeaverConfig config2;
-
- auto ret = weaver->getConfig(&config1);
- ASSERT_TRUE(ret.isOk());
-
- ret = weaver->getConfig(&config2);
- ASSERT_TRUE(ret.isOk());
-
- EXPECT_EQ(config1, config2);
-}
-
-/*
- * Gets the number of slots from the config and writes a key and value to the last one
- */
-TEST_P(WeaverAidlTest, WriteToLastSlot) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
-
- ASSERT_TRUE(configRet.isOk());
-
- const uint32_t lastSlot = config.slots - 1;
- const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
- ASSERT_TRUE(writeRet.isOk());
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with the same key and receives the value that was previously written
- */
-TEST_P(WeaverAidlTest, WriteFollowedByReadGivesTheSameValue) {
- constexpr uint32_t slotId = 0;
- const auto ret = weaver->write(slotId, KEY, VALUE);
- ASSERT_TRUE(ret.isOk());
-
- WeaverReadResponse response;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- WeaverReadStatus status;
- const auto readRet = weaver->read(slotId, KEY, &response);
-
- readValue = response.value;
- timeout = response.timeout;
- status = response.status;
-
- ASSERT_TRUE(readRet.isOk());
- EXPECT_EQ(readValue, VALUE);
- EXPECT_EQ(timeout, 0u);
- EXPECT_EQ(status, WeaverReadStatus::OK);
-}
-
-/*
- * Writes a key and value to a slot
- * Overwrites the slot with a new key and value
- * Reads the slot with the new key and receives the new value
- */
-TEST_P(WeaverAidlTest, OverwritingSlotUpdatesTheValue) {
- constexpr uint32_t slotId = 0;
- const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
- ASSERT_TRUE(initialWriteRet.isOk());
-
- const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
- ASSERT_TRUE(overwriteRet.isOk());
-
- WeaverReadResponse response;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- WeaverReadStatus status;
- const auto readRet = weaver->read(slotId, KEY, &response);
-
- readValue = response.value;
- timeout = response.timeout;
- status = response.status;
-
- ASSERT_TRUE(readRet.isOk());
- EXPECT_EQ(readValue, OTHER_VALUE);
- EXPECT_EQ(timeout, 0u);
- EXPECT_EQ(status, WeaverReadStatus::OK);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with a different key so does not receive the value
- */
-TEST_P(WeaverAidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
- constexpr uint32_t slotId = 0;
- const auto ret = weaver->write(slotId, KEY, VALUE);
- ASSERT_TRUE(ret.isOk());
-
- WeaverReadResponse response;
- std::vector<uint8_t> readValue;
- WeaverReadStatus status;
- const auto readRet =
- weaver->read(slotId, WRONG_KEY, &response);
-
- readValue = response.value;
- status = response.status;
-
- ASSERT_TRUE(readRet.isOk());
- EXPECT_TRUE(readValue.empty());
- EXPECT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
-}
-
-/*
- * Writing to an invalid slot fails
- */
-TEST_P(WeaverAidlTest, WritingToInvalidSlotFails) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
- ASSERT_TRUE(configRet.isOk());
-
- if (config.slots == std::numeric_limits<uint32_t>::max()) {
- // If there are no invalid slots then pass
- return;
- }
-
- const auto writeRet = weaver->write(config.slots, KEY, VALUE);
- ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Reading from an invalid slot fails rather than incorrect key
- */
-TEST_P(WeaverAidlTest, ReadingFromInvalidSlotFails) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
- ASSERT_TRUE(configRet.isOk());
-
- if (config.slots == std::numeric_limits<uint32_t>::max()) {
- // If there are no invalid slots then pass
- return;
- }
-
- WeaverReadResponse response;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- WeaverReadStatus status;
- const auto readRet =
- weaver->read(config.slots, KEY, &response);
-
- readValue = response.value;
- timeout = response.timeout;
- status = response.status;
-
- ASSERT_TRUE(readRet.isOk());
- EXPECT_TRUE(readValue.empty());
- EXPECT_EQ(timeout, 0u);
- EXPECT_EQ(status, WeaverReadStatus::FAILED);
-}
-
-/*
- * Writing a key that is too large fails
- */
-TEST_P(WeaverAidlTest, WriteWithTooLargeKeyFails) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
- ASSERT_TRUE(configRet.isOk());
-
- std::vector<uint8_t> bigKey(config.keySize + 1);
-
- constexpr uint32_t slotId = 0;
- const auto writeRet = weaver->write(slotId, bigKey, VALUE);
- ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Writing a value that is too large fails
- */
-TEST_P(WeaverAidlTest, WriteWithTooLargeValueFails) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
- ASSERT_TRUE(configRet.isOk());
-
- std::vector<uint8_t> bigValue(config.valueSize + 1);
-
- constexpr uint32_t slotId = 0;
- const auto writeRet = weaver->write(slotId, KEY, bigValue);
- ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Reading with a key that is loo large fails
- */
-TEST_P(WeaverAidlTest, ReadWithTooLargeKeyFails) {
- WeaverConfig config;
- const auto configRet = weaver->getConfig(&config);
- ASSERT_TRUE(configRet.isOk());
-
- std::vector<uint8_t> bigKey(config.keySize + 1);
-
- constexpr uint32_t slotId = 0;
- WeaverReadResponse response;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- WeaverReadStatus status;
- const auto readRet =
- weaver->read(slotId, bigKey, &response);
-
- readValue = response.value;
- timeout = response.timeout;
- status = response.status;
-
- ASSERT_TRUE(readRet.isOk());
- EXPECT_TRUE(readValue.empty());
- EXPECT_EQ(timeout, 0u);
- EXPECT_EQ(status, WeaverReadStatus::FAILED);
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverAidlTest);
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, WeaverAidlTest,
- testing::ValuesIn(android::getAidlHalInstanceNames(IWeaver::descriptor)),
- android::PrintInstanceNameToString);
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- ABinderProcess_setThreadPoolMaxThreadCount(1);
- ABinderProcess_startThreadPool();
- return RUN_ALL_TESTS();
-}
diff --git a/weaver/aidl/vts/Android.bp b/weaver/vts/Android.bp
similarity index 92%
rename from weaver/aidl/vts/Android.bp
rename to weaver/vts/Android.bp
index 557fe47..ee03b28 100644
--- a/weaver/aidl/vts/Android.bp
+++ b/weaver/vts/Android.bp
@@ -34,7 +34,10 @@
"libbinder_ndk",
"libbase",
],
- static_libs: ["android.hardware.weaver-V2-ndk"],
+ static_libs: [
+ "android.hardware.weaver-V2-ndk",
+ "android.hardware.weaver@1.0",
+ ],
test_suites: [
"general-tests",
"vts",
diff --git a/weaver/vts/VtsHalWeaverTargetTest.cpp b/weaver/vts/VtsHalWeaverTargetTest.cpp
new file mode 100644
index 0000000..9ee6d93
--- /dev/null
+++ b/weaver/vts/VtsHalWeaverTargetTest.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/weaver/IWeaver.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/hardware/weaver/1.0/IWeaver.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <limits>
+
+using ::aidl::android::hardware::weaver::IWeaver;
+using ::aidl::android::hardware::weaver::WeaverConfig;
+using ::aidl::android::hardware::weaver::WeaverReadResponse;
+using ::aidl::android::hardware::weaver::WeaverReadStatus;
+
+using HidlIWeaver = ::android::hardware::weaver::V1_0::IWeaver;
+using HidlWeaverConfig = ::android::hardware::weaver::V1_0::WeaverConfig;
+using HidlWeaverReadStatus = ::android::hardware::weaver::V1_0::WeaverReadStatus;
+using HidlWeaverReadResponse = ::android::hardware::weaver::V1_0::WeaverReadResponse;
+using HidlWeaverStatus = ::android::hardware::weaver::V1_0::WeaverStatus;
+
+const std::string kSlotMapFile = "/metadata/password_slots/slot_map";
+const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
+
+class WeaverAdapter {
+ public:
+ virtual ~WeaverAdapter() {}
+ virtual bool isReady() = 0;
+ virtual ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) = 0;
+ virtual ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ WeaverReadResponse* _aidl_return) = 0;
+ virtual ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ const std::vector<uint8_t>& in_value) = 0;
+};
+
+class WeaverAidlAdapter : public WeaverAdapter {
+ public:
+ WeaverAidlAdapter(const std::string& param)
+ : aidl_weaver_(IWeaver::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_waitForService(param.c_str())))) {}
+ ~WeaverAidlAdapter() {}
+
+ bool isReady() { return aidl_weaver_ != nullptr; }
+
+ ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) {
+ return aidl_weaver_->getConfig(_aidl_return);
+ }
+
+ ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ WeaverReadResponse* _aidl_return) {
+ return aidl_weaver_->read(in_slotId, in_key, _aidl_return);
+ }
+
+ ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ const std::vector<uint8_t>& in_value) {
+ return aidl_weaver_->write(in_slotId, in_key, in_value);
+ }
+
+ private:
+ std::shared_ptr<IWeaver> aidl_weaver_;
+};
+
+class WeaverHidlAdapter : public WeaverAdapter {
+ public:
+ WeaverHidlAdapter(const std::string& param) : hidl_weaver_(HidlIWeaver::getService(param)) {}
+ ~WeaverHidlAdapter() {}
+
+ bool isReady() { return hidl_weaver_ != nullptr; }
+
+ ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) {
+ bool callbackCalled = false;
+ HidlWeaverStatus status;
+ HidlWeaverConfig config;
+ auto ret = hidl_weaver_->getConfig([&](HidlWeaverStatus s, HidlWeaverConfig c) {
+ callbackCalled = true;
+ status = s;
+ config = c;
+ });
+ if (!ret.isOk() || !callbackCalled || status != HidlWeaverStatus::OK) {
+ return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+ }
+ _aidl_return->slots = config.slots;
+ _aidl_return->keySize = config.keySize;
+ _aidl_return->valueSize = config.valueSize;
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ WeaverReadResponse* _aidl_return) {
+ bool callbackCalled = false;
+ HidlWeaverReadStatus status;
+ std::vector<uint8_t> value;
+ uint32_t timeout;
+ auto ret = hidl_weaver_->read(in_slotId, in_key,
+ [&](HidlWeaverReadStatus s, HidlWeaverReadResponse r) {
+ callbackCalled = true;
+ status = s;
+ value = r.value;
+ timeout = r.timeout;
+ });
+ if (!ret.isOk() || !callbackCalled) {
+ return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+ }
+ switch (status) {
+ case HidlWeaverReadStatus::OK:
+ _aidl_return->status = WeaverReadStatus::OK;
+ break;
+ case HidlWeaverReadStatus::FAILED:
+ _aidl_return->status = WeaverReadStatus::FAILED;
+ break;
+ case HidlWeaverReadStatus::INCORRECT_KEY:
+ _aidl_return->status = WeaverReadStatus::INCORRECT_KEY;
+ break;
+ case HidlWeaverReadStatus::THROTTLE:
+ _aidl_return->status = WeaverReadStatus::THROTTLE;
+ break;
+ default:
+ ADD_FAILURE() << "Unknown HIDL read status: " << static_cast<uint32_t>(status);
+ _aidl_return->status = WeaverReadStatus::FAILED;
+ break;
+ }
+ _aidl_return->value = value;
+ _aidl_return->timeout = timeout;
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+ const std::vector<uint8_t>& in_value) {
+ auto status = hidl_weaver_->write(in_slotId, in_key, in_value);
+ switch (status) {
+ case HidlWeaverStatus::OK:
+ return ::ndk::ScopedAStatus::ok();
+ case HidlWeaverStatus::FAILED:
+ return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+ default:
+ ADD_FAILURE() << "Unknown HIDL write status: " << status.description();
+ return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+ }
+ }
+
+ private:
+ android::sp<HidlIWeaver> hidl_weaver_;
+};
+
+class WeaverTest : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+ protected:
+ void SetUp() override;
+ void TearDown() override {}
+ void FindFreeSlots();
+
+ std::unique_ptr<WeaverAdapter> weaver_;
+ WeaverConfig config_;
+ uint32_t first_free_slot_;
+ uint32_t last_free_slot_;
+};
+
+void WeaverTest::SetUp() {
+ std::string api, instance_name;
+ std::tie(api, instance_name) = GetParam();
+ if (api == "hidl") {
+ weaver_.reset(new WeaverHidlAdapter(instance_name));
+ } else if (api == "aidl") {
+ weaver_.reset(new WeaverAidlAdapter(instance_name));
+ } else {
+ FAIL() << "Bad test parameterization";
+ }
+ ASSERT_TRUE(weaver_->isReady());
+
+ auto ret = weaver_->getConfig(&config_);
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_GT(config_.slots, 0);
+ GTEST_LOG_(INFO) << "WeaverConfig: slots=" << config_.slots << ", keySize=" << config_.keySize
+ << ", valueSize=" << config_.valueSize;
+
+ FindFreeSlots();
+ GTEST_LOG_(INFO) << "First free slot is " << first_free_slot_ << ", last free slot is "
+ << last_free_slot_;
+}
+
+void WeaverTest::FindFreeSlots() {
+ // Determine which Weaver slots are in use by the system. These slots can't be used by the test.
+ std::set<uint32_t> used_slots;
+ if (access(kSlotMapFile.c_str(), F_OK) == 0) {
+ std::string contents;
+ ASSERT_TRUE(android::base::ReadFileToString(kSlotMapFile, &contents))
+ << "Failed to read " << kSlotMapFile;
+ for (const auto& line : android::base::Split(contents, "\n")) {
+ auto trimmed_line = android::base::Trim(line);
+ if (trimmed_line[0] == '#' || trimmed_line[0] == '\0') continue;
+ auto slot_and_user = android::base::Split(trimmed_line, "=");
+ uint32_t slot;
+ ASSERT_TRUE(slot_and_user.size() == 2 &&
+ android::base::ParseUint(slot_and_user[0], &slot))
+ << "Error parsing " << kSlotMapFile << " at \"" << line << "\"";
+ GTEST_LOG_(INFO) << "Slot " << slot << " is in use by " << slot_and_user[1];
+ ASSERT_LT(slot, config_.slots);
+ used_slots.insert(slot);
+ }
+ }
+ // Starting in Android 14, the system will always use at least one Weaver slot if Weaver is
+ // supported at all. Make sure we saw at least one.
+ // TODO: uncomment after Android 14 is merged into AOSP
+ // ASSERT_FALSE(used_slots.empty())
+ //<< "Could not determine which Weaver slots are in use by the system";
+
+ // Find the first free slot.
+ int found = 0;
+ for (uint32_t i = 0; i < config_.slots; i++) {
+ if (used_slots.find(i) == used_slots.end()) {
+ first_free_slot_ = i;
+ found++;
+ break;
+ }
+ }
+ // Find the last free slot.
+ for (uint32_t i = config_.slots; i > 0; i--) {
+ if (used_slots.find(i - 1) == used_slots.end()) {
+ last_free_slot_ = i - 1;
+ found++;
+ break;
+ }
+ }
+ ASSERT_EQ(found, 2) << "All Weaver slots are already in use by the system";
+}
+
+/*
+ * Checks config values are suitably large
+ */
+TEST_P(WeaverTest, GetConfig) {
+ EXPECT_GE(config_.slots, 16u);
+ EXPECT_GE(config_.keySize, 16u);
+ EXPECT_GE(config_.valueSize, 16u);
+}
+
+/*
+ * Gets the config twice and checks they are the same
+ */
+TEST_P(WeaverTest, GettingConfigMultipleTimesGivesSameResult) {
+ WeaverConfig config2;
+
+ auto ret = weaver_->getConfig(&config2);
+ ASSERT_TRUE(ret.isOk());
+
+ EXPECT_EQ(config_, config2);
+}
+
+/*
+ * Writes a key and value to the last free slot
+ */
+TEST_P(WeaverTest, WriteToLastSlot) {
+ const auto writeRet = weaver_->write(last_free_slot_, KEY, VALUE);
+ ASSERT_TRUE(writeRet.isOk());
+}
+
+/*
+ * Writes a key and value to a slot
+ * Reads the slot with the same key and receives the value that was previously written
+ */
+TEST_P(WeaverTest, WriteFollowedByReadGivesTheSameValue) {
+ const uint32_t slotId = first_free_slot_;
+ const auto ret = weaver_->write(slotId, KEY, VALUE);
+ ASSERT_TRUE(ret.isOk());
+
+ WeaverReadResponse response;
+ const auto readRet = weaver_->read(slotId, KEY, &response);
+ ASSERT_TRUE(readRet.isOk());
+ EXPECT_EQ(response.value, VALUE);
+ EXPECT_EQ(response.timeout, 0u);
+ EXPECT_EQ(response.status, WeaverReadStatus::OK);
+}
+
+/*
+ * Writes a key and value to a slot
+ * Overwrites the slot with a new key and value
+ * Reads the slot with the new key and receives the new value
+ */
+TEST_P(WeaverTest, OverwritingSlotUpdatesTheValue) {
+ const uint32_t slotId = first_free_slot_;
+ const auto initialWriteRet = weaver_->write(slotId, WRONG_KEY, VALUE);
+ ASSERT_TRUE(initialWriteRet.isOk());
+
+ const auto overwriteRet = weaver_->write(slotId, KEY, OTHER_VALUE);
+ ASSERT_TRUE(overwriteRet.isOk());
+
+ WeaverReadResponse response;
+ const auto readRet = weaver_->read(slotId, KEY, &response);
+ ASSERT_TRUE(readRet.isOk());
+ EXPECT_EQ(response.value, OTHER_VALUE);
+ EXPECT_EQ(response.timeout, 0u);
+ EXPECT_EQ(response.status, WeaverReadStatus::OK);
+}
+
+/*
+ * Writes a key and value to a slot
+ * Reads the slot with a different key so does not receive the value
+ */
+TEST_P(WeaverTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
+ const uint32_t slotId = first_free_slot_;
+ const auto writeRet = weaver_->write(slotId, KEY, VALUE);
+ ASSERT_TRUE(writeRet.isOk());
+
+ WeaverReadResponse response;
+ const auto readRet = weaver_->read(slotId, WRONG_KEY, &response);
+ ASSERT_TRUE(readRet.isOk());
+ EXPECT_TRUE(response.value.empty());
+ EXPECT_EQ(response.status, WeaverReadStatus::INCORRECT_KEY);
+}
+
+/*
+ * Writing to an invalid slot fails
+ */
+TEST_P(WeaverTest, WritingToInvalidSlotFails) {
+ if (config_.slots == std::numeric_limits<uint32_t>::max()) {
+ // If there are no invalid slots then pass
+ return;
+ }
+
+ const auto writeRet = weaver_->write(config_.slots, KEY, VALUE);
+ ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Reading from an invalid slot fails rather than incorrect key
+ */
+TEST_P(WeaverTest, ReadingFromInvalidSlotFails) {
+ if (config_.slots == std::numeric_limits<uint32_t>::max()) {
+ // If there are no invalid slots then pass
+ return;
+ }
+
+ WeaverReadResponse response;
+ const auto readRet = weaver_->read(config_.slots, KEY, &response);
+ ASSERT_TRUE(readRet.isOk());
+ EXPECT_TRUE(response.value.empty());
+ EXPECT_EQ(response.timeout, 0u);
+ EXPECT_EQ(response.status, WeaverReadStatus::FAILED);
+}
+
+/*
+ * Writing a key that is too large fails
+ */
+TEST_P(WeaverTest, WriteWithTooLargeKeyFails) {
+ std::vector<uint8_t> bigKey(config_.keySize + 1);
+
+ const auto writeRet = weaver_->write(first_free_slot_, bigKey, VALUE);
+ ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Writing a value that is too large fails
+ */
+TEST_P(WeaverTest, WriteWithTooLargeValueFails) {
+ std::vector<uint8_t> bigValue(config_.valueSize + 1);
+
+ const auto writeRet = weaver_->write(first_free_slot_, KEY, bigValue);
+ ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Reading with a key that is too large fails
+ */
+TEST_P(WeaverTest, ReadWithTooLargeKeyFails) {
+ std::vector<uint8_t> bigKey(config_.keySize + 1);
+
+ WeaverReadResponse response;
+ const auto readRet = weaver_->read(first_free_slot_, bigKey, &response);
+ ASSERT_TRUE(readRet.isOk());
+ EXPECT_TRUE(response.value.empty());
+ EXPECT_EQ(response.timeout, 0u);
+ EXPECT_EQ(response.status, WeaverReadStatus::FAILED);
+}
+
+// Instantiate the test for each HIDL Weaver service.
+INSTANTIATE_TEST_SUITE_P(
+ PerHidlInstance, WeaverTest,
+ testing::Combine(testing::Values("hidl"),
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ HidlIWeaver::descriptor))),
+ [](const testing::TestParamInfo<std::tuple<std::string, std::string>>& info) {
+ return android::hardware::PrintInstanceNameToString(
+ testing::TestParamInfo<std::string>{std::get<1>(info.param), info.index});
+ });
+
+// Instantiate the test for each AIDL Weaver service.
+INSTANTIATE_TEST_SUITE_P(
+ PerAidlInstance, WeaverTest,
+ testing::Combine(testing::Values("aidl"),
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWeaver::descriptor))),
+ [](const testing::TestParamInfo<std::tuple<std::string, std::string>>& info) {
+ // This name_generator makes the instance name be included in the test case names, e.g.
+ // "PerAidlInstance/WeaverTest#GetConfig/0_android_hardware_weaver_IWeaver_default"
+ // instead of "PerAidlInstance/WeaverTest#GetConfig/0".
+ return android::PrintInstanceNameToString(
+ testing::TestParamInfo<std::string>{std::get<1>(info.param), info.index});
+ });
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}