Merge "[Composer-HAL-AIDL] Deprecates getDisplayAttribute" into main
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 19b2397..4e583a4 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -76,6 +76,7 @@
"ModulePrimary.cpp",
"SoundDose.cpp",
"Stream.cpp",
+ "StreamSwitcher.cpp",
"Telephony.cpp",
"alsa/Mixer.cpp",
"alsa/ModuleAlsa.cpp",
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 5478633..b59bd7c 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()) {
@@ -1129,7 +1129,7 @@
if (!mSoundDose) {
mSoundDose = ndk::SharedRefBase::make<sounddose::SoundDose>();
}
- *_aidl_return = mSoundDose.getPtr();
+ *_aidl_return = mSoundDose.getInstance();
LOG(DEBUG) << __func__ << ": returning instance of ISoundDose: " << _aidl_return->get();
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
index cbb6730..29e8126 100644
--- a/audio/aidl/default/ModulePrimary.cpp
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -37,23 +37,24 @@
if (!mTelephony) {
mTelephony = ndk::SharedRefBase::make<Telephony>();
}
- *_aidl_return = mTelephony.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
+ *_aidl_return = mTelephony.getInstance();
+ 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..d2be48c 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);
}
@@ -85,17 +91,18 @@
}
std::string StreamWorkerCommonLogic::init() {
- if (mCommandMQ == nullptr) return "Command MQ is null";
- if (mReplyMQ == nullptr) return "Reply MQ is null";
- if (mDataMQ == nullptr) return "Data MQ is null";
- if (sizeof(DataBufferElement) != mDataMQ->getQuantumSize()) {
- return "Unexpected Data MQ quantum size: " + std::to_string(mDataMQ->getQuantumSize());
+ if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
+ if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
+ StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+ if (dataMQ == nullptr) return "Data MQ is null";
+ if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
+ return "Unexpected Data MQ quantum size: " + std::to_string(dataMQ->getQuantumSize());
}
- mDataBufferSize = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize();
+ mDataBufferSize = dataMQ->getQuantumCount() * dataMQ->getQuantumSize();
mDataBuffer.reset(new (std::nothrow) DataBufferElement[mDataBufferSize]);
if (mDataBuffer == nullptr) {
return "Failed to allocate data buffer for element count " +
- std::to_string(mDataMQ->getQuantumCount()) +
+ std::to_string(dataMQ->getQuantumCount()) +
", size in bytes: " + std::to_string(mDataBufferSize);
}
if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
@@ -108,7 +115,7 @@
bool isConnected) const {
reply->status = STATUS_OK;
if (isConnected) {
- reply->observable.frames = mFrameCount;
+ reply->observable.frames = mContext->getFrameCount();
reply->observable.timeNs = ::android::elapsedRealtimeNano();
if (auto status = mDriver->getPosition(&reply->observable); status == ::android::OK) {
return;
@@ -135,7 +142,7 @@
// TODO: Add a delay for transitions of async operations when/if they added.
StreamDescriptor::Command command{};
- if (!mCommandMQ->readBlocking(&command, 1)) {
+ if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
@@ -153,7 +160,7 @@
switch (command.getTag()) {
case Tag::halReservedExit:
if (const int32_t cookie = command.get<Tag::halReservedExit>();
- cookie == mInternalCommandCookie) {
+ cookie == mContext->getInternalCommandCookie()) {
mDriver->shutdown();
setClosed();
// This is an internal command, no need to reply.
@@ -271,7 +278,7 @@
}
reply.state = mState;
LOG(severity) << __func__ << ": writing reply " << reply.toString();
- if (!mReplyMQ->writeBlocking(&reply, 1)) {
+ if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
@@ -280,14 +287,16 @@
}
bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply) {
- const size_t byteCount = std::min({clientSize, mDataMQ->availableToWrite(), mDataBufferSize});
+ StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+ const size_t byteCount = std::min({clientSize, dataMQ->availableToWrite(), mDataBufferSize});
const bool isConnected = mIsConnected;
+ const size_t frameSize = mContext->getFrameSize();
size_t actualFrameCount = 0;
bool fatal = false;
int32_t latency = Module::kLatencyMs;
if (isConnected) {
- if (::android::status_t status = mDriver->transfer(
- mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
+ if (::android::status_t status = mDriver->transfer(mDataBuffer.get(), byteCount / frameSize,
+ &actualFrameCount, &latency);
status != ::android::OK) {
fatal = true;
LOG(ERROR) << __func__ << ": read failed: " << status;
@@ -295,17 +304,16 @@
} else {
usleep(3000); // Simulate blocking transfer delay.
for (size_t i = 0; i < byteCount; ++i) mDataBuffer[i] = 0;
- actualFrameCount = byteCount / mFrameSize;
+ actualFrameCount = byteCount / frameSize;
}
- const size_t actualByteCount = actualFrameCount * mFrameSize;
- if (bool success =
- actualByteCount > 0 ? mDataMQ->write(&mDataBuffer[0], actualByteCount) : true;
+ const size_t actualByteCount = actualFrameCount * frameSize;
+ if (bool success = actualByteCount > 0 ? dataMQ->write(&mDataBuffer[0], actualByteCount) : true;
success) {
LOG(VERBOSE) << __func__ << ": writing of " << actualByteCount << " bytes into data MQ"
<< " succeeded; connected? " << isConnected;
// Frames are provided and counted regardless of connection status.
reply->fmqByteCount += actualByteCount;
- mFrameCount += actualFrameCount;
+ mContext->advanceFrameCount(actualFrameCount);
populateReply(reply, isConnected);
} else {
LOG(WARNING) << __func__ << ": writing of " << actualByteCount
@@ -324,7 +332,8 @@
if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - mTransientStateStart);
stateDurationMs >= mTransientStateDelayMs) {
- if (mAsyncCallback == nullptr) {
+ std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
+ if (asyncCallback == nullptr) {
// In blocking mode, mState can only be DRAINING.
mState = StreamDescriptor::State::IDLE;
} else {
@@ -332,13 +341,13 @@
// drain or transfer completion. In the stub, we switch unconditionally.
if (mState == StreamDescriptor::State::DRAINING) {
mState = StreamDescriptor::State::IDLE;
- ndk::ScopedAStatus status = mAsyncCallback->onDrainReady();
+ ndk::ScopedAStatus status = asyncCallback->onDrainReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
}
} else {
mState = StreamDescriptor::State::ACTIVE;
- ndk::ScopedAStatus status = mAsyncCallback->onTransferReady();
+ ndk::ScopedAStatus status = asyncCallback->onTransferReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
}
@@ -352,7 +361,7 @@
}
StreamDescriptor::Command command{};
- if (!mCommandMQ->readBlocking(&command, 1)) {
+ if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
@@ -371,7 +380,7 @@
switch (command.getTag()) {
case Tag::halReservedExit:
if (const int32_t cookie = command.get<Tag::halReservedExit>();
- cookie == mInternalCommandCookie) {
+ cookie == mContext->getInternalCommandCookie()) {
mDriver->shutdown();
setClosed();
// This is an internal command, no need to reply.
@@ -426,10 +435,11 @@
if (!write(fmqByteCount, &reply)) {
mState = StreamDescriptor::State::ERROR;
}
+ std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
if (mState == StreamDescriptor::State::STANDBY ||
mState == StreamDescriptor::State::DRAIN_PAUSED ||
mState == StreamDescriptor::State::PAUSED) {
- if (mAsyncCallback == nullptr ||
+ if (asyncCallback == nullptr ||
mState != StreamDescriptor::State::DRAIN_PAUSED) {
mState = StreamDescriptor::State::PAUSED;
} else {
@@ -438,7 +448,7 @@
} else if (mState == StreamDescriptor::State::IDLE ||
mState == StreamDescriptor::State::DRAINING ||
mState == StreamDescriptor::State::ACTIVE) {
- if (mAsyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
+ if (asyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
mState = StreamDescriptor::State::ACTIVE;
} else {
switchToTransientState(StreamDescriptor::State::TRANSFERRING);
@@ -460,7 +470,8 @@
if (::android::status_t status = mDriver->drain(mode);
status == ::android::OK) {
populateReply(&reply, mIsConnected);
- if (mState == StreamDescriptor::State::ACTIVE && mForceSynchronousDrain) {
+ if (mState == StreamDescriptor::State::ACTIVE &&
+ mContext->getForceSynchronousDrain()) {
mState = StreamDescriptor::State::IDLE;
} else {
switchToTransientState(StreamDescriptor::State::DRAINING);
@@ -535,7 +546,7 @@
}
reply.state = mState;
LOG(severity) << __func__ << ": writing reply " << reply.toString();
- if (!mReplyMQ->writeBlocking(&reply, 1)) {
+ if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
@@ -544,38 +555,40 @@
}
bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* reply) {
- const size_t readByteCount = mDataMQ->availableToRead();
+ StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+ const size_t readByteCount = dataMQ->availableToRead();
+ const size_t frameSize = mContext->getFrameSize();
bool fatal = false;
int32_t latency = Module::kLatencyMs;
- if (bool success = readByteCount > 0 ? mDataMQ->read(&mDataBuffer[0], readByteCount) : true) {
+ if (bool success = readByteCount > 0 ? dataMQ->read(&mDataBuffer[0], readByteCount) : true) {
const bool isConnected = mIsConnected;
LOG(VERBOSE) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
<< " succeeded; connected? " << isConnected;
// Amount of data that the HAL module is going to actually use.
size_t byteCount = std::min({clientSize, readByteCount, mDataBufferSize});
- if (byteCount >= mFrameSize && mForceTransientBurst) {
+ if (byteCount >= frameSize && mContext->getForceTransientBurst()) {
// In order to prevent the state machine from going to ACTIVE state,
// simulate partial write.
- byteCount -= mFrameSize;
+ byteCount -= frameSize;
}
size_t actualFrameCount = 0;
if (isConnected) {
if (::android::status_t status = mDriver->transfer(
- mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
+ mDataBuffer.get(), byteCount / frameSize, &actualFrameCount, &latency);
status != ::android::OK) {
fatal = true;
LOG(ERROR) << __func__ << ": write failed: " << status;
}
} else {
- if (mAsyncCallback == nullptr) {
+ if (mContext->getAsyncCallback() == nullptr) {
usleep(3000); // Simulate blocking transfer delay.
}
- actualFrameCount = byteCount / mFrameSize;
+ actualFrameCount = byteCount / frameSize;
}
- const size_t actualByteCount = actualFrameCount * mFrameSize;
+ const size_t actualByteCount = actualFrameCount * frameSize;
// Frames are consumed and counted regardless of the connection status.
reply->fmqByteCount += actualByteCount;
- mFrameCount += actualFrameCount;
+ mContext->advanceFrameCount(actualFrameCount);
populateReply(reply, isConnected);
} else {
LOG(WARNING) << __func__ << ": reading of " << readByteCount
@@ -597,18 +610,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.getInstance();
LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -659,8 +670,7 @@
LOG(DEBUG) << __func__ << ": joining the worker thread...";
mWorker->stop();
LOG(DEBUG) << __func__ << ": worker thread joined";
- mContext.reset();
- mWorker->setClosed();
+ onClose(mWorker->setClosed());
return ndk::ScopedAStatus::ok();
} else {
LOG(ERROR) << __func__ << ": stream was already closed";
@@ -723,11 +733,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 +794,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/StreamSwitcher.cpp b/audio/aidl/default/StreamSwitcher.cpp
new file mode 100644
index 0000000..956f413
--- /dev/null
+++ b/audio/aidl/default/StreamSwitcher.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits>
+
+#define LOG_TAG "AHAL_StreamSwitcher"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+
+#include "core-impl/StreamStub.h"
+#include "core-impl/StreamSwitcher.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioDevice;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamSwitcher::StreamSwitcher(StreamContext* context, const Metadata& metadata)
+ : mMetadata(metadata), mStream(new InnerStreamWrapper<StreamStub>(context, mMetadata)) {}
+
+ndk::ScopedAStatus StreamSwitcher::closeCurrentStream(bool validateStreamState) {
+ if (!mStream) return ndk::ScopedAStatus::ok();
+ RETURN_STATUS_IF_ERROR(mStream->prepareToClose());
+ RETURN_STATUS_IF_ERROR(mStream->close());
+ if (validateStreamState && !isValidClosingStreamState(mStream->getStatePriorToClosing())) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ mStream.reset();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::close() {
+ if (mStream != nullptr) {
+ auto status = closeCurrentStream(false /*validateStreamState*/);
+ // The actual state is irrelevant since only StreamSwitcher cares about it.
+ onClose(StreamDescriptor::State::STANDBY);
+ return status;
+ }
+ LOG(ERROR) << __func__ << ": stream was already closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+}
+
+ndk::ScopedAStatus StreamSwitcher::prepareToClose() {
+ if (mStream != nullptr) {
+ return mStream->prepareToClose();
+ }
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+}
+
+ndk::ScopedAStatus StreamSwitcher::updateHwAvSyncId(int32_t in_hwAvSyncId) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ RETURN_STATUS_IF_ERROR(mStream->updateHwAvSyncId(in_hwAvSyncId));
+ mHwAvSyncId = in_hwAvSyncId;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (mIsStubStream) {
+ LOG(ERROR) << __func__ << ": the stream is not connected";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return mStream->getVendorParameters(in_ids, _aidl_return);
+}
+
+ndk::ScopedAStatus StreamSwitcher::setVendorParameters(
+ const std::vector<VendorParameter>& in_parameters, bool in_async) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (mIsStubStream) {
+ mMissedParameters.emplace_back(in_parameters, in_async);
+ return ndk::ScopedAStatus::ok();
+ }
+ return mStream->setVendorParameters(in_parameters, in_async);
+}
+
+ndk::ScopedAStatus StreamSwitcher::addEffect(const std::shared_ptr<IEffect>& in_effect) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (!mIsStubStream) {
+ RETURN_STATUS_IF_ERROR(mStream->addEffect(in_effect));
+ }
+ mEffects.push_back(in_effect);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::removeEffect(const std::shared_ptr<IEffect>& in_effect) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ for (auto it = mEffects.begin(); it != mEffects.end();) {
+ if ((*it)->asBinder() == in_effect->asBinder()) {
+ it = mEffects.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ return !mIsStubStream ? mStream->removeEffect(in_effect) : ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::getStreamCommonCommon(
+ std::shared_ptr<IStreamCommon>* _aidl_return) {
+ if (!mCommon) {
+ LOG(FATAL) << __func__ << ": the common interface was not created";
+ }
+ *_aidl_return = mCommon.getInstance();
+ LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::updateMetadataCommon(const Metadata& metadata) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ mMetadata = metadata;
+ return !mIsStubStream ? mStream->updateMetadataCommon(metadata) : ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::initInstance(
+ const std::shared_ptr<StreamCommonInterface>& delegate) {
+ mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
+ // The delegate is null because StreamSwitcher handles IStreamCommon methods by itself.
+ return mStream->initInstance(nullptr);
+}
+
+const StreamContext& StreamSwitcher::getContext() const {
+ return *mContext;
+}
+
+bool StreamSwitcher::isClosed() const {
+ return mStream == nullptr || mStream->isClosed();
+}
+
+const StreamCommonInterface::ConnectedDevices& StreamSwitcher::getConnectedDevices() const {
+ return mStream->getConnectedDevices();
+}
+
+ndk::ScopedAStatus StreamSwitcher::setConnectedDevices(const std::vector<AudioDevice>& devices) {
+ LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(devices);
+ if (mStream->getConnectedDevices() == devices) return ndk::ScopedAStatus::ok();
+ const DeviceSwitchBehavior behavior = switchCurrentStream(devices);
+ if (behavior == DeviceSwitchBehavior::UNSUPPORTED_DEVICES) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ } else if (behavior == DeviceSwitchBehavior::SWITCH_TO_STUB_STREAM && !devices.empty()) {
+ // This is an error in the extending class.
+ LOG(FATAL) << __func__
+ << ": switching to stub stream with connected devices is not allowed";
+ }
+ if (behavior == USE_CURRENT_STREAM) {
+ mIsStubStream = false;
+ } else {
+ LOG(DEBUG) << __func__ << ": connected devices changed, switching stream";
+ // Two streams can't be opened for the same context, thus we always need to close
+ // the current one before creating a new one.
+ RETURN_STATUS_IF_ERROR(closeCurrentStream(true /*validateStreamState*/));
+ if (behavior == CREATE_NEW_STREAM) {
+ mStream = createNewStream(devices, mContext, mMetadata);
+ mIsStubStream = false;
+ } else { // SWITCH_TO_STUB_STREAM
+ mStream.reset(new InnerStreamWrapper<StreamStub>(mContext, mMetadata));
+ mIsStubStream = true;
+ }
+ // The delegate is null because StreamSwitcher handles IStreamCommon methods by itself.
+ if (ndk::ScopedAStatus status = mStream->initInstance(nullptr); !status.isOk()) {
+ // Need to close the current failed stream, and report an error.
+ // Since we can't operate without a stream implementation, put a stub in.
+ RETURN_STATUS_IF_ERROR(closeCurrentStream(false /*validateStreamState*/));
+ mStream.reset(new InnerStreamWrapper<StreamStub>(mContext, mMetadata));
+ (void)mStream->initInstance(nullptr);
+ (void)mStream->setConnectedDevices(devices);
+ return status;
+ }
+ }
+ RETURN_STATUS_IF_ERROR(mStream->setConnectedDevices(devices));
+ if (behavior == CREATE_NEW_STREAM) {
+ // These updates are less critical, only log warning on failure.
+ if (mHwAvSyncId.has_value()) {
+ if (auto status = mStream->updateHwAvSyncId(*mHwAvSyncId); !status.isOk()) {
+ LOG(WARNING) << __func__ << ": could not update HW AV Sync for a new stream: "
+ << status.getDescription();
+ }
+ }
+ for (const auto& vndParam : mMissedParameters) {
+ if (auto status = mStream->setVendorParameters(vndParam.first, vndParam.second);
+ !status.isOk()) {
+ LOG(WARNING) << __func__ << ": error while setting parameters for a new stream: "
+ << status.getDescription();
+ }
+ }
+ mMissedParameters.clear();
+ for (const auto& effect : mEffects) {
+ if (auto status = mStream->addEffect(effect); !status.isOk()) {
+ LOG(WARNING) << __func__ << ": error while adding effect for a new stream: "
+ << status.getDescription();
+ }
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::core
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..00a7a84 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(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/ChildInterface.h b/audio/aidl/default/include/core-impl/ChildInterface.h
index 1b31691..2421b59 100644
--- a/audio/aidl/default/include/core-impl/ChildInterface.h
+++ b/audio/aidl/default/include/core-impl/ChildInterface.h
@@ -35,14 +35,20 @@
}
ChildInterface& operator=(std::shared_ptr<C>&& c) {
this->first = std::move(c);
- this->second = this->first->asBinder();
- AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
return *this;
}
explicit operator bool() const { return !!this->first; }
C& operator*() const { return *(this->first); }
C* operator->() const { return this->first; }
- std::shared_ptr<C> getPtr() const { return this->first; }
+ // Use 'getInstance' when returning the interface instance.
+ std::shared_ptr<C> getInstance() {
+ if (this->second.get() == nullptr) {
+ this->second = this->first->asBinder();
+ AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
+ }
+ return this->first;
+ }
};
} // namespace aidl::android::hardware::audio::core
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..fa2b760 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 {
@@ -65,7 +66,8 @@
DataMQ;
// Ensure that this value is not used by any of StreamDescriptor.State enums
- static constexpr int32_t STATE_CLOSED = -1;
+ static constexpr StreamDescriptor::State STATE_CLOSED =
+ static_cast<StreamDescriptor::State>(-1);
struct DebugParameters {
// An extra delay for transient states, in ms.
@@ -112,7 +114,8 @@
mDataMQ(std::move(other.mDataMQ)),
mAsyncCallback(std::move(other.mAsyncCallback)),
mOutEventCallback(std::move(other.mOutEventCallback)),
- mDebugParameters(std::move(other.mDebugParameters)) {}
+ mDebugParameters(std::move(other.mDebugParameters)),
+ mFrameCount(other.mFrameCount) {}
StreamContext& operator=(StreamContext&& other) {
mCommandMQ = std::move(other.mCommandMQ);
mInternalCommandCookie = other.mInternalCommandCookie;
@@ -127,11 +130,13 @@
mAsyncCallback = std::move(other.mAsyncCallback);
mOutEventCallback = std::move(other.mOutEventCallback);
mDebugParameters = std::move(other.mDebugParameters);
+ mFrameCount = other.mFrameCount;
return *this;
}
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;
}
@@ -154,7 +159,12 @@
int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
int getSampleRate() const { return mSampleRate; }
bool isValid() const;
+ // 'reset' is called on a Binder thread when closing the stream. Does not use
+ // locking because it only cleans MQ pointers which were also set on the Binder thread.
void reset();
+ // 'advanceFrameCount' and 'getFrameCount' are only called on the worker thread.
+ long advanceFrameCount(size_t increase) { return mFrameCount += increase; }
+ long getFrameCount() const { return mFrameCount; }
private:
std::unique_ptr<CommandMQ> mCommandMQ;
@@ -170,6 +180,7 @@
std::shared_ptr<IStreamCallback> mAsyncCallback;
std::shared_ptr<IStreamOutEventCallback> mOutEventCallback; // Only used by output streams
DebugParameters mDebugParameters;
+ long mFrameCount = 0;
};
// This interface provides operations of the stream which are executed on the worker thread.
@@ -195,26 +206,23 @@
class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
public:
- bool isClosed() const {
- return static_cast<int32_t>(mState.load()) == StreamContext::STATE_CLOSED;
+ bool isClosed() const { return mState == StreamContext::STATE_CLOSED; }
+ StreamDescriptor::State setClosed() {
+ auto prevState = mState.exchange(StreamContext::STATE_CLOSED);
+ if (prevState != StreamContext::STATE_CLOSED) {
+ mStatePriorToClosing = prevState;
+ }
+ return mStatePriorToClosing;
}
- void setClosed() { mState = static_cast<StreamDescriptor::State>(StreamContext::STATE_CLOSED); }
void setIsConnected(bool connected) { mIsConnected = connected; }
protected:
using DataBufferElement = int8_t;
- StreamWorkerCommonLogic(const StreamContext& context, DriverInterface* driver)
- : mDriver(driver),
- mInternalCommandCookie(context.getInternalCommandCookie()),
- mFrameSize(context.getFrameSize()),
- mCommandMQ(context.getCommandMQ()),
- mReplyMQ(context.getReplyMQ()),
- mDataMQ(context.getDataMQ()),
- mAsyncCallback(context.getAsyncCallback()),
- mTransientStateDelayMs(context.getTransientStateDelayMs()),
- mForceTransientBurst(context.getForceTransientBurst()),
- mForceSynchronousDrain(context.getForceSynchronousDrain()) {}
+ StreamWorkerCommonLogic(StreamContext* context, DriverInterface* driver)
+ : mContext(context),
+ mDriver(driver),
+ mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
std::string init() override;
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
void populateReplyWrongState(StreamDescriptor::Reply* reply,
@@ -224,38 +232,35 @@
mTransientStateStart = std::chrono::steady_clock::now();
}
+ // The context is only used for reading, except for updating the frame count,
+ // which happens on the worker thread only.
+ StreamContext* const mContext;
DriverInterface* const mDriver;
+ // This is the state the stream was in before being closed. It is retrieved by the main
+ // thread after joining the worker thread.
+ StreamDescriptor::State mStatePriorToClosing = StreamDescriptor::State::STANDBY;
// Atomic fields are used both by the main and worker threads.
std::atomic<bool> mIsConnected = false;
static_assert(std::atomic<StreamDescriptor::State>::is_always_lock_free);
std::atomic<StreamDescriptor::State> mState = StreamDescriptor::State::STANDBY;
- // All fields are used on the worker thread only.
- const int mInternalCommandCookie;
- const size_t mFrameSize;
- StreamContext::CommandMQ* const mCommandMQ;
- StreamContext::ReplyMQ* const mReplyMQ;
- StreamContext::DataMQ* const mDataMQ;
- std::shared_ptr<IStreamCallback> mAsyncCallback;
+ // All fields below are used on the worker thread only.
const std::chrono::duration<int, std::milli> mTransientStateDelayMs;
std::chrono::time_point<std::chrono::steady_clock> mTransientStateStart;
- const bool mForceTransientBurst;
- const bool mForceSynchronousDrain;
// We use an array and the "size" field instead of a vector to be able to detect
// memory allocation issues.
std::unique_ptr<DataBufferElement[]> mDataBuffer;
size_t mDataBufferSize;
- long mFrameCount = 0;
};
// This interface is used to decouple stream implementations from a concrete StreamWorker
// implementation.
struct StreamWorkerInterface {
- using CreateInstance = std::function<StreamWorkerInterface*(const StreamContext& context,
- DriverInterface* driver)>;
+ using CreateInstance =
+ std::function<StreamWorkerInterface*(StreamContext* context, DriverInterface* driver)>;
virtual ~StreamWorkerInterface() = default;
virtual bool isClosed() const = 0;
virtual void setIsConnected(bool isConnected) = 0;
- virtual void setClosed() = 0;
+ virtual StreamDescriptor::State setClosed() = 0;
virtual bool start() = 0;
virtual void stop() = 0;
};
@@ -266,11 +271,11 @@
using WorkerImpl = ::android::hardware::audio::common::StreamWorker<WorkerLogic>;
public:
- StreamWorkerImpl(const StreamContext& context, DriverInterface* driver)
+ StreamWorkerImpl(StreamContext* context, DriverInterface* driver)
: WorkerImpl(context, driver) {}
bool isClosed() const override { return WorkerImpl::isClosed(); }
void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
- void setClosed() override { WorkerImpl::setClosed(); }
+ StreamDescriptor::State setClosed() override { return WorkerImpl::setClosed(); }
bool start() override {
return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_AUDIO);
}
@@ -280,7 +285,7 @@
class StreamInWorkerLogic : public StreamWorkerCommonLogic {
public:
static const std::string kThreadName;
- StreamInWorkerLogic(const StreamContext& context, DriverInterface* driver)
+ StreamInWorkerLogic(StreamContext* context, DriverInterface* driver)
: StreamWorkerCommonLogic(context, driver) {}
protected:
@@ -294,8 +299,9 @@
class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
public:
static const std::string kThreadName;
- StreamOutWorkerLogic(const StreamContext& context, DriverInterface* driver)
- : StreamWorkerCommonLogic(context, driver), mEventCallback(context.getOutEventCallback()) {}
+ StreamOutWorkerLogic(StreamContext* context, DriverInterface* driver)
+ : StreamWorkerCommonLogic(context, driver),
+ mEventCallback(context->getOutEventCallback()) {}
protected:
Status cycle() override;
@@ -409,16 +415,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(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(context, this)) {}
+ StreamCommonImpl(StreamContext* context, const Metadata& metadata)
: StreamCommonImpl(
- metadata, std::move(context),
+ context, metadata,
isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
~StreamCommonImpl();
@@ -450,23 +457,23 @@
protected:
static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
- return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+ return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
return new StreamInWorker(ctx, driver);
};
}
static StreamWorkerInterface::CreateInstance getDefaultOutWorkerCreator() {
- return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+ return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
return new StreamOutWorker(ctx, driver);
};
}
+ virtual void onClose(StreamDescriptor::State statePriorToClosing) = 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 +481,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 +502,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 +546,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..f98a922 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(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..b39583e 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(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(StreamDescriptor::State) 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(StreamDescriptor::State) 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..a8a3fc4 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(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(StreamDescriptor::State) 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(StreamDescriptor::State) override { defaultOnClose(); }
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/include/core-impl/StreamSwitcher.h
new file mode 100644
index 0000000..e462481
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamSwitcher.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+// 'StreamSwitcher' is implementation of 'StreamCommonInterface' which allows
+// dynamically switching the underlying stream implementation based on currently
+// connected devices. This is achieved by replacing inheritance from
+// 'StreamCommonImpl' with owning an instance of it. StreamSwitcher must be
+// extended in order to supply the logic for choosing the stream
+// implementation. When there are no connected devices, for instance, upon the
+// creation, the StreamSwitcher engages an instance of a stub stream in order to
+// keep serving requests coming via 'StreamDescriptor'.
+//
+// StreamSwitcher implements the 'IStreamCommon' interface directly, with
+// necessary delegation to the current stream implementation. While the stub
+// stream is engaged, any requests made via 'IStreamCommon' (parameters, effects
+// setting, etc) are postponed and only delivered on device connection change
+// to the "real" stream implementation provided by the extending class. This is why
+// the behavior of StreamSwitcher in the "stub" state is not identical to behavior
+// of 'StreamStub'. It can become a full substitute for 'StreamStub' once
+// device connection change event occurs and the extending class returns
+// 'LEAVE_CURRENT_STREAM' from 'switchCurrentStream' method.
+//
+// There is a natural limitation that the current stream implementation may only
+// be switched when the stream is in the 'STANDBY' state. Thus, when the event
+// to switch the stream occurs, the current stream is stopped and joined, and
+// its last state is validated. Since the change of the set of connected devices
+// normally occurs on patch updates, if the stream was not in standby, this is
+// reported to the caller of 'IModule.setAudioPatch' as the 'EX_ILLEGAL_STATE'
+// error.
+//
+// The simplest use case, when the implementor just needs to emulate the legacy HAL API
+// behavior of receiving the connected devices upon stream creation, the implementation
+// of the extending class can look as follows. We assume that 'StreamLegacy' implementation
+// is the one requiring to know connected devices on creation:
+//
+// class StreamLegacy : public StreamCommonImpl {
+// public:
+// StreamLegacy(StreamContext* context, const Metadata& metadata,
+// const std::vector<AudioDevice>& devices);
+// };
+//
+// class StreamOutLegacy final : public StreamOut, public StreamSwitcher {
+// public:
+// StreamOutLegacy(StreamContext&& context, metatadata etc.)
+// private:
+// DeviceSwitchBehavior switchCurrentStream(const std::vector<AudioDevice>&) override {
+// // This implementation effectively postpones stream creation until
+// // receiving the first call to 'setConnectedDevices' with a non-empty list.
+// return isStubStream() ? DeviceSwitchBehavior::CREATE_NEW_STREAM :
+// DeviceSwitchBehavior::USE_CURRENT_STREAM;
+// }
+// std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+// const std::vector<AudioDevice>& devices,
+// StreamContext* context, const Metadata& metadata) override {
+// return std::unique_ptr<StreamCommonInterfaceEx>(new InnerStreamWrapper<StreamLegacy>(
+// context, metadata, devices));
+// }
+// void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+// }
+//
+
+class StreamCommonInterfaceEx : virtual public StreamCommonInterface {
+ public:
+ virtual StreamDescriptor::State getStatePriorToClosing() const = 0;
+};
+
+template <typename T>
+class InnerStreamWrapper : public T, public StreamCommonInterfaceEx {
+ public:
+ InnerStreamWrapper(StreamContext* context, const Metadata& metadata) : T(context, metadata) {}
+ StreamDescriptor::State getStatePriorToClosing() const override { return mStatePriorToClosing; }
+
+ private:
+ // Do not need to do anything on close notification from the inner stream
+ // because StreamSwitcher handles IStreamCommon::close by itself.
+ void onClose(StreamDescriptor::State statePriorToClosing) override {
+ mStatePriorToClosing = statePriorToClosing;
+ }
+
+ StreamDescriptor::State mStatePriorToClosing = StreamDescriptor::State::STANDBY;
+};
+
+class StreamSwitcher : virtual public StreamCommonInterface {
+ public:
+ StreamSwitcher(StreamContext* context, const Metadata& metadata);
+
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus prepareToClose() override;
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override;
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override;
+ ndk::ScopedAStatus addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
+ ndk::ScopedAStatus removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+ override;
+
+ ndk::ScopedAStatus getStreamCommonCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override;
+ ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+
+ ndk::ScopedAStatus initInstance(
+ const std::shared_ptr<StreamCommonInterface>& delegate) override;
+ const StreamContext& getContext() const override;
+ bool isClosed() const override;
+ const ConnectedDevices& getConnectedDevices() const override;
+ ndk::ScopedAStatus setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
+
+ protected:
+ // Since switching a stream requires closing down the current stream, StreamSwitcher
+ // asks the extending class its intent on the connected devices change.
+ enum DeviceSwitchBehavior {
+ // Continue using the current stream implementation. If it's the stub implementation,
+ // StreamSwitcher starts treating the stub stream as a "real" implementation,
+ // without effectively closing it and starting again.
+ USE_CURRENT_STREAM,
+ // This is the normal case when the extending class provides a "real" implementation
+ // which is not a stub implementation.
+ CREATE_NEW_STREAM,
+ // This is the case when the extending class wants to revert back to the initial
+ // condition of using a stub stream provided by the StreamSwitcher. This behavior
+ // is only allowed when the list of connected devices is empty.
+ SWITCH_TO_STUB_STREAM,
+ // Use when the set of devices is not supported by the extending class. This returns
+ // 'EX_UNSUPPORTED_OPERATION' from 'setConnectedDevices'.
+ UNSUPPORTED_DEVICES,
+ };
+ // StreamSwitcher will call these methods from 'setConnectedDevices'. If the switch behavior
+ // is 'CREATE_NEW_STREAM', the 'createwNewStream' function will be called (with the same
+ // device vector) for obtaining a new stream implementation, assuming that closing
+ // the current stream was a success.
+ virtual DeviceSwitchBehavior switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
+ virtual std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) = 0;
+ virtual void onClose(StreamDescriptor::State streamPriorToClosing) = 0;
+
+ bool isStubStream() const { return mIsStubStream; }
+ StreamCommonInterfaceEx* getCurrentStream() const { return mStream.get(); }
+
+ private:
+ using VndParam = std::pair<std::vector<VendorParameter>, bool /*isAsync*/>;
+
+ static constexpr bool isValidClosingStreamState(StreamDescriptor::State state) {
+ return state == StreamDescriptor::State::STANDBY || state == StreamDescriptor::State::ERROR;
+ }
+
+ ndk::ScopedAStatus closeCurrentStream(bool validateStreamState);
+
+ // StreamSwitcher does not own the context.
+ StreamContext* mContext;
+ Metadata mMetadata;
+ ChildInterface<StreamCommonDelegator> mCommon;
+ // The current stream.
+ std::unique_ptr<StreamCommonInterfaceEx> mStream;
+ // Indicates whether 'mCurrentStream' is a stub stream implementation
+ // maintained by StreamSwitcher until the extending class provides a "real"
+ // implementation. The invariant of this state is that there are no connected
+ // devices.
+ bool mIsStubStream = true;
+ // Storage for the data from commands received via 'IStreamCommon'.
+ std::optional<int32_t> mHwAvSyncId;
+ std::vector<VndParam> mMissedParameters;
+ std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
+};
+
+} // 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..74e30ff 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(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(StreamDescriptor::State) 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(StreamDescriptor::State) 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..9537ebc 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -29,14 +29,14 @@
namespace aidl::android::hardware::audio::core {
-StreamRemoteSubmix::StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context)
- : StreamCommonImpl(metadata, std::move(context)),
- mPortId(context.getPortId()),
+StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata)
+ : StreamCommonImpl(context, metadata),
+ mPortId(context->getPortId()),
mIsInput(isInput(metadata)) {
- mStreamConfig.frameSize = context.getFrameSize();
- mStreamConfig.format = context.getFormat();
- mStreamConfig.channelLayout = context.getChannelLayout();
- mStreamConfig.sampleRate = context.getSampleRate();
+ mStreamConfig.frameSize = context->getFrameSize();
+ mStreamConfig.format = context->getFormat();
+ mStreamConfig.channelLayout = context->getChannelLayout();
+ mStreamConfig.sampleRate = context->getSampleRate();
}
std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
@@ -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..9f6e0b4 100644
--- a/audio/aidl/default/stub/ModuleStub.cpp
+++ b/audio/aidl/default/stub/ModuleStub.cpp
@@ -37,8 +37,9 @@
if (!mBluetooth) {
mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
}
- *_aidl_return = mBluetooth.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get();
+ *_aidl_return = mBluetooth.getInstance();
+ LOG(DEBUG) << __func__
+ << ": returning instance of IBluetooth: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -46,8 +47,9 @@
if (!mBluetoothA2dp) {
mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
}
- *_aidl_return = mBluetoothA2dp.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+ *_aidl_return = mBluetoothA2dp.getInstance();
+ LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: "
+ << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@@ -55,23 +57,24 @@
if (!mBluetoothLe) {
mBluetoothLe = ndk::SharedRefBase::make<BluetoothLe>();
}
- *_aidl_return = mBluetoothLe.getPtr();
- LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+ *_aidl_return = mBluetoothLe.getInstance();
+ 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..66f4605 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(StreamContext* context, const Metadata& metadata)
+ : StreamCommonImpl(context, metadata),
mFrameSizeBytes(getContext().getFrameSize()),
mSampleRate(getContext().getSampleRate()),
mIsAsynchronous(!!getContext().getAsyncCallback()),
@@ -118,12 +118,13 @@
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..9684a87 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(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/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 0f6cac8..7d88810 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -169,7 +169,7 @@
* int32Values[4] = wheel base
* int32Values[5] = track width front
* int32Values[6] = track width rear
- * int32Values[7] = curb to curb turning radius
+ * int32Values[7] = curb to curb turning diameter
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 9757287..ec28846 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -52,6 +52,14 @@
const keymaster::HardwareAuthToken& hat,
const std::future<void>& cancel) {
BEGIN_OP(0);
+
+ // Do proper HAT verification in the real implementation.
+ if (hat.mac.empty()) {
+ LOG(ERROR) << "Fail: hat";
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
+
updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
}
@@ -112,17 +120,10 @@
}
bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb,
- const keymaster::HardwareAuthToken& hat,
+ const keymaster::HardwareAuthToken&,
const std::future<void>& cancel) {
BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
- // Do proper HAT verification in the real implementation.
- if (hat.mac.empty()) {
- LOG(ERROR) << "Fail: hat";
- cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
- return true;
- }
-
// Force error-out
auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
if (err != 0) {
@@ -258,7 +259,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..8584921 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -115,7 +115,8 @@
}
BroadcastRadio::~BroadcastRadio() {
- mThread.reset();
+ mTuningThread.reset();
+ mProgramListThread.reset();
}
ScopedAStatus BroadcastRadio::getAmFmRegionConfig(bool full, AmFmRegionConfig* returnConfigs) {
@@ -239,7 +240,7 @@
callback->onCurrentProgramInfoChanged(programInfo);
};
auto cancelTask = [program, callback]() { callback->onTuneFailed(Result::CANCELED, program); };
- mThread->schedule(task, cancelTask, kTuneDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kTuneDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -267,7 +268,7 @@
callback->onTuneFailed(Result::TIMEOUT, {});
};
- mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -300,7 +301,7 @@
}
callback->onCurrentProgramInfoChanged(programInfo);
};
- mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -355,15 +356,15 @@
callback->onCurrentProgramInfoChanged(programInfo);
};
auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
- mThread->schedule(task, cancelTask, kStepDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kStepDelayTimeMs);
return ScopedAStatus::ok();
}
void BroadcastRadio::cancelLocked() {
- LOG(DEBUG) << __func__ << ": cancelling current operations...";
+ LOG(DEBUG) << __func__ << ": cancelling current tuning operations...";
- mThread->cancelAll();
+ mTuningThread->cancelAll();
if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) {
mIsTuneCompleted = true;
}
@@ -388,6 +389,8 @@
lock_guard<mutex> lk(mMutex);
+ cancelProgramListUpdateLocked();
+
const auto& list = mVirtualRadio.getProgramList();
vector<VirtualProgram> filteredList;
std::copy_if(list.begin(), list.end(), std::back_inserter(filteredList), filterCb);
@@ -410,31 +413,43 @@
callback->onProgramListUpdated(chunk);
};
- mThread->schedule(task, kListDelayTimeS);
+ mProgramListThread->schedule(task, kListDelayTimeS);
return ScopedAStatus::ok();
}
+void BroadcastRadio::cancelProgramListUpdateLocked() {
+ LOG(DEBUG) << __func__ << ": cancelling current program list update operations...";
+ mProgramListThread->cancelAll();
+}
+
ScopedAStatus BroadcastRadio::stopProgramListUpdates() {
LOG(DEBUG) << __func__ << ": requested program list updates to stop...";
- // TODO(b/243681584) Implement stop program list updates method
+ lock_guard<mutex> lk(mMutex);
+ cancelProgramListUpdateLocked();
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..0f818ce 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -68,16 +68,22 @@
const VirtualRadio& mVirtualRadio;
std::mutex mMutex;
AmFmRegionConfig mAmFmConfig GUARDED_BY(mMutex);
- std::unique_ptr<::android::WorkerThread> mThread GUARDED_BY(mMutex) =
+ std::unique_ptr<::android::WorkerThread> mTuningThread GUARDED_BY(mMutex) =
+ std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
+ std::unique_ptr<::android::WorkerThread> mProgramListThread GUARDED_BY(mMutex) =
std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
bool mIsTuneCompleted GUARDED_BY(mMutex) = true;
Properties mProperties GUARDED_BY(mMutex);
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);
+ void cancelProgramListUpdateLocked();
binder_status_t cmdHelp(int fd) const;
binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
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/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index f3374c3..fc3a8b3 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <functional>
#include <string>
#include <vector>
diff --git a/graphics/composer/2.1/utils/resources/Android.bp b/graphics/composer/2.1/utils/resources/Android.bp
index 9eb23fa..4052003 100644
--- a/graphics/composer/2.1/utils/resources/Android.bp
+++ b/graphics/composer/2.1/utils/resources/Android.bp
@@ -29,20 +29,15 @@
vendor_available: true,
shared_libs: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
"libcutils",
"libhardware", // TODO remove hwcomposer2.h dependency
"libhidlbase",
"liblog",
+ "libui",
"libutils",
],
export_shared_lib_headers: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
"libhardware",
"libhidlbase",
"liblog",
diff --git a/graphics/composer/2.1/utils/resources/ComposerResources.cpp b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
index e52bf71..80bfb7a 100644
--- a/graphics/composer/2.1/utils/resources/ComposerResources.cpp
+++ b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
@@ -18,6 +18,8 @@
#include "composer-resources/2.1/ComposerResources.h"
+#include <ui/GraphicBufferMapper.h>
+
namespace android {
namespace hardware {
namespace graphics {
@@ -25,23 +27,10 @@
namespace V2_1 {
namespace hal {
+ComposerHandleImporter::ComposerHandleImporter() : mMapper{GraphicBufferMapper::get()} {}
+
bool ComposerHandleImporter::init() {
- mMapper4 = mapper::V4_0::IMapper::getService();
- if (mMapper4) {
- return true;
- }
- ALOGI_IF(!mMapper4, "failed to get mapper 4.0 service, falling back to mapper 3.0");
-
- mMapper3 = mapper::V3_0::IMapper::getService();
- if (mMapper3) {
- return true;
- }
- ALOGI_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");
-
- mMapper2 = mapper::V2_0::IMapper::getService();
- ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
-
- return mMapper2 != nullptr;
+ return true;
}
Error ComposerHandleImporter::importBuffer(const native_handle_t* rawHandle,
@@ -51,51 +40,17 @@
return Error::NONE;
}
- const native_handle_t* bufferHandle;
- if (mMapper2) {
- mapper::V2_0::Error error;
- mMapper2->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
- });
- if (error != mapper::V2_0::Error::NONE) {
- return Error::NO_RESOURCES;
- }
+ status_t status = mMapper.importBufferNoValidate(rawHandle, outBufferHandle);
+ if (status == STATUS_OK) {
+ return Error::NONE;
+ } else {
+ return Error::NO_RESOURCES;
}
- if (mMapper3) {
- mapper::V3_0::Error error;
- mMapper3->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
- });
- if (error != mapper::V3_0::Error::NONE) {
- return Error::NO_RESOURCES;
- }
- }
- if (mMapper4) {
- mapper::V4_0::Error error;
- mMapper4->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
- });
- if (error != mapper::V4_0::Error::NONE) {
- return Error::NO_RESOURCES;
- }
- }
-
- *outBufferHandle = bufferHandle;
- return Error::NONE;
}
void ComposerHandleImporter::freeBuffer(const native_handle_t* bufferHandle) {
if (bufferHandle) {
- if (mMapper2) {
- mMapper2->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
- } else if (mMapper3) {
- mMapper3->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
- } else if (mMapper4) {
- mMapper4->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
- }
+ mMapper.freeBuffer(bufferHandle);
}
}
diff --git a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
index de78a59..9838118 100644
--- a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
@@ -27,12 +27,10 @@
#include <android/hardware/graphics/composer/2.1/types.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
#include <log/log.h>
namespace android {
+class GraphicBufferMapper;
namespace hardware {
namespace graphics {
namespace composer {
@@ -42,6 +40,7 @@
// wrapper for IMapper to import buffers and sideband streams
class ComposerHandleImporter {
public:
+ ComposerHandleImporter();
bool init();
Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle);
@@ -50,9 +49,7 @@
void freeStream(const native_handle_t* streamHandle);
private:
- sp<mapper::V2_0::IMapper> mMapper2;
- sp<mapper::V3_0::IMapper> mMapper3;
- sp<mapper::V4_0::IMapper> mMapper4;
+ GraphicBufferMapper& mMapper;
};
class ComposerHandleCache {
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
index 7b6a0e6..3bc127f 100644
--- a/graphics/composer/2.1/utils/vts/Android.bp
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -26,7 +26,6 @@
cc_library_static {
name: "android.hardware.graphics.composer@2.1-vts",
defaults: [
- "android.hardware.graphics.allocator-ndk_static",
"hidl_defaults",
],
srcs: [
@@ -34,18 +33,15 @@
"GraphicsComposerCallback.cpp",
"TestCommandReader.cpp",
],
+ shared_libs: [
+ "libui",
+ ],
static_libs: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libgtest",
],
export_static_lib_headers: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
],
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 4603dd1..8b89784 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -308,113 +308,6 @@
writer->reset();
}
-NativeHandleWrapper::~NativeHandleWrapper() {
- if (mHandle) {
- mGralloc.freeBuffer(mHandle);
- }
-}
-
-Gralloc::Gralloc() {
- [this] {
- ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>(
- /*aidlAllocatorServiceName*/ IAllocator::descriptor +
- std::string("/default"),
- /*hidlAllocatorServiceName*/ "default",
- /*mapperServiceName*/ "default",
- /*errOnFailure=*/false));
- if (!mGralloc4->hasAllocator() || mGralloc4->getMapper() == nullptr) {
- mGralloc4 = nullptr;
- ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
- /*errOnFailure=*/false));
- if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) {
- mGralloc3 = nullptr;
- ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
- }
- }
- }();
-}
-
-const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import,
- uint32_t* outStride) {
- const native_handle_t* handle;
- if (mGralloc4) {
- IMapper4::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
- info.usage = usage;
- handle = mGralloc4->allocate(info, import, outStride);
- } else if (mGralloc3) {
- IMapper3::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
- info.usage = usage;
- handle = mGralloc3->allocate(info, import, outStride);
- } else {
- IMapper2::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = format;
- info.usage = usage;
- handle = mGralloc2->allocate(info, import, outStride);
- }
- return NativeHandleWrapper(*this, handle);
-}
-
-void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
- const AccessRegion& accessRegionRect, int acquireFence) {
- if (mGralloc4) {
- IMapper4::Rect accessRegion;
- accessRegion.left = accessRegionRect.left;
- accessRegion.top = accessRegionRect.top;
- accessRegion.width = accessRegionRect.width;
- accessRegion.height = accessRegionRect.height;
- return mGralloc4->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
- } else if (mGralloc3) {
- IMapper3::Rect accessRegion;
- accessRegion.left = accessRegionRect.left;
- accessRegion.top = accessRegionRect.top;
- accessRegion.width = accessRegionRect.width;
- accessRegion.height = accessRegionRect.height;
- int32_t bytesPerPixel;
- int32_t bytesPerStride;
- return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel,
- &bytesPerStride);
- } else {
- IMapper2::Rect accessRegion;
- accessRegion.left = accessRegionRect.left;
- accessRegion.top = accessRegionRect.top;
- accessRegion.width = accessRegionRect.width;
- accessRegion.height = accessRegionRect.height;
- return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
- }
-}
-
-int Gralloc::unlock(const native_handle_t* bufferHandle) {
- if (mGralloc4) {
- return mGralloc4->unlock(bufferHandle);
- } else if (mGralloc3) {
- return mGralloc3->unlock(bufferHandle);
- } else {
- return mGralloc2->unlock(bufferHandle);
- }
-}
-
-void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
- if (mGralloc4) {
- mGralloc4->freeBuffer(bufferHandle);
- } else if (mGralloc3) {
- mGralloc3->freeBuffer(bufferHandle);
- } else {
- mGralloc2->freeBuffer(bufferHandle);
- }
-}
-
} // namespace vts
} // namespace V2_1
} // namespace composer
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index f8ea661..c0aacb5 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -25,9 +25,6 @@
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
#include <composer-vts/2.1/TestCommandReader.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
#include <utils/StrongPointer.h>
#include "gtest/gtest.h"
@@ -43,13 +40,6 @@
using android::hardware::graphics::common::V1_0::Dataspace;
using android::hardware::graphics::common::V1_0::Hdr;
using android::hardware::graphics::common::V1_0::PixelFormat;
-using IMapper2 = android::hardware::graphics::mapper::V2_0::IMapper;
-using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
-using IMapper4 = android::hardware::graphics::mapper::V4_0::IMapper;
-using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
-using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
-using Gralloc4 = android::hardware::graphics::mapper::V4_0::vts::Gralloc;
-using IAllocator = aidl::android::hardware::graphics::allocator::IAllocator;
class ComposerClient;
@@ -129,52 +119,6 @@
const sp<IComposerClient> mClient;
};
-class AccessRegion {
- public:
- int32_t left;
- int32_t top;
- int32_t width;
- int32_t height;
-};
-
-class Gralloc;
-
-// RAII wrapper around native_handle_t*
-class NativeHandleWrapper {
- public:
- NativeHandleWrapper(Gralloc& gralloc, const native_handle_t* handle)
- : mGralloc(gralloc), mHandle(handle) {}
-
- ~NativeHandleWrapper();
-
- const native_handle_t* get() { return mHandle; }
-
- private:
- Gralloc& mGralloc;
- const native_handle_t* mHandle;
-};
-
-class Gralloc {
- public:
- explicit Gralloc();
-
- const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import = true,
- uint32_t* outStride = nullptr);
-
- void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
- const AccessRegion& accessRegionRect, int acquireFence);
-
- int unlock(const native_handle_t* bufferHandle);
-
- void freeBuffer(const native_handle_t* bufferHandle);
-
- protected:
- std::shared_ptr<Gralloc2> mGralloc2 = nullptr;
- std::shared_ptr<Gralloc3> mGralloc3 = nullptr;
- std::shared_ptr<Gralloc4> mGralloc4 = nullptr;
-};
-
} // namespace vts
} // namespace V2_1
} // namespace composer
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 0f6d7e8..0706341 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -27,7 +27,6 @@
name: "VtsHalGraphicsComposerV2_1TargetTest",
defaults: [
"VtsHalTargetTestDefaults",
- "android.hardware.graphics.allocator-ndk_static",
],
tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
@@ -38,22 +37,12 @@
"libbinder_ndk",
"libfmq",
"libsync",
+ "libui",
"android.hardware.common-V2-ndk",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
],
static_libs: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@2.1-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
],
header_libs: [
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 9444d89..b67cfc2 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -25,9 +25,7 @@
#include <hardware/hwcomposer2.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
#include <unistd.h>
@@ -52,7 +50,6 @@
using android::hardware::graphics::common::V1_0::Dataspace;
using android::hardware::graphics::common::V1_0::PixelFormat;
using android::hardware::graphics::common::V1_0::Transform;
-using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
@@ -651,7 +648,6 @@
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
IComposerClient::Attribute::WIDTH);
@@ -666,13 +662,17 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- NativeHandleWrapper allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
+ sp<GraphicBuffer> allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
- NativeHandleWrapper allocate(uint32_t width, uint32_t height) {
- uint64_t usage =
+ sp<GraphicBuffer> allocate(int32_t width, int32_t height) {
+ auto result = sp<GraphicBuffer>::make(
+ width, height, static_cast<int32_t>(PixelFormat::RGBA_8888), /*layerCount*/ 1,
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
- BufferUsage::COMPOSER_OVERLAY);
- return mGralloc->allocate(width, height, 1, PixelFormat::RGBA_8888, usage);
+ BufferUsage::COMPOSER_OVERLAY));
+ if (result->initCheck() != STATUS_OK) {
+ return nullptr;
+ }
+ return result;
}
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -681,9 +681,6 @@
std::unique_ptr<TestCommandReader> mReader;
int32_t mDisplayWidth;
int32_t mDisplayHeight;
-
- private:
- std::unique_ptr<Gralloc> mGralloc;
};
/**
@@ -729,11 +726,11 @@
display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
kBufferSlotCount, &format));
- std::unique_ptr<NativeHandleWrapper> handle;
- ASSERT_NO_FATAL_FAILURE(handle.reset(new NativeHandleWrapper(allocate())));
+ auto handle = allocate();
+ ASSERT_TRUE(handle);
mWriter->selectDisplay(display);
- mWriter->setOutputBuffer(0, handle->get(), -1);
+ mWriter->setOutputBuffer(0, handle->handle, -1);
execute();
}
@@ -802,7 +799,7 @@
mWriter->setLayerZOrder(10);
mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
- mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerBuffer(0, handle->handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
@@ -820,7 +817,7 @@
mWriter->selectLayer(layer);
auto handle2 = allocate();
ASSERT_NE(nullptr, handle2.get());
- mWriter->setLayerBuffer(0, handle2.get(), -1);
+ mWriter->setLayerBuffer(0, handle2->handle, -1);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
mWriter->presentDisplay();
execute();
@@ -840,7 +837,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerBuffer(0, handle->handle, -1);
mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
mWriter->setLayerDisplayFrame(displayFrame);
mWriter->setLayerPlaneAlpha(1);
@@ -881,7 +878,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerBuffer(0, handle->handle, -1);
execute();
}
@@ -905,7 +902,7 @@
mWriter->selectLayer(layer);
mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
mWriter->setLayerDisplayFrame(displayFrame);
- mWriter->setLayerBuffer(0, handle1.get(), -1);
+ mWriter->setLayerBuffer(0, handle1->handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
execute();
@@ -928,7 +925,7 @@
mWriter->selectLayer(layer);
mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
mWriter->setLayerDisplayFrame(displayFrame);
- mWriter->setLayerBuffer(1, handle2.get(), -1);
+ mWriter->setLayerBuffer(1, handle2->handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
execute();
@@ -951,7 +948,7 @@
mWriter->selectLayer(layer);
mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
mWriter->setLayerDisplayFrame(displayFrame);
- mWriter->setLayerBuffer(2, handle3.get(), -1);
+ mWriter->setLayerBuffer(2, handle3->handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
execute();
@@ -968,10 +965,10 @@
// Ensure we can clear multiple buffer slots and then restore the active buffer at the end
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, clearSlotBuffer.get(), -1);
+ mWriter->setLayerBuffer(0, clearSlotBuffer->handle, -1);
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(1, clearSlotBuffer.get(), -1);
+ mWriter->setLayerBuffer(1, clearSlotBuffer->handle, -1);
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
mWriter->setLayerBuffer(2, nullptr, -1);
@@ -1113,7 +1110,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
- mWriter->setLayerSidebandStream(handle.get());
+ mWriter->setLayerSidebandStream(handle->handle);
execute();
}
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index d11592f..a923923 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -26,7 +26,6 @@
cc_library_static {
name: "android.hardware.graphics.composer@2.2-vts",
defaults: [
- "android.hardware.graphics.allocator-ndk_static",
"android.hardware.graphics.composer3-ndk_static",
"hidl_defaults",
"librenderengine_deps",
@@ -42,7 +41,6 @@
static_libs: [
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
- "android.hardware.graphics.mapper@2.1-vts",
"libarect",
"libgtest",
"libmath",
@@ -50,15 +48,10 @@
"librenderengine",
"libshaders",
"libtonemap",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0",
- "android.hardware.graphics.mapper@4.0-vts",
],
export_static_lib_headers: [
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
- "android.hardware.graphics.mapper@2.1-vts",
],
header_libs: [
"android.hardware.graphics.composer@2.2-command-buffer",
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index d4f0281..d041064 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -179,66 +179,6 @@
return matrix;
}
-Gralloc::Gralloc() {
- [this] {
- ALOGD("Attempting to initialize gralloc4");
- ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>(
- /*aidlAllocatorServiceName*/ IAllocator::descriptor +
- std::string("/default"),
- /*hidlAllocatorServiceName*/ "default",
- /*mapperServiceName*/ "default",
- /*errOnFailure=*/false));
- if (mGralloc4->getMapper() == nullptr || !mGralloc4->hasAllocator()) {
- mGralloc4 = nullptr;
- ALOGD("Failed to initialize gralloc4, initializing gralloc3");
- ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
- /*errOnFailure=*/false));
- if (mGralloc3->getMapper() == nullptr || mGralloc3->getAllocator() == nullptr) {
- mGralloc3 = nullptr;
- ALOGD("Failed to initialize gralloc3, initializing gralloc2_1");
- mGralloc2_1 = std::make_shared<Gralloc2_1>(/*errOnFailure*/ false);
- if (!mGralloc2_1->getMapper()) {
- mGralloc2_1 = nullptr;
- ALOGD("Failed to initialize gralloc2_1, initializing gralloc2");
- ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
- }
- }
- }
- }();
-}
-
-bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle, uint32_t width,
- uint32_t height, uint32_t layerCount, PixelFormat format,
- uint64_t usage, uint32_t stride) {
- if (mGralloc4) {
- IMapper4::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
- info.usage = usage;
- return mGralloc4->validateBufferSize(bufferHandle, info, stride);
- } else if (mGralloc3) {
- IMapper3::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
- info.usage = usage;
- return mGralloc3->validateBufferSize(bufferHandle, info, stride);
- } else if (mGralloc2_1) {
- IMapper2_1::BufferDescriptorInfo info{};
- info.width = width;
- info.height = height;
- info.layerCount = layerCount;
- info.format = static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format);
- info.usage = usage;
- return mGralloc2_1->validateBufferSize(bufferHandle, info, stride);
- } else {
- return true;
- }
-}
-
} // namespace vts
} // namespace V2_2
} // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index a1794af..9ba34f1 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -187,12 +187,11 @@
}
ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
- const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
- uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
+ uint32_t width, uint32_t height, PixelFormat pixelFormat,
+ Dataspace dataspace) {
mDisplay = display;
mComposerClient = client;
- mGralloc = gralloc;
mPixelFormat = pixelFormat;
mDataspace = dataspace;
@@ -202,20 +201,12 @@
mLayerCount = 1;
mFormat = mPixelFormat;
mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
-
- mAccessRegion.top = 0;
- mAccessRegion.left = 0;
- mAccessRegion.width = width;
- mAccessRegion.height = height;
}
void ReadbackBuffer::setReadbackBuffer() {
- mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
- mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
- /*import*/ true, &mStride)));
- ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
- mLayerCount, mFormat, mUsage, mStride));
- ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
+ mBuffer = sp<GraphicBuffer>::make(mWidth, mHeight, (int32_t)mFormat, mLayerCount, mUsage);
+ ASSERT_EQ(STATUS_OK, mBuffer->initCheck());
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBuffer->handle, -1));
}
void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
@@ -223,15 +214,14 @@
int32_t fenceHandle;
ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
- void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
+ void* bufData = nullptr;
+ int32_t stride = mBuffer->stride;
+ status_t status = mBuffer->lockAsync(mUsage, &bufData, fenceHandle);
+ ASSERT_EQ(STATUS_OK, status);
ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
- ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
+ ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
mPixelFormat);
- int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
- if (unlockFence != -1) {
- sync_wait(unlockFence, -1);
- close(unlockFence);
- }
+ EXPECT_EQ(STATUS_OK, mBuffer->unlock());
}
void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
@@ -251,12 +241,10 @@
}
TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
- const std::shared_ptr<Gralloc>& gralloc,
TestRenderEngine& renderEngine, Display display, int32_t width,
int32_t height, PixelFormat format,
IComposerClient::Composition composition)
: TestLayer{client, display}, mRenderEngine(renderEngine) {
- mGralloc = gralloc;
mComposition = composition;
mWidth = width;
mHeight = height;
@@ -265,11 +253,6 @@
mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE);
- mAccessRegion.top = 0;
- mAccessRegion.left = 0;
- mAccessRegion.width = width;
- mAccessRegion.height = height;
-
setSourceCrop({0, 0, (float)width, (float)height});
}
@@ -277,15 +260,13 @@
TestLayer::write(writer);
writer->setLayerCompositionType(mComposition);
writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
- if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence);
+ if (mBuffer) writer->setLayerBuffer(0, mBuffer->handle, -1);
}
LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
layerSettings.source.buffer.buffer = std::make_shared<renderengine::impl::ExternalTexture>(
- new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
- static_cast<int32_t>(mFormat), 1, mUsage, mStride),
- mRenderEngine.getInternalRenderEngine(),
+ mBuffer, mRenderEngine.getInternalRenderEngine(),
renderengine::impl::ExternalTexture::Usage::READABLE);
layerSettings.source.buffer.usePremultipliedAlpha =
@@ -304,24 +285,18 @@
}
void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
- void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1);
- ASSERT_NO_FATAL_FAILURE(
- ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
- mFillFence = mGralloc->unlock(mBufferHandle->get());
- if (mFillFence != -1) {
- sync_wait(mFillFence, -1);
- close(mFillFence);
- }
+ void* bufData = nullptr;
+ status_t status = mBuffer->lock(mUsage, &bufData);
+ ASSERT_EQ(STATUS_OK, status);
+ ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, mBuffer->stride, bufData,
+ mFormat, expectedColors));
+ EXPECT_EQ(STATUS_OK, mBuffer->unlock());
}
void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
- mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
- mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
- /*import*/ true, &mStride)));
- ASSERT_NE(nullptr, mBufferHandle->get());
+ mBuffer = sp<GraphicBuffer>::make(mWidth, mHeight, (int32_t)mFormat, mLayerCount, mUsage);
+ ASSERT_EQ(STATUS_OK, mBuffer->initCheck());
ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
- ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
- mLayerCount, mFormat, mUsage, mStride));
}
void TestBufferLayer::setDataspace(Dataspace dataspace,
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 1700b2a..62974f8 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -24,7 +24,6 @@
namespace V2_2 {
namespace vts {
-using mapper::V2_1::IMapper;
using renderengine::DisplaySettings;
using renderengine::LayerSettings;
using renderengine::RenderEngineCreationArgs;
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 02d7bdb..3e26d94 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -26,7 +26,6 @@
#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
#include <composer-vts/2.1/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -41,14 +40,6 @@
using common::V1_1::Dataspace;
using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
-using IMapper2_1 = android::hardware::graphics::mapper::V2_1::IMapper;
-using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
-using IMapper4 = android::hardware::graphics::mapper::V4_0::IMapper;
-using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
-using Gralloc2_1 = android::hardware::graphics::mapper::V2_1::vts::Gralloc;
-using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
-using Gralloc4 = android::hardware::graphics::mapper::V4_0::vts::Gralloc;
-using IAllocator = aidl::android::hardware::graphics::allocator::IAllocator;
class ComposerClient;
@@ -92,28 +83,6 @@
const sp<IComposerClient> mClient;
};
-class Gralloc : public V2_1::vts::Gralloc {
- public:
- using NativeHandleWrapper = V2_1::vts::NativeHandleWrapper;
-
- Gralloc();
- const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
- PixelFormat format, uint64_t usage, bool import = true,
- uint32_t* outStride = nullptr) {
- return V2_1::vts::Gralloc::allocate(
- width, height, layerCount,
- static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format), usage,
- import, outStride);
- }
-
- bool validateBufferSize(const native_handle_t* bufferHandle, uint32_t width, uint32_t height,
- uint32_t layerCount, PixelFormat format, uint64_t usage,
- uint32_t stride);
-
- protected:
- std::shared_ptr<Gralloc2_1> mGralloc2_1 = nullptr;
-};
-
} // namespace vts
} // namespace V2_2
} // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
index 58efde9..aa6932a 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -22,7 +22,6 @@
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
#include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
#include <renderengine/RenderEngine.h>
#include <memory>
@@ -38,12 +37,9 @@
using common::V1_1::BufferUsage;
using common::V1_1::Dataspace;
using common::V1_1::PixelFormat;
-using IMapper2_1 = mapper::V2_1::IMapper;
-using Gralloc2_1 = mapper::V2_1::vts::Gralloc;
using renderengine::LayerSettings;
using V2_1::Display;
using V2_1::Layer;
-using V2_1::vts::AccessRegion;
using V2_1::vts::TestCommandReader;
static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
@@ -113,9 +109,8 @@
class TestBufferLayer : public TestLayer {
public:
TestBufferLayer(
- const std::shared_ptr<ComposerClient>& client, const std::shared_ptr<Gralloc>& gralloc,
- TestRenderEngine& renderEngine, Display display, int32_t width, int32_t height,
- PixelFormat format,
+ const std::shared_ptr<ComposerClient>& client, TestRenderEngine& renderEngine,
+ Display display, int32_t width, int32_t height, PixelFormat format,
IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
void write(const std::shared_ptr<CommandWriterBase>& writer) override;
@@ -135,15 +130,11 @@
uint32_t mLayerCount;
PixelFormat mFormat;
uint64_t mUsage;
- AccessRegion mAccessRegion;
- uint32_t mStride;
protected:
IComposerClient::Composition mComposition;
- std::shared_ptr<Gralloc> mGralloc;
TestRenderEngine& mRenderEngine;
- int32_t mFillFence;
- std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle;
+ sp<GraphicBuffer> mBuffer;
};
class ReadbackHelper {
@@ -179,9 +170,8 @@
class ReadbackBuffer {
public:
- ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
- const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
- PixelFormat pixelFormat, Dataspace dataspace);
+ ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client, uint32_t width,
+ uint32_t height, PixelFormat pixelFormat, Dataspace dataspace);
void setReadbackBuffer();
@@ -193,13 +183,10 @@
uint32_t mLayerCount;
PixelFormat mFormat;
uint64_t mUsage;
- AccessRegion mAccessRegion;
- uint32_t mStride;
- std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle = nullptr;
+ sp<GraphicBuffer> mBuffer;
PixelFormat mPixelFormat;
Dataspace mDataspace;
Display mDisplay;
- std::shared_ptr<Gralloc> mGralloc;
std::shared_ptr<ComposerClient> mComposerClient;
};
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
index 26027d3..09b89ff 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
@@ -22,7 +22,6 @@
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -34,10 +33,8 @@
namespace V2_2 {
namespace vts {
-using mapper::V2_1::IMapper;
using renderengine::DisplaySettings;
using renderengine::RenderEngineCreationArgs;
-using vts::Gralloc;
class TestRenderEngine {
public:
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 3476376..a781712 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -27,7 +27,6 @@
name: "VtsHalGraphicsComposerV2_2TargetTest",
defaults: [
"VtsHalTargetTestDefaults",
- "android.hardware.graphics.allocator-ndk_static",
"android.hardware.graphics.composer3-ndk_static",
"librenderengine_deps",
],
@@ -54,24 +53,13 @@
"libsync",
"libui",
"android.hardware.common-V2-ndk",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
],
static_libs: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.2-vts",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@2.1-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
"libgtest",
"librenderengine",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index e2a0f4d..fa1d588 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -26,7 +26,6 @@
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -45,9 +44,7 @@
using common::V1_1::PixelFormat;
using V2_1::Config;
using V2_1::Display;
-using V2_1::vts::NativeHandleWrapper;
using V2_1::vts::TestCommandReader;
-using vts::Gralloc;
class GraphicsCompositionTestBase : public ::testing::Test {
protected:
@@ -79,7 +76,6 @@
// set up command writer/reader and gralloc
mWriter = std::make_shared<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
- mGralloc = std::make_shared<Gralloc>();
ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
@@ -143,7 +139,6 @@
std::vector<ColorMode> mTestColorModes;
std::shared_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
- std::shared_ptr<Gralloc> mGralloc;
std::unique_ptr<TestRenderEngine> mTestRenderEngine;
bool mHasReadbackBuffer;
@@ -220,7 +215,7 @@
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -272,7 +267,7 @@
mWriter->selectDisplay(mPrimaryDisplay);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
@@ -285,9 +280,9 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
- mDisplayHeight, PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+ mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -352,15 +347,16 @@
// This following buffer call should have no effect
uint64_t usage =
static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
- NativeHandleWrapper bufferHandle =
- mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
- mWriter->setLayerBuffer(0, bufferHandle.get(), -1);
+ sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(
+ mDisplayWidth, mDisplayHeight, (int32_t)PixelFormat::RGBA_8888, 1, usage);
+ ASSERT_EQ(STATUS_OK, buffer->initCheck());
+ mWriter->setLayerBuffer(0, buffer->handle, -1);
// expected color for each pixel
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -419,16 +415,16 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
- mDisplayHeight, PixelFormat::RGBA_FP16);
+ auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+ mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_FP16);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(layers);
@@ -462,25 +458,20 @@
}
// create client target buffer
- uint32_t clientStride;
- NativeHandleWrapper clientBufferHandle =
- mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount,
- clientFormat, clientUsage, /*import*/ true, &clientStride);
- ASSERT_NE(nullptr, clientBufferHandle.get());
+ sp<GraphicBuffer> clientBuffer =
+ sp<GraphicBuffer>::make(layer->mWidth, layer->mHeight, (int32_t)clientFormat,
+ layer->mLayerCount, clientUsage);
+ ASSERT_EQ(STATUS_OK, clientBuffer->initCheck());
- void* clientBufData =
- mGralloc->lock(clientBufferHandle.get(), clientUsage, layer->mAccessRegion, -1);
+ void* clientBufData = nullptr;
+ ASSERT_EQ(STATUS_OK, clientBuffer->lock(clientUsage, &clientBufData));
ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight,
- clientStride, clientBufData,
+ clientBuffer->stride, clientBufData,
clientFormat, expectedColors));
- int clientFence = mGralloc->unlock(clientBufferHandle.get());
- if (clientFence != -1) {
- sync_wait(clientFence, -1);
- close(clientFence);
- }
+ clientBuffer->unlock();
- mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
+ mWriter->setClientTarget(0, clientBuffer->handle, -1, clientDataspace,
std::vector<IComposerClient::Rect>(1, damage));
layer->setToClientComposition(mWriter);
@@ -531,12 +522,12 @@
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
auto deviceLayer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+ mComposerClient, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
mDisplayHeight / 2, PixelFormat::RGBA_8888);
std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth *
deviceLayer->mHeight);
@@ -573,8 +564,8 @@
}
auto clientLayer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, clientWidth,
- clientHeight, PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
+ mComposerClient, *mTestRenderEngine, mPrimaryDisplay, clientWidth, clientHeight,
+ PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
clientLayer->setDisplayFrame(clientFrame);
clientLayer->setZOrder(0);
@@ -590,27 +581,22 @@
}
// create client target buffer
ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
- uint32_t clientStride;
- NativeHandleWrapper clientBufferHandle =
- mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount,
- clientFormat, clientUsage, /*import*/ true, &clientStride);
- ASSERT_NE(nullptr, clientBufferHandle.get());
+ sp<GraphicBuffer> clientBuffer =
+ sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight, (int32_t)clientFormat,
+ clientLayer->mLayerCount, clientUsage);
+ ASSERT_EQ(STATUS_OK, clientBuffer->initCheck());
- void* clientBufData = mGralloc->lock(clientBufferHandle.get(), clientUsage,
- {0, 0, mDisplayWidth, mDisplayHeight}, -1);
+ void* clientBufData = nullptr;
+ ASSERT_EQ(STATUS_OK, clientBuffer->lock(clientUsage, &clientBufData));
std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
ReadbackHelper::fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight,
- clientStride, clientBufData,
+ clientBuffer->stride, clientBufData,
clientFormat, clientColors));
- int clientFence = mGralloc->unlock(clientBufferHandle.get());
- if (clientFence != -1) {
- sync_wait(clientFence, -1);
- close(clientFence);
- }
+ EXPECT_EQ(STATUS_OK, clientBuffer->unlock());
- mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
+ mWriter->setClientTarget(0, clientBuffer->handle, -1, clientDataspace,
std::vector<IComposerClient::Rect>(1, clientFrame));
clientLayer->setToClientComposition(mWriter);
mWriter->validateDisplay();
@@ -655,9 +641,9 @@
std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
- auto layer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
- mDisplayHeight, PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+ mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -665,7 +651,7 @@
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -742,7 +728,7 @@
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -803,9 +789,9 @@
{0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
BLUE);
- auto layer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
- mDisplayHeight, PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+ mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -819,7 +805,7 @@
// update expected colors to match crop
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
{0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(layers);
@@ -886,7 +872,7 @@
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -955,9 +941,9 @@
backgroundLayer->setZOrder(0);
backgroundLayer->setColor(mBackgroundColor);
- auto layer = std::make_shared<TestBufferLayer>(
- mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
- mDisplayHeight, PixelFormat::RGBA_8888);
+ auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+ mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
layer->setZOrder(10);
layer->setDataspace(Dataspace::UNKNOWN, mWriter);
@@ -1043,7 +1029,7 @@
setUpLayers(IComposerClient::BlendMode::NONE);
setExpectedColors(expectedColors);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
@@ -1102,7 +1088,7 @@
setUpLayers(IComposerClient::BlendMode::COVERAGE);
setExpectedColors(expectedColors);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
@@ -1153,7 +1139,7 @@
setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED);
setExpectedColors(expectedColors);
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
@@ -1193,7 +1179,7 @@
IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength,
mSideLength};
- mLayer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, *mTestRenderEngine,
+ mLayer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
mPrimaryDisplay, mSideLength, mSideLength,
PixelFormat::RGBA_8888);
mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
@@ -1236,7 +1222,7 @@
GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
return;
}
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::FLIP_H);
@@ -1291,7 +1277,7 @@
GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
return;
}
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -1346,7 +1332,7 @@
GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
return;
}
- ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+ ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
mDisplayHeight, mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 13ae089..2bd287b 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -18,14 +18,13 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
#include <composer-vts/2.2/ComposerVts.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
namespace android {
namespace hardware {
@@ -40,7 +39,6 @@
using common::V1_1::Dataspace;
using common::V1_1::PixelFormat;
using common::V1_1::RenderIntent;
-using V2_1::vts::NativeHandleWrapper;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
@@ -141,8 +139,6 @@
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<V2_1::vts::TestCommandReader>();
}
@@ -152,20 +148,10 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- NativeHandleWrapper allocate() {
- uint64_t usage =
- static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
- return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
- PixelFormat::RGBA_8888, usage);
- }
-
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
-
- private:
- std::unique_ptr<Gralloc> mGralloc;
};
/**
@@ -437,13 +423,11 @@
uint64_t usage =
static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
- std::unique_ptr<Gralloc> gralloc;
- std::unique_ptr<NativeHandleWrapper> buffer;
- ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
- ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
- gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
+ sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight,
+ (int32_t)mReadbackPixelFormat, 1, usage);
+ ASSERT_EQ(STATUS_OK, buffer->initCheck());
- mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->get(), -1);
+ mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->handle, -1);
}
/**
@@ -460,14 +444,12 @@
uint64_t usage =
static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
- std::unique_ptr<Gralloc> gralloc;
- std::unique_ptr<NativeHandleWrapper> buffer;
- ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
- ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
- gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
+ sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight,
+ (int32_t)mReadbackPixelFormat, 1, usage);
+ ASSERT_EQ(STATUS_OK, buffer->initCheck());
- Error error =
- mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->get(), nullptr);
+ Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->handle,
+ nullptr);
ASSERT_EQ(Error::BAD_DISPLAY, error);
}
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
index b372804..99429db 100644
--- a/graphics/composer/2.3/utils/vts/Android.bp
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -26,7 +26,6 @@
cc_library_static {
name: "android.hardware.graphics.composer@2.3-vts",
defaults: [
- "android.hardware.graphics.allocator-ndk_static",
"hidl_defaults",
],
srcs: [
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 13f2b11..0d3c27d 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -27,7 +27,6 @@
name: "VtsHalGraphicsComposerV2_3TargetTest",
defaults: [
"VtsHalTargetTestDefaults",
- "android.hardware.graphics.allocator-ndk_static",
],
tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
@@ -40,25 +39,14 @@
"libhidlbase",
"libsync",
"android.hardware.common-V2-ndk",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
],
static_libs: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.2-vts",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.3-vts",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@2.1-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
],
header_libs: [
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index ecfe66c..c072ef0 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -21,7 +21,6 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
@@ -29,7 +28,6 @@
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
namespace android {
namespace hardware {
@@ -43,7 +41,6 @@
using common::V1_2::ColorMode;
using common::V1_2::Dataspace;
using common::V1_2::PixelFormat;
-using V2_2::vts::Gralloc;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
@@ -128,8 +125,6 @@
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<V2_1::vts::TestCommandReader>();
}
@@ -143,9 +138,6 @@
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
-
- private:
- std::unique_ptr<Gralloc> mGralloc;
};
/**
diff --git a/graphics/composer/2.4/utils/vts/Android.bp b/graphics/composer/2.4/utils/vts/Android.bp
index d2b2ffa..c39b5eb1 100644
--- a/graphics/composer/2.4/utils/vts/Android.bp
+++ b/graphics/composer/2.4/utils/vts/Android.bp
@@ -26,7 +26,6 @@
cc_library_static {
name: "android.hardware.graphics.composer@2.4-vts",
defaults: [
- "android.hardware.graphics.allocator-ndk_static",
"hidl_defaults",
],
srcs: [
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index b4ab259..52624b4 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -27,7 +27,6 @@
name: "VtsHalGraphicsComposerV2_4TargetTest",
defaults: [
"VtsHalTargetTestDefaults",
- "android.hardware.graphics.allocator-ndk_static",
],
tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
@@ -38,16 +37,10 @@
"libbinder_ndk",
"libfmq",
"libsync",
+ "libui",
"android.hardware.common-V2-ndk",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
],
static_libs: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
@@ -56,10 +49,6 @@
"android.hardware.graphics.composer@2.3-vts",
"android.hardware.graphics.composer@2.4",
"android.hardware.graphics.composer@2.4-vts",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@2.1-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
],
header_libs: [
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index dac46f9..7ae917b 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -22,7 +22,6 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
#include <composer-vts/2.4/ComposerVts.h>
#include <composer-vts/2.4/GraphicsComposerCallback.h>
@@ -30,9 +29,7 @@
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
#include <utils/Timers.h>
namespace android {
@@ -51,9 +48,7 @@
using common::V1_2::Dataspace;
using common::V1_2::PixelFormat;
using V2_1::Layer;
-using V2_1::vts::NativeHandleWrapper;
using V2_2::Transform;
-using V2_2::vts::Gralloc;
using ContentType = IComposerClient::ContentType;
using DisplayCapability = IComposerClient::DisplayCapability;
@@ -103,8 +98,6 @@
}
mComposerCallback->setVsyncAllowed(false);
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
}
@@ -157,12 +150,15 @@
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- NativeHandleWrapper allocate(int32_t width, int32_t height) {
- return mGralloc->allocate(
- width, height, /*layerCount*/ 1,
- static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
+ sp<GraphicBuffer> allocate(int32_t width, int32_t height) {
+ auto result = sp<GraphicBuffer>::make(
+ width, height, static_cast<int32_t>(PixelFormat::RGBA_8888), /*layerCount*/ 1,
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
BufferUsage::COMPOSER_OVERLAY));
+ if (result->initCheck() != STATUS_OK) {
+ return nullptr;
+ }
+ return result;
}
struct TestParameters {
@@ -256,7 +252,6 @@
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
sp<GraphicsComposerCallback> mComposerCallback;
- std::unique_ptr<Gralloc> mGralloc;
};
TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
@@ -458,7 +453,7 @@
mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
mWriter->setLayerSurfaceDamage(
std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
- mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerBuffer(0, handle->handle, -1);
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
mWriter->validateDisplay();
@@ -476,7 +471,7 @@
ASSERT_NE(nullptr, handle.get());
mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle.get(), -1);
+ mWriter->setLayerBuffer(0, handle->handle, -1);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
mWriter->validateDisplay();
execute();
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 88abb73..c105ad4 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -54,6 +54,9 @@
enabled: true,
},
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
index 662240e..cce35e7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -45,4 +45,5 @@
boolean acceptDisplayChanges;
boolean presentDisplay;
boolean presentOrValidateDisplay;
+ int frameIntervalNs;
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl
index 908842a..040afd7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl
@@ -40,6 +40,7 @@
@nullable android.hardware.graphics.composer3.DisplayConfiguration.Dpi dpi;
int configGroup;
int vsyncPeriod;
+ @nullable android.hardware.graphics.composer3.VrrConfig vrrConfig;
parcelable Dpi {
float x;
float y;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index 6d2b485..bc27cc7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -85,7 +85,8 @@
android.hardware.graphics.common.HdrConversionCapability[] getHdrConversionCapabilities();
android.hardware.graphics.common.Hdr setHdrConversionStrategy(in android.hardware.graphics.common.HdrConversionStrategy conversionStrategy);
void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
- android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display);
+ android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
+ oneway void notifyExpectedPresent(long display, in android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
const int EX_BAD_CONFIG = 1;
const int EX_BAD_DISPLAY = 2;
const int EX_BAD_LAYER = 3;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
new file mode 100644
index 0000000..bb2569f
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable VrrConfig {
+ int minFrameIntervalNs;
+ @nullable android.hardware.graphics.composer3.VrrConfig.FrameIntervalPowerHint[] frameIntervalPowerHints;
+ @nullable android.hardware.graphics.composer3.VrrConfig.NotifyExpectedPresentConfig notifyExpectedPresentConfig;
+ parcelable FrameIntervalPowerHint {
+ int frameIntervalNs;
+ int averageRefreshPeriodNs;
+ }
+ parcelable NotifyExpectedPresentConfig {
+ int notifyExpectedPresentHeadsUpNs;
+ int notifyExpectedPresentTimeoutNs;
+ }
+}
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/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
index 4f69aee..02c1389 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -174,4 +174,15 @@
* or perform a VALIDATE_DISPLAY action instead.
*/
boolean presentOrValidateDisplay;
+
+ /**
+ * If a value greater than 0 is set, it provides a hint about the next frame(s)
+ * cadence. This parameter represents the time in nanoseconds of when to expect the
+ * next frames to arrive. For example. frameIntervalNs=33333333 indicates that the
+ * cadence of the next frames is 30Hz.
+ *
+ * The implementation should take the necessary steps to present the next frames as
+ * close as possible to the cadence.
+ */
+ int frameIntervalNs;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
index b0095d2..791078d 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
@@ -15,6 +15,7 @@
*/
package android.hardware.graphics.composer3;
+import android.hardware.graphics.composer3.VrrConfig;
@VintfStability
parcelable DisplayConfiguration {
@@ -60,4 +61,10 @@
* must be signaled on a vsync boundary.
*/
int vsyncPeriod;
+
+ /**
+ * Represents the specific configurations for VRR (Variable Refresh Rate) display modes.
+ * Non-VRR modes should set this to null.
+ */
+ @nullable VrrConfig vrrConfig;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index cb4b9fb..725c947 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -22,6 +22,7 @@
import android.hardware.graphics.common.HdrConversionStrategy;
import android.hardware.graphics.common.Transform;
import android.hardware.graphics.composer3.ClientTargetProperty;
+import android.hardware.graphics.composer3.ClockMonotonicTimestamp;
import android.hardware.graphics.composer3.ColorMode;
import android.hardware.graphics.composer3.CommandResultPayload;
import android.hardware.graphics.composer3.ContentType;
@@ -878,8 +879,38 @@
* getDisplayConfigs should return at least one config.
*
* @param display is the display for which the configurations are requested.
+ * @param maxFrameIntervalNs refers to the largest frameInterval to be set for
+ * VrrConfig.frameIntervalPowerHints in nanoseconds
*
* @see getDisplayConfigs
*/
- DisplayConfiguration[] getDisplayConfigurations(long display);
+ DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
+
+ /**
+ * Provides an early hint for a frame that is likely to be presented.
+ * This is used for the implementation to take the necessary steps to ensure that
+ * the next frame(s) could be presented as close as possible to the expectedPresentTime and
+ * according to the frameIntervalNs cadence.
+ * See DisplayCommand.expectedPresentTime and DisplayCommand.frameIntervalNs.
+ *
+ * The framework will call this function based on the parameters specified in
+ * DisplayConfiguration.VrrConfig:
+ * - notifyExpectedPresentTimeoutNs specifies the idle time from the previous present command
+ * where the framework must send the early hint for the next frame.
+ * - notifyExpectedPresentHeadsUpNs specifies minimal time that framework must send
+ * the early hint before the next frame.
+ *
+ * The framework can omit calling this API when the next present command matches
+ * the cadence of the previous present command frameIntervalNs.
+ *
+ * If DisplayConfiguration.notifyExpectedPresentConfig is null, this function will never be
+ * called.
+ *
+ * @param display is the display for which the notifyExpectedPresent is called.
+ * @param expectedPresentTime is the expectedPresentTime that will be provided in the next
+ * present command
+ * @param frameIntervalNs is a hint about the cadence of the next frames in nanoseconds.
+ */
+ oneway void notifyExpectedPresent(
+ long display, in ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
new file mode 100644
index 0000000..3b241ba
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable VrrConfig {
+ /**
+ * The minimal time (in nanoseconds) that needs to pass between the previously presented frame
+ * and when the next frame can be presented.
+ */
+ int minFrameIntervalNs;
+
+ /**
+ * An optional mapping between frame intervals, and the physical display refresh period on
+ * average. This provides useful information to the framework when picking a specific frame rate
+ * (which is a divisor of the vsync rate) about the real display refresh rate, which could be
+ * used for power optimizations. The implementation should populate this map for frame rates
+ * that requires the display to run at a higher refresh rate due to self refresh frames. The
+ * lowest frame rate provided should be according to the parameter `maxFrameIntervalNs`
+ * specified in IComposerClient.getDisplayConfigurations, as the framework would generally not
+ * try to run at a lower frame rate.
+ */
+ parcelable FrameIntervalPowerHint {
+ int frameIntervalNs;
+ int averageRefreshPeriodNs;
+ }
+ @nullable FrameIntervalPowerHint[] frameIntervalPowerHints;
+
+ parcelable NotifyExpectedPresentConfig {
+ /**
+ * The minimal time in nanoseconds that IComposerClient.notifyExpectedPresent needs to be
+ * called ahead of an expectedPresentTime provided on a presentDisplay command.
+ */
+ int notifyExpectedPresentHeadsUpNs;
+
+ /**
+ * The time in nanoseconds that represents a timeout from the previous presentDisplay, which
+ * after this point the display needs a call to IComposerClient.notifyExpectedPresent before
+ * sending the next frame. If set to 0, there is no need to call
+ * IComposerClient.notifyExpectedPresent for timeout.
+ */
+ int notifyExpectedPresentTimeoutNs;
+ }
+
+ /**
+ * Parameters for when to call IComposerClient.notifyExpectedPresent.
+ *
+ * When set to null, the framework will not call IComposerClient.notifyExpectedPresent.
+ */
+ @nullable NotifyExpectedPresentConfig notifyExpectedPresentConfig;
+}
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 88b5de4..e60e1a7 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -55,13 +55,6 @@
"libhidlbase",
"libprocessgroup",
"libtinyxml2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
"libvndksupport",
],
header_libs: [
@@ -71,13 +64,6 @@
"android.hardware.graphics.common@1.2",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.mapper@2.0-vts",
- "android.hardware.graphics.mapper@2.1-vts",
- "android.hardware.graphics.mapper@3.0-vts",
- "android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
"libarect",
"libbase",
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index ee9f0d5..d5602c1 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -20,7 +20,6 @@
#include <android-base/unique_fd.h>
#include <android/hardware/graphics/composer3/ComposerClientReader.h>
#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
-#include <mapper-vts/2.1/MapperVts.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
#include <memory>
@@ -32,7 +31,6 @@
using ::android::renderengine::LayerSettings;
using common::Dataspace;
using common::PixelFormat;
-using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
static const Color BLACK = {0.0f, 0.0f, 0.0f, 1.0f};
static const Color RED = {1.0f, 0.0f, 0.0f, 1.0f};
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index 66779c8..19e8a9b 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -19,7 +19,6 @@
namespace aidl::android::hardware::graphics::composer3::vts {
-using ::android::hardware::graphics::mapper::V2_1::IMapper;
using ::android::renderengine::DisplaySettings;
using ::android::renderengine::LayerSettings;
using ::android::renderengine::RenderEngineCreationArgs;
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.h b/graphics/composer/aidl/vts/RenderEngineVts.h
index 43d3a42..612f0ea 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.h
+++ b/graphics/composer/aidl/vts/RenderEngineVts.h
@@ -15,13 +15,11 @@
*/
#pragma once
-#include <mapper-vts/2.1/MapperVts.h>
#include <math/half.h>
#include <math/vec3.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -29,7 +27,6 @@
namespace aidl::android::hardware::graphics::composer3::vts {
-using ::android::hardware::graphics::mapper::V2_1::IMapper;
using ::android::renderengine::DisplaySettings;
using ::android::renderengine::ExternalTexture;
using ::android::renderengine::RenderEngineCreationArgs;
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index bf42d88..11b995e 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -312,7 +312,14 @@
std::pair<ScopedAStatus, std::vector<DisplayConfiguration>>
VtsComposerClient::getDisplayConfigurations(int64_t display) {
std::vector<DisplayConfiguration> outConfigs;
- return {mComposerClient->getDisplayConfigurations(display, &outConfigs), outConfigs};
+ return {mComposerClient->getDisplayConfigurations(display, kMaxFrameIntervalNs, &outConfigs),
+ outConfigs};
+}
+
+ScopedAStatus VtsComposerClient::notifyExpectedPresent(int64_t display,
+ ClockMonotonicTimestamp expectedPresentTime,
+ int frameIntervalNs) {
+ return mComposerClient->notifyExpectedPresent(display, expectedPresentTime, frameIntervalNs);
}
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index 1add23c..20dc733 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -145,6 +145,10 @@
std::pair<ScopedAStatus, std::vector<DisplayConfiguration>> getDisplayConfigurations(
int64_t display);
+ ScopedAStatus notifyExpectedPresent(int64_t display,
+ ClockMonotonicTimestamp expectedPresentTime,
+ int frameIntervalNs);
+
std::pair<ScopedAStatus, int32_t> getDisplayVsyncPeriod(int64_t display);
ScopedAStatus setAutoLowLatencyMode(int64_t display, bool isEnabled);
@@ -192,6 +196,8 @@
std::vector<RefreshRateChangedDebugData> takeListOfRefreshRateChangedDebugData();
+ static constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20fps
+
private:
void addDisplayConfigs(VtsDisplay*, const std::vector<DisplayConfiguration>&);
ScopedAStatus addDisplayConfigLegacy(VtsDisplay*, int32_t config);
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/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index d559213..90944d5 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1234,6 +1234,43 @@
EXPECT_NE(-1, displayConfig.dpi->x);
EXPECT_NE(-1, displayConfig.dpi->y);
}
+ if (displayConfig.vrrConfig) {
+ const auto& vrrConfig = *displayConfig.vrrConfig;
+ EXPECT_GE(vrrConfig.minFrameIntervalNs, displayConfig.vsyncPeriod);
+
+ const auto verifyFrameIntervalIsDivisorOfVsync = [&](int32_t frameIntervalNs) {
+ constexpr auto kThreshold = 0.05f; // 5%
+ const auto ratio =
+ static_cast<float>(frameIntervalNs) / displayConfig.vsyncPeriod;
+ return ratio - std::round(ratio) <= kThreshold;
+ };
+
+ EXPECT_TRUE(verifyFrameIntervalIsDivisorOfVsync(vrrConfig.minFrameIntervalNs));
+
+ if (vrrConfig.frameIntervalPowerHints) {
+ const auto& frameIntervalPowerHints = *vrrConfig.frameIntervalPowerHints;
+ EXPECT_FALSE(frameIntervalPowerHints.empty());
+
+ const auto minFrameInterval = *min_element(frameIntervalPowerHints.cbegin(),
+ frameIntervalPowerHints.cend());
+ EXPECT_LE(minFrameInterval->frameIntervalNs,
+ VtsComposerClient::kMaxFrameIntervalNs);
+
+ EXPECT_TRUE(std::all_of(frameIntervalPowerHints.cbegin(),
+ frameIntervalPowerHints.cend(),
+ [&](const auto& frameIntervalPowerHint) {
+ return verifyFrameIntervalIsDivisorOfVsync(
+ frameIntervalPowerHint->frameIntervalNs);
+ }));
+ }
+
+ if (vrrConfig.notifyExpectedPresentConfig) {
+ const auto& notifyExpectedPresentConfig =
+ *vrrConfig.notifyExpectedPresentConfig;
+ EXPECT_GT(0, notifyExpectedPresentConfig.notifyExpectedPresentHeadsUpNs);
+ EXPECT_GE(0, notifyExpectedPresentConfig.notifyExpectedPresentTimeoutNs);
+ }
+ }
}
}
}
@@ -1312,6 +1349,17 @@
}
}
+// TODO(b/291792736) Add detailed VTS test cases for NotifyExpectedPresent
+TEST_P(GraphicsComposerAidlV3Test, NotifyExpectedPresent) {
+ for (const auto& display : mDisplays) {
+ EXPECT_TRUE(mComposerClient
+ ->notifyExpectedPresent(display.getDisplayId(),
+ ClockMonotonicTimestamp{0},
+ std::chrono::nanoseconds{8ms}.count())
+ .isOk());
+ }
+}
+
// Tests for Command.
class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
protected:
diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h
index 54b2740..fc3066e 100644
--- a/health/utils/libhealthloop/include/health/HealthLoop.h
+++ b/health/utils/libhealthloop/include/health/HealthLoop.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <functional>
#include <memory>
#include <mutex>
#include <vector>
diff --git a/radio/1.2/vts/functional/AndroidTest.xml b/radio/1.2/vts/functional/AndroidTest.xml
index e25249b..4a0be56 100644
--- a/radio/1.2/vts/functional/AndroidTest.xml
+++ b/radio/1.2/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_2TargetTest" />
</test>
</configuration>
diff --git a/radio/1.3/vts/functional/AndroidTest.xml b/radio/1.3/vts/functional/AndroidTest.xml
index 44b7419..a2cd791 100644
--- a/radio/1.3/vts/functional/AndroidTest.xml
+++ b/radio/1.3/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_3TargetTest" />
</test>
</configuration>
diff --git a/radio/1.4/vts/functional/AndroidTest.xml b/radio/1.4/vts/functional/AndroidTest.xml
index d0843e6..54051ed 100644
--- a/radio/1.4/vts/functional/AndroidTest.xml
+++ b/radio/1.4/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_4TargetTest" />
</test>
</configuration>
diff --git a/radio/1.5/vts/functional/AndroidTest.xml b/radio/1.5/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..d3617c8
--- /dev/null
+++ b/radio/1.5/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalRadioV1_5TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+
+ <!-- TODO: b/154638140, b/152655658: bad interactions -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalRadioV1_5TargetTest->/data/local/tmp/VtsHalRadioV1_5TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+ <option name="module-name" value="VtsHalRadioV1_5TargetTest" />
+ </test>
+</configuration>
diff --git a/radio/1.6/vts/functional/AndroidTest.xml b/radio/1.6/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..c3ecdb0
--- /dev/null
+++ b/radio/1.6/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalRadioV1_6TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+
+ <!-- TODO: b/154638140, b/152655658: bad interactions -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalRadioV1_6TargetTest->/data/local/tmp/VtsHalRadioV1_6TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+ <option name="module-name" value="VtsHalRadioV1_6TargetTest" />
+ </test>
+</configuration>
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/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp
index 3bdd8b6..ca3eb14 100644
--- a/sensors/aidl/default/Sensor.cpp
+++ b/sensors/aidl/default/Sensor.cpp
@@ -268,7 +268,7 @@
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
- mSensorInfo.flags = 0;
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
};
void MagnetometerSensor::readEventPayload(EventPayload& payload) {
@@ -343,7 +343,7 @@
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
- mSensorInfo.flags = 0;
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
};
void GyroSensor::readEventPayload(EventPayload& payload) {
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index 618acbb..456aee7 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -921,9 +921,15 @@
continue;
}
+ // Skip sensors with no events
+ const std::vector<Event> events = callback.getEvents(sensor.sensorHandle);
+ if (events.empty()) {
+ continue;
+ }
+
// Ensure that the first event received is not stale by ensuring that its timestamp is
// sufficiently different from the previous event
- const Event newEvent = callback.getEvents(sensor.sensorHandle).front();
+ const Event newEvent = events.front();
std::chrono::milliseconds delta =
duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds(
newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index aa6e881..b381580 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -806,9 +806,15 @@
continue;
}
+ // Skip sensors with no events
+ const std::vector<EventType> events = callback.getEvents(sensor.sensorHandle);
+ if (events.empty()) {
+ continue;
+ }
+
// Ensure that the first event received is not stale by ensuring that its timestamp is
// sufficiently different from the previous event
- const EventType newEvent = callback.getEvents(sensor.sensorHandle).front();
+ const EventType newEvent = events.front();
milliseconds delta = duration_cast<milliseconds>(
nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
milliseconds sensorMinDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index 049ec73..00943fd 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -18,7 +18,6 @@
#include <android-base/logging.h>
#include <android/hardware/vr/1.0/IVr.h>
#include <gtest/gtest.h>
-#include <hardware/vr.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <log/log.h>
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..754d467
--- /dev/null
+++ b/weaver/vts/VtsHalWeaverTargetTest.cpp
@@ -0,0 +1,427 @@
+/*
+ * 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);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverTest);
+
+// 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();
+}