Merge "Remove R FCM HALs and older kernels" into main
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 52ae936..dc411ff 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -186,6 +186,12 @@
template <typename E, typename U = std::underlying_type_t<E>,
typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr bool areAllBitPositionFlagsSet(U mask, std::initializer_list<E> flags) {
+ return (mask & makeBitPositionFlagMask<E>(flags)) == makeBitPositionFlagMask<E>(flags);
+}
+
+template <typename E, typename U = std::underlying_type_t<E>,
+ typename = std::enable_if_t<is_bit_position_enum<E>::value>>
constexpr bool isAnyBitPositionFlagSet(U mask, std::initializer_list<E> flags) {
return (mask & makeBitPositionFlagMask<E>(flags)) != 0;
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 73d7626..14082eb 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -77,8 +77,10 @@
"r_submix/ModuleRemoteSubmix.cpp",
"r_submix/SubmixRoute.cpp",
"r_submix/StreamRemoteSubmix.cpp",
+ "stub/ApeHeader.cpp",
"stub/DriverStubImpl.cpp",
"stub/ModuleStub.cpp",
+ "stub/StreamOffloadStub.cpp",
"stub/StreamStub.cpp",
"usb/ModuleUsb.cpp",
"usb/StreamUsb.cpp",
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index f9fa799..077d80b 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -211,9 +211,9 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
const auto& flags = portConfigIt->flags.value();
- StreamContext::DebugParameters params{
- mDebug.streamTransientStateDelayMs, mVendorDebug.forceTransientBurst,
- mVendorDebug.forceSynchronousDrain, mVendorDebug.forceDrainToDraining};
+ StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
+ mVendorDebug.forceTransientBurst,
+ mVendorDebug.forceSynchronousDrain};
std::unique_ptr<StreamContext::DataMQ> dataMQ = nullptr;
std::shared_ptr<IStreamCallback> streamAsyncCallback = nullptr;
std::shared_ptr<ISoundDose> soundDose;
@@ -1546,7 +1546,6 @@
const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst";
const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain";
-const std::string Module::VendorDebug::kForceDrainToDrainingName = "aosp.forceDrainToDraining";
ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
std::vector<VendorParameter>* _aidl_return) {
@@ -1561,10 +1560,6 @@
VendorParameter forceSynchronousDrain{.id = id};
forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain});
_aidl_return->push_back(std::move(forceSynchronousDrain));
- } else if (id == VendorDebug::kForceDrainToDrainingName) {
- VendorParameter forceDrainToDraining{.id = id};
- forceDrainToDraining.ext.setParcelable(Boolean{mVendorDebug.forceDrainToDraining});
- _aidl_return->push_back(std::move(forceDrainToDraining));
} else {
allParametersKnown = false;
LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\"";
@@ -1605,10 +1600,6 @@
if (!extractParameter<Boolean>(p, &mVendorDebug.forceSynchronousDrain)) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- } else if (p.id == VendorDebug::kForceDrainToDrainingName) {
- if (!extractParameter<Boolean>(p, &mVendorDebug.forceDrainToDraining)) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- }
} else {
allParametersKnown = false;
LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << p.id
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
index 3da6d48..2a1dba9 100644
--- a/audio/aidl/default/ModulePrimary.cpp
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -21,12 +21,16 @@
#include <android-base/logging.h>
#include "core-impl/ModulePrimary.h"
+#include "core-impl/StreamOffloadStub.h"
#include "core-impl/StreamPrimary.h"
#include "core-impl/Telephony.h"
+using aidl::android::hardware::audio::common::areAllBitPositionFlagsSet;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::MicrophoneInfo;
@@ -43,6 +47,17 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus ModulePrimary::calculateBufferSizeFrames(
+ const ::aidl::android::media::audio::common::AudioFormatDescription& format,
+ int32_t latencyMs, int32_t sampleRateHz, int32_t* bufferSizeFrames) {
+ if (format.type != ::aidl::android::media::audio::common::AudioFormatType::PCM &&
+ StreamOffloadStub::getSupportedEncodings().count(format.encoding)) {
+ *bufferSizeFrames = sampleRateHz / 2; // 1/2 of a second.
+ return ndk::ScopedAStatus::ok();
+ }
+ return Module::calculateBufferSizeFrames(format, latencyMs, sampleRateHz, bufferSizeFrames);
+}
+
ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
@@ -54,8 +69,18 @@
ndk::ScopedAStatus ModulePrimary::createOutputStream(
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
- return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
- offloadInfo);
+ if (!areAllBitPositionFlagsSet(
+ context.getFlags().get<AudioIoFlags::output>(),
+ {AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::NON_BLOCKING})) {
+ return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
+ offloadInfo);
+ } else {
+ // "Stub" is used because there is no actual decoder. The stream just
+ // extracts the clip duration from the media file header and simulates
+ // playback over time.
+ return createStreamInstance<StreamOutOffloadStub>(result, std::move(context),
+ sourceMetadata, offloadInfo);
+ }
}
int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) {
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index c138095..c6c1b5d 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -142,12 +142,16 @@
", size in bytes: " + std::to_string(mDataBufferSize);
}
}
- if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
+ if (::android::status_t status = mDriver->init(this /*DriverCallbackInterface*/);
+ status != STATUS_OK) {
return "Failed to initialize the driver: " + std::to_string(status);
}
return "";
}
+void StreamWorkerCommonLogic::onBufferStateChange(size_t /*bufferFramesLeft*/) {}
+void StreamWorkerCommonLogic::onClipStateChange(size_t /*clipFramesLeft*/, bool /*hasNextClip*/) {}
+
void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply,
bool isConnected) const {
static const StreamDescriptor::Position kUnknownPosition = {
@@ -381,48 +385,60 @@
const std::string StreamOutWorkerLogic::kThreadName = "writer";
-StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
- if (mState == StreamDescriptor::State::DRAINING && mContext->getForceDrainToDraining() &&
- mOnDrainReadyStatus == OnDrainReadyStatus::UNSENT) {
+void StreamOutWorkerLogic::onBufferStateChange(size_t bufferFramesLeft) {
+ const StreamDescriptor::State state = mState;
+ LOG(DEBUG) << __func__ << ": state: " << toString(state)
+ << ", bufferFramesLeft: " << bufferFramesLeft;
+ if (state == StreamDescriptor::State::TRANSFERRING) {
+ mState = StreamDescriptor::State::ACTIVE;
std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
if (asyncCallback != nullptr) {
+ ndk::ScopedAStatus status = asyncCallback->onTransferReady();
+ if (!status.isOk()) {
+ LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
+ }
+ }
+ }
+}
+
+void StreamOutWorkerLogic::onClipStateChange(size_t clipFramesLeft, bool hasNextClip) {
+ const DrainState drainState = mDrainState;
+ std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
+ LOG(DEBUG) << __func__ << ": drainState: " << drainState << "; clipFramesLeft "
+ << clipFramesLeft << "; hasNextClip? " << hasNextClip << "; asyncCallback? "
+ << (asyncCallback != nullptr);
+ if (drainState != DrainState::NONE && clipFramesLeft == 0) {
+ mState =
+ hasNextClip ? StreamDescriptor::State::TRANSFERRING : StreamDescriptor::State::IDLE;
+ mDrainState = DrainState::NONE;
+ if (drainState == DrainState::ALL && asyncCallback != nullptr) {
+ LOG(DEBUG) << __func__ << ": sending onDrainReady";
ndk::ScopedAStatus status = asyncCallback->onDrainReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
}
- // This sets the timeout for moving into IDLE on next iterations.
- switchToTransientState(StreamDescriptor::State::DRAINING);
- mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
}
- } else if (mState == StreamDescriptor::State::DRAINING ||
- mState == StreamDescriptor::State::TRANSFERRING) {
+ } else if (drainState == DrainState::EN && clipFramesLeft > 0) {
+ // The stream state does not change, it is still draining.
+ mDrainState = DrainState::EN_SENT;
+ if (asyncCallback != nullptr) {
+ LOG(DEBUG) << __func__ << ": sending onDrainReady";
+ ndk::ScopedAStatus status = asyncCallback->onDrainReady();
+ if (!status.isOk()) {
+ LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
+ }
+ }
+ }
+}
+
+StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
+ // Non-blocking mode is handled within 'onClipStateChange'
+ if (std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
+ mState == StreamDescriptor::State::DRAINING && asyncCallback == nullptr) {
if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - mTransientStateStart);
stateDurationMs >= mTransientStateDelayMs) {
- std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
- if (asyncCallback == nullptr) {
- // In blocking mode, mState can only be DRAINING.
- mState = StreamDescriptor::State::IDLE;
- } else {
- // In a real implementation, the driver should notify the HAL about
- // drain or transfer completion. In the stub, we switch unconditionally.
- if (mState == StreamDescriptor::State::DRAINING) {
- mState = StreamDescriptor::State::IDLE;
- if (mOnDrainReadyStatus != OnDrainReadyStatus::SENT) {
- ndk::ScopedAStatus status = asyncCallback->onDrainReady();
- if (!status.isOk()) {
- LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
- }
- mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
- }
- } else {
- mState = StreamDescriptor::State::ACTIVE;
- ndk::ScopedAStatus status = asyncCallback->onTransferReady();
- if (!status.isOk()) {
- LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
- }
- }
- }
+ mState = StreamDescriptor::State::IDLE;
if (mTransientStateDelayMs.count() != 0) {
LOG(DEBUG) << __func__ << ": switched to state " << toString(mState)
<< " after a timeout";
@@ -552,10 +568,9 @@
mState = StreamDescriptor::State::IDLE;
} else {
switchToTransientState(StreamDescriptor::State::DRAINING);
- mOnDrainReadyStatus =
- mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY
- ? OnDrainReadyStatus::UNSENT
- : OnDrainReadyStatus::IGNORE;
+ mDrainState = mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY
+ ? DrainState::EN
+ : DrainState::ALL;
}
} else {
LOG(ERROR) << __func__ << ": drain failed: " << status;
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 210c26b..7a44cc7 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -72,7 +72,7 @@
return source;
}
-::android::status_t StreamAlsa::init() {
+::android::status_t StreamAlsa::init(DriverCallbackInterface* /*callback*/) {
return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
}
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
index 6e1a811..77ce121 100644
--- a/audio/aidl/default/bluetooth/StreamBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -70,7 +70,7 @@
cleanupWorker();
}
-::android::status_t StreamBluetooth::init() {
+::android::status_t StreamBluetooth::init(DriverCallbackInterface*) {
std::lock_guard guard(mLock);
if (mBtDeviceProxy == nullptr) {
// This is a normal situation in VTS tests.
diff --git a/audio/aidl/default/include/core-impl/DriverStubImpl.h b/audio/aidl/default/include/core-impl/DriverStubImpl.h
index 40a9fea..84f869a 100644
--- a/audio/aidl/default/include/core-impl/DriverStubImpl.h
+++ b/audio/aidl/default/include/core-impl/DriverStubImpl.h
@@ -22,9 +22,11 @@
class DriverStubImpl : virtual public DriverInterface {
public:
- explicit DriverStubImpl(const StreamContext& context);
+ explicit DriverStubImpl(const StreamContext& context)
+ : DriverStubImpl(context, 500 /*asyncSleepTimeUs*/) {}
+ DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs);
- ::android::status_t init() override;
+ ::android::status_t init(DriverCallbackInterface* callback) override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
@@ -34,12 +36,14 @@
int32_t* latencyMs) override;
void shutdown() override;
- private:
+ protected:
const size_t mBufferSizeFrames;
const size_t mFrameSizeBytes;
const int mSampleRate;
const bool mIsAsynchronous;
const bool mIsInput;
+ const int32_t mMixPortHandle;
+ const int mAsyncSleepTimeUs;
bool mIsInitialized = false; // Used for validating the state machine logic.
bool mIsStandby = true; // Used for validating the state machine logic.
int64_t mStartTimeNs = 0;
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index cbc13d1..6a43102 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -148,10 +148,8 @@
struct VendorDebug {
static const std::string kForceTransientBurstName;
static const std::string kForceSynchronousDrainName;
- static const std::string kForceDrainToDrainingName;
bool forceTransientBurst = false;
bool forceSynchronousDrain = false;
- bool forceDrainToDraining = false;
};
// ids of device ports created at runtime via 'connectExternalDevice'.
// Also stores a list of ids of mix ports with dynamic profiles that were populated from
diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h
index 82c8a03..a657dc5 100644
--- a/audio/aidl/default/include/core-impl/ModulePrimary.h
+++ b/audio/aidl/default/include/core-impl/ModulePrimary.h
@@ -28,6 +28,9 @@
protected:
ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
+ ndk::ScopedAStatus calculateBufferSizeFrames(
+ const ::aidl::android::media::audio::common::AudioFormatDescription& format,
+ int32_t latencyMs, int32_t sampleRateHz, int32_t* bufferSizeFrames) override;
ndk::ScopedAStatus createInputStream(
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 304f9b7..f0139b4 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -78,10 +78,6 @@
bool forceTransientBurst = false;
// Force the "drain" command to be synchronous, going directly to the IDLE state.
bool forceSynchronousDrain = false;
- // Force the "drain early notify" command to keep the SM in the DRAINING state
- // after sending 'onDrainReady' callback. The SM moves to IDLE after
- // 'transientStateDelayMs'.
- bool forceDrainToDraining = false;
};
StreamContext() = default;
@@ -123,7 +119,6 @@
::aidl::android::media::audio::common::AudioIoFlags getFlags() const { return mFlags; }
bool getForceTransientBurst() const { return mDebugParameters.forceTransientBurst; }
bool getForceSynchronousDrain() const { return mDebugParameters.forceSynchronousDrain; }
- bool getForceDrainToDraining() const { return mDebugParameters.forceDrainToDraining; }
size_t getFrameSize() const;
int getInternalCommandCookie() const { return mInternalCommandCookie; }
int32_t getMixPortHandle() const { return mMixPortHandle; }
@@ -146,8 +141,8 @@
// 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; }
+ int64_t advanceFrameCount(size_t increase) { return mFrameCount += increase; }
+ int64_t getFrameCount() const { return mFrameCount; }
private:
// Fields are non const to allow move assignment.
@@ -165,14 +160,30 @@
std::shared_ptr<IStreamOutEventCallback> mOutEventCallback; // Only used by output streams
std::weak_ptr<sounddose::StreamDataProcessorInterface> mStreamDataProcessor;
DebugParameters mDebugParameters;
- long mFrameCount = 0;
+ int64_t mFrameCount = 0;
+};
+
+// Driver callbacks are executed on a dedicated thread, not on the worker thread.
+struct DriverCallbackInterface {
+ virtual ~DriverCallbackInterface() = default;
+ // Both callbacks are used to notify the worker about the progress of the playback
+ // offloaded to the DSP.
+
+ // 'bufferFramesLeft' is how many *encoded* frames are left in the buffer until
+ // it depletes.
+ virtual void onBufferStateChange(size_t bufferFramesLeft) = 0;
+ // 'clipFramesLeft' is how many *decoded* frames are left until the end of the currently
+ // playing clip. '0' frames left means that the clip has ended (by itself or due
+ // to draining).
+ // 'hasNextClip' indicates whether the DSP has audio data for the next clip.
+ virtual void onClipStateChange(size_t clipFramesLeft, bool hasNextClip) = 0;
};
// This interface provides operations of the stream which are executed on the worker thread.
struct DriverInterface {
virtual ~DriverInterface() = default;
// All the methods below are called on the worker thread.
- virtual ::android::status_t init() = 0; // This function is only called once.
+ virtual ::android::status_t init(DriverCallbackInterface* callback) = 0; // Called once.
virtual ::android::status_t drain(StreamDescriptor::DrainMode mode) = 0;
virtual ::android::status_t flush() = 0;
virtual ::android::status_t pause() = 0;
@@ -194,7 +205,8 @@
virtual void shutdown() = 0; // This function is only called once.
};
-class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
+class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic,
+ public DriverCallbackInterface {
public:
bool isClosed() const { return mState == StreamContext::STATE_CLOSED; }
StreamDescriptor::State setClosed() {
@@ -214,7 +226,13 @@
mDriver(driver),
mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
pid_t getTid() const;
+
+ // ::android::hardware::audio::common::StreamLogic
std::string init() override;
+ // DriverCallbackInterface
+ void onBufferStateChange(size_t bufferFramesLeft) override;
+ void onClipStateChange(size_t clipFramesLeft, bool hasNextClip) override;
+
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
void populateReplyWrongState(StreamDescriptor::Reply* reply,
const StreamDescriptor::Command& command) const;
@@ -301,14 +319,17 @@
protected:
Status cycle() override;
+ // DriverCallbackInterface
+ void onBufferStateChange(size_t bufferFramesLeft) override;
+ void onClipStateChange(size_t clipFramesLeft, bool hasNextClip) override;
private:
bool write(size_t clientSize, StreamDescriptor::Reply* reply);
std::shared_ptr<IStreamOutEventCallback> mEventCallback;
- enum OnDrainReadyStatus : int32_t { IGNORE /*used for DRAIN_ALL*/, UNSENT, SENT };
- OnDrainReadyStatus mOnDrainReadyStatus = OnDrainReadyStatus::IGNORE;
+ enum DrainState : int32_t { NONE, ALL, EN /*early notify*/, EN_SENT };
+ std::atomic<DrainState> mDrainState = DrainState::NONE;
};
using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index 7e0f0ac..c0dcb63 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -40,7 +40,7 @@
~StreamAlsa();
// Methods of 'DriverInterface'.
- ::android::status_t init() override;
+ ::android::status_t init(DriverCallbackInterface* callback) override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
index 357a546..2bdd6b2 100644
--- a/audio/aidl/default/include/core-impl/StreamBluetooth.h
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -44,7 +44,7 @@
~StreamBluetooth();
// Methods of 'DriverInterface'.
- ::android::status_t init() override;
+ ::android::status_t init(DriverCallbackInterface*) override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
diff --git a/audio/aidl/default/include/core-impl/StreamOffloadStub.h b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
new file mode 100644
index 0000000..67abe95
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2025 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 <mutex>
+#include <set>
+#include <string>
+
+#include "core-impl/DriverStubImpl.h"
+#include "core-impl/Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+struct DspSimulatorState {
+ const std::string formatEncoding;
+ const int sampleRate;
+ const int64_t earlyNotifyFrames;
+ const int64_t bufferNotifyFrames;
+ DriverCallbackInterface* callback = nullptr; // set before starting DSP worker
+ std::mutex lock;
+ std::vector<int64_t> clipFramesLeft GUARDED_BY(lock);
+ int64_t bufferFramesLeft GUARDED_BY(lock);
+};
+
+class DspSimulatorLogic : public ::android::hardware::audio::common::StreamLogic {
+ protected:
+ explicit DspSimulatorLogic(DspSimulatorState& sharedState) : mSharedState(sharedState) {}
+ std::string init() override;
+ Status cycle() override;
+
+ private:
+ DspSimulatorState& mSharedState;
+};
+
+class DspSimulatorWorker
+ : public ::android::hardware::audio::common::StreamWorker<DspSimulatorLogic> {
+ public:
+ explicit DspSimulatorWorker(DspSimulatorState& sharedState)
+ : ::android::hardware::audio::common::StreamWorker<DspSimulatorLogic>(sharedState) {}
+};
+
+class DriverOffloadStubImpl : public DriverStubImpl {
+ public:
+ DriverOffloadStubImpl(const StreamContext& context);
+ ::android::status_t init(DriverCallbackInterface* callback) override;
+ ::android::status_t drain(StreamDescriptor::DrainMode drainMode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
+ ::android::status_t start() override;
+ ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+ int32_t* latencyMs) override;
+ void shutdown() override;
+
+ private:
+ ::android::status_t startWorkerIfNeeded();
+
+ DspSimulatorState mState;
+ DspSimulatorWorker mDspWorker;
+ bool mDspWorkerStarted = false;
+};
+
+class StreamOffloadStub : public StreamCommonImpl, public DriverOffloadStubImpl {
+ public:
+ static const std::set<std::string>& getSupportedEncodings();
+
+ StreamOffloadStub(StreamContext* context, const Metadata& metadata);
+ ~StreamOffloadStub();
+};
+
+class StreamOutOffloadStub final : public StreamOut, public StreamOffloadStub {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamOutOffloadStub(
+ 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/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
index 4f19a46..06f8bc3 100644
--- a/audio/aidl/default/include/core-impl/StreamPrimary.h
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -32,7 +32,7 @@
StreamPrimary(StreamContext* context, const Metadata& metadata);
// Methods of 'DriverInterface'.
- ::android::status_t init() override;
+ ::android::status_t init(DriverCallbackInterface* callback) override;
::android::status_t drain(StreamDescriptor::DrainMode mode) override;
::android::status_t flush() override;
::android::status_t pause() override;
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index 5e52ad0..28a446a 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -32,7 +32,7 @@
~StreamRemoteSubmix();
// Methods of 'DriverInterface'.
- ::android::status_t init() override;
+ ::android::status_t init(DriverCallbackInterface*) override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
index 46e384e..8455680 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -46,9 +46,9 @@
context->startStreamDataProcessor();
}
-::android::status_t StreamPrimary::init() {
- RETURN_STATUS_IF_ERROR(mStubDriver.init());
- return StreamAlsa::init();
+::android::status_t StreamPrimary::init(DriverCallbackInterface* callback) {
+ RETURN_STATUS_IF_ERROR(mStubDriver.init(callback));
+ return StreamAlsa::init(callback);
}
::android::status_t StreamPrimary::drain(StreamDescriptor::DrainMode mode) {
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index f8ead16..cc3c644 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -51,7 +51,7 @@
cleanupWorker();
}
-::android::status_t StreamRemoteSubmix::init() {
+::android::status_t StreamRemoteSubmix::init(DriverCallbackInterface*) {
mCurrentRoute = SubmixRoute::findOrCreateRoute(mDeviceAddress, mStreamConfig);
if (mCurrentRoute == nullptr) {
return ::android::NO_INIT;
diff --git a/audio/aidl/default/stub/ApeHeader.cpp b/audio/aidl/default/stub/ApeHeader.cpp
new file mode 100644
index 0000000..9112377
--- /dev/null
+++ b/audio/aidl/default/stub/ApeHeader.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_OffloadStream"
+#include <android-base/logging.h>
+
+#include "ApeHeader.h"
+
+namespace aidl::android::hardware::audio::core {
+
+static constexpr uint32_t kApeSignature1 = 0x2043414d; // 'MAC ';
+static constexpr uint32_t kApeSignature2 = 0x4643414d; // 'MACF';
+static constexpr uint16_t kMinimumVersion = 3980;
+
+void* findApeHeader(void* buffer, size_t bufferSizeBytes, ApeHeader** header) {
+ auto advanceBy = [&](size_t bytes) -> void* {
+ buffer = static_cast<uint8_t*>(buffer) + bytes;
+ bufferSizeBytes -= bytes;
+ return buffer;
+ };
+
+ while (bufferSizeBytes >= sizeof(ApeDescriptor) + sizeof(ApeHeader)) {
+ ApeDescriptor* descPtr = static_cast<ApeDescriptor*>(buffer);
+ if (descPtr->signature != kApeSignature1 && descPtr->signature != kApeSignature2) {
+ advanceBy(sizeof(descPtr->signature));
+ continue;
+ }
+ if (descPtr->version < kMinimumVersion) {
+ LOG(ERROR) << __func__ << ": Unsupported APE version: " << descPtr->version
+ << ", minimum supported version: " << kMinimumVersion;
+ // Older versions only have a header, which is of the size similar to the modern header.
+ advanceBy(sizeof(ApeHeader));
+ continue;
+ }
+ if (descPtr->descriptorSizeBytes > bufferSizeBytes) {
+ LOG(ERROR) << __func__
+ << ": Invalid APE descriptor size: " << descPtr->descriptorSizeBytes
+ << ", overruns remaining buffer size: " << bufferSizeBytes;
+ advanceBy(sizeof(ApeDescriptor));
+ continue;
+ }
+ advanceBy(descPtr->descriptorSizeBytes);
+ if (sizeof(ApeHeader) > bufferSizeBytes) {
+ LOG(ERROR) << __func__ << ": APE header is incomplete, want: " << sizeof(ApeHeader)
+ << " bytes, have: " << bufferSizeBytes;
+ return nullptr;
+ }
+ *header = static_cast<ApeHeader*>(buffer);
+ return advanceBy(sizeof(ApeHeader));
+ }
+ return nullptr;
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/ApeHeader.h b/audio/aidl/default/stub/ApeHeader.h
new file mode 100644
index 0000000..df30335
--- /dev/null
+++ b/audio/aidl/default/stub/ApeHeader.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 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 <cstdint>
+
+namespace aidl::android::hardware::audio::core {
+
+// Simplified APE (Monkey Audio) header definition sufficient to figure out
+// the basic parameters of the encoded file. Only supports the "current"
+// versions of the header (>= 3980).
+
+#pragma pack(push, 4)
+
+// Only the beginning of the descriptor is needed to find the header which
+// follows the descriptor.
+struct ApeDescriptor {
+ uint32_t signature; // 'MAC ' or 'MACF'
+ uint16_t version;
+ uint16_t padding;
+ uint32_t descriptorSizeBytes;
+ uint32_t headerSizeBytes;
+};
+
+struct ApeHeader {
+ uint16_t compressionLevel;
+ uint16_t flags;
+ uint32_t blocksPerFrame; // "frames" are encoder frames, while "blocks" are audio frames
+ uint32_t lastFrameBlocks; // number of "blocks" in the last encoder "frame"
+ uint32_t totalFrames; // total number of encoder "frames"
+ uint16_t bitsPerSample;
+ uint16_t channelCount;
+ uint32_t sampleRate;
+};
+
+#pragma pack(pop)
+
+// Tries to find APE descriptor and header in the buffer. Returns the position
+// after the header or nullptr if it was not found.
+void* findApeHeader(void* buffer, size_t bufferSizeBytes, ApeHeader** header);
+
+// Clip duration in audio frames ("blocks" in the APE terminology).
+inline int64_t getApeClipDurationFrames(const ApeHeader* header) {
+ return header->totalFrames != 0
+ ? (header->totalFrames - 1) * header->blocksPerFrame + header->lastFrameBlocks
+ : 0;
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/DriverStubImpl.cpp b/audio/aidl/default/stub/DriverStubImpl.cpp
index beb0114..0d129e6 100644
--- a/audio/aidl/default/stub/DriverStubImpl.cpp
+++ b/audio/aidl/default/stub/DriverStubImpl.cpp
@@ -24,19 +24,27 @@
namespace aidl::android::hardware::audio::core {
-DriverStubImpl::DriverStubImpl(const StreamContext& context)
+DriverStubImpl::DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs)
: mBufferSizeFrames(context.getBufferSizeInFrames()),
mFrameSizeBytes(context.getFrameSize()),
mSampleRate(context.getSampleRate()),
mIsAsynchronous(!!context.getAsyncCallback()),
- mIsInput(context.isInput()) {}
+ mIsInput(context.isInput()),
+ mMixPortHandle(context.getMixPortHandle()),
+ mAsyncSleepTimeUs(asyncSleepTimeUs) {}
-::android::status_t DriverStubImpl::init() {
+#define LOG_ENTRY() \
+ LOG(DEBUG) << "[" << (mIsInput ? "in" : "out") << "|ioHandle:" << mMixPortHandle << "] " \
+ << __func__;
+
+::android::status_t DriverStubImpl::init(DriverCallbackInterface* /*callback*/) {
+ LOG_ENTRY();
mIsInitialized = true;
return ::android::OK;
}
::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -46,14 +54,15 @@
const size_t delayUs = static_cast<size_t>(
std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
usleep(delayUs);
- } else {
- usleep(500);
+ } else if (mAsyncSleepTimeUs) {
+ usleep(mAsyncSleepTimeUs);
}
}
return ::android::OK;
}
::android::status_t DriverStubImpl::flush() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -61,6 +70,7 @@
}
::android::status_t DriverStubImpl::pause() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -68,6 +78,7 @@
}
::android::status_t DriverStubImpl::standby() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -76,6 +87,7 @@
}
::android::status_t DriverStubImpl::start() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -87,6 +99,7 @@
::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t*) {
+ // No LOG_ENTRY as this is called very often.
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -95,7 +108,7 @@
}
*actualFrameCount = frameCount;
if (mIsAsynchronous) {
- usleep(500);
+ if (mAsyncSleepTimeUs) usleep(mAsyncSleepTimeUs);
} else {
mFramesSinceStart += *actualFrameCount;
const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate;
@@ -120,6 +133,7 @@
}
void DriverStubImpl::shutdown() {
+ LOG_ENTRY();
mIsInitialized = false;
}
diff --git a/audio/aidl/default/stub/StreamOffloadStub.cpp b/audio/aidl/default/stub/StreamOffloadStub.cpp
new file mode 100644
index 0000000..95cef35
--- /dev/null
+++ b/audio/aidl/default/stub/StreamOffloadStub.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_OffloadStream"
+#include <android-base/logging.h>
+#include <audio_utils/clock.h>
+#include <error/Result.h>
+#include <utils/SystemClock.h>
+
+#include "ApeHeader.h"
+#include "core-impl/StreamOffloadStub.h"
+
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+std::string DspSimulatorLogic::init() {
+ return "";
+}
+
+DspSimulatorLogic::Status DspSimulatorLogic::cycle() {
+ std::vector<std::pair<int64_t, bool>> clipNotifies;
+ // Simulate playback.
+ const int64_t timeBeginNs = ::android::uptimeNanos();
+ usleep(1000);
+ const int64_t clipFramesPlayed =
+ (::android::uptimeNanos() - timeBeginNs) * mSharedState.sampleRate / NANOS_PER_SECOND;
+ const int64_t bufferFramesConsumed = clipFramesPlayed / 2; // assume 1:2 compression ratio
+ int64_t bufferFramesLeft = 0;
+ {
+ std::lock_guard l(mSharedState.lock);
+ mSharedState.bufferFramesLeft =
+ mSharedState.bufferFramesLeft > bufferFramesConsumed
+ ? mSharedState.bufferFramesLeft - bufferFramesConsumed
+ : 0;
+ bufferFramesLeft = mSharedState.bufferFramesLeft;
+ int64_t framesPlayed = clipFramesPlayed;
+ while (framesPlayed > 0 && !mSharedState.clipFramesLeft.empty()) {
+ LOG(VERBOSE) << __func__ << ": clips: "
+ << ::android::internal::ToString(mSharedState.clipFramesLeft);
+ const bool hasNextClip = mSharedState.clipFramesLeft.size() > 1;
+ if (mSharedState.clipFramesLeft[0] > framesPlayed) {
+ mSharedState.clipFramesLeft[0] -= framesPlayed;
+ framesPlayed = 0;
+ if (mSharedState.clipFramesLeft[0] <= mSharedState.earlyNotifyFrames) {
+ clipNotifies.emplace_back(mSharedState.clipFramesLeft[0], hasNextClip);
+ }
+ } else {
+ clipNotifies.emplace_back(0 /*clipFramesLeft*/, hasNextClip);
+ framesPlayed -= mSharedState.clipFramesLeft[0];
+ mSharedState.clipFramesLeft.erase(mSharedState.clipFramesLeft.begin());
+ }
+ }
+ }
+ if (bufferFramesLeft <= mSharedState.bufferNotifyFrames) {
+ LOG(DEBUG) << __func__ << ": sending onBufferStateChange: " << bufferFramesLeft;
+ mSharedState.callback->onBufferStateChange(bufferFramesLeft);
+ }
+ for (const auto& notify : clipNotifies) {
+ LOG(DEBUG) << __func__ << ": sending onClipStateChange: " << notify.first << ", "
+ << notify.second;
+ mSharedState.callback->onClipStateChange(notify.first, notify.second);
+ }
+ return Status::CONTINUE;
+}
+
+DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
+ : DriverStubImpl(context, 0 /*asyncSleepTimeUs*/),
+ mState{context.getFormat().encoding, context.getSampleRate(),
+ 250 /*earlyNotifyMs*/ * context.getSampleRate() / MILLIS_PER_SECOND,
+ static_cast<int64_t>(context.getBufferSizeInFrames()) / 2},
+ mDspWorker(mState) {
+ LOG_IF(FATAL, !mIsAsynchronous) << "The steam must be used in asynchronous mode";
+}
+
+::android::status_t DriverOffloadStubImpl::init(DriverCallbackInterface* callback) {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::init(callback));
+ if (!StreamOffloadStub::getSupportedEncodings().count(mState.formatEncoding)) {
+ LOG(ERROR) << __func__ << ": encoded format \"" << mState.formatEncoding
+ << "\" is not supported";
+ return ::android::NO_INIT;
+ }
+ mState.callback = callback;
+ return ::android::OK;
+}
+
+::android::status_t DriverOffloadStubImpl::drain(StreamDescriptor::DrainMode drainMode) {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::drain(drainMode));
+ std::lock_guard l(mState.lock);
+ if (!mState.clipFramesLeft.empty()) {
+ // Cut playback of the current clip.
+ mState.clipFramesLeft[0] = std::min(mState.earlyNotifyFrames * 2, mState.clipFramesLeft[0]);
+ if (drainMode == StreamDescriptor::DrainMode::DRAIN_ALL) {
+ // Make sure there are no clips after the current one.
+ mState.clipFramesLeft.resize(1);
+ }
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverOffloadStubImpl::flush() {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::flush());
+ mDspWorker.pause();
+ {
+ std::lock_guard l(mState.lock);
+ mState.clipFramesLeft.clear();
+ mState.bufferFramesLeft = 0;
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverOffloadStubImpl::pause() {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::pause());
+ mDspWorker.pause();
+ return ::android::OK;
+}
+
+::android::status_t DriverOffloadStubImpl::start() {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::start());
+ RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
+ bool hasClips; // Can be start after paused draining.
+ {
+ std::lock_guard l(mState.lock);
+ hasClips = !mState.clipFramesLeft.empty();
+ LOG(DEBUG) << __func__
+ << ": clipFramesLeft: " << ::android::internal::ToString(mState.clipFramesLeft);
+ }
+ if (hasClips) {
+ mDspWorker.resume();
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverOffloadStubImpl::transfer(void* buffer, size_t frameCount,
+ size_t* actualFrameCount, int32_t* latencyMs) {
+ RETURN_STATUS_IF_ERROR(
+ DriverStubImpl::transfer(buffer, frameCount, actualFrameCount, latencyMs));
+ RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
+ // Scan the buffer for clip headers.
+ *actualFrameCount = frameCount;
+ while (buffer != nullptr && frameCount > 0) {
+ ApeHeader* apeHeader = nullptr;
+ void* prevBuffer = buffer;
+ buffer = findApeHeader(prevBuffer, frameCount * mFrameSizeBytes, &apeHeader);
+ if (buffer != nullptr && apeHeader != nullptr) {
+ // Frame count does not include the size of the header data.
+ const size_t headerSizeFrames =
+ (static_cast<uint8_t*>(buffer) - static_cast<uint8_t*>(prevBuffer)) /
+ mFrameSizeBytes;
+ frameCount -= headerSizeFrames;
+ *actualFrameCount = frameCount;
+ // Stage the clip duration into the DSP worker's queue.
+ const int64_t clipDurationFrames = getApeClipDurationFrames(apeHeader);
+ const int32_t clipSampleRate = apeHeader->sampleRate;
+ LOG(DEBUG) << __func__ << ": found APE clip of " << clipDurationFrames << " frames, "
+ << "sample rate: " << clipSampleRate;
+ if (clipSampleRate == mState.sampleRate) {
+ std::lock_guard l(mState.lock);
+ mState.clipFramesLeft.push_back(clipDurationFrames);
+ } else {
+ LOG(ERROR) << __func__ << ": clip sample rate " << clipSampleRate
+ << " does not match stream sample rate " << mState.sampleRate;
+ }
+ } else {
+ frameCount = 0;
+ }
+ }
+ {
+ std::lock_guard l(mState.lock);
+ mState.bufferFramesLeft = *actualFrameCount;
+ }
+ mDspWorker.resume();
+ return ::android::OK;
+}
+
+void DriverOffloadStubImpl::shutdown() {
+ LOG(DEBUG) << __func__ << ": stopping the DSP simulator worker";
+ mDspWorker.stop();
+ DriverStubImpl::shutdown();
+}
+
+::android::status_t DriverOffloadStubImpl::startWorkerIfNeeded() {
+ if (!mDspWorkerStarted) {
+ // This is an "audio service thread," must have elevated priority.
+ if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
+ return ::android::NO_INIT;
+ }
+ mDspWorkerStarted = true;
+ }
+ return ::android::OK;
+}
+
+// static
+const std::set<std::string>& StreamOffloadStub::getSupportedEncodings() {
+ static const std::set<std::string> kSupportedEncodings = {
+ "audio/x-ape",
+ };
+ return kSupportedEncodings;
+}
+
+StreamOffloadStub::StreamOffloadStub(StreamContext* context, const Metadata& metadata)
+ : StreamCommonImpl(context, metadata), DriverOffloadStubImpl(getContext()) {}
+
+StreamOffloadStub::~StreamOffloadStub() {
+ cleanupWorker();
+}
+
+StreamOutOffloadStub::StreamOutOffloadStub(StreamContext&& context,
+ const SourceMetadata& sourceMetadata,
+ const std::optional<AudioOffloadInfo>& offloadInfo)
+ : StreamOut(std::move(context), offloadInfo),
+ StreamOffloadStub(&mContextInstance, sourceMetadata) {}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index f6c87e1..2278880 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -14,11 +14,8 @@
* limitations under the License.
*/
-#include <cmath>
-
#define LOG_TAG "AHAL_Stream"
#include <android-base/logging.h>
-#include <audio_utils/clock.h>
#include "core-impl/Module.h"
#include "core-impl/StreamStub.h"
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 14e70ef..f855038 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -41,7 +41,6 @@
"-Wthread-safety",
"-Wno-error=unused-parameter",
],
- test_config_template: "VtsHalAudioTargetTestTemplate.xml",
test_suites: [
"general-tests",
"vts",
@@ -60,6 +59,7 @@
srcs: [
":effectCommonFile",
],
+ test_config_template: "VtsHalAudioEffectTargetTestTemplate.xml",
}
cc_test {
@@ -77,6 +77,11 @@
"VtsHalAudioCoreConfigTargetTest.cpp",
"VtsHalAudioCoreModuleTargetTest.cpp",
],
+ data: [
+ "data/sine882hz_44100_3s.ape",
+ "data/sine960hz_48000_3s.ape",
+ ],
+ test_config_template: "VtsHalAudioCoreTargetTestTemplate.xml",
}
cc_test {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index d24c4c8..7d4cc70 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -36,12 +36,10 @@
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
-using aidl::android::media::audio::common::AudioEncapsulationMode;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
-using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
@@ -51,26 +49,6 @@
using aidl::android::media::audio::common::Int;
// static
-std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
- const AudioPortConfig& portConfig) {
- if (portConfig.flags.has_value() &&
- portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
- isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
- AudioOutputFlags::COMPRESS_OFFLOAD)) {
- AudioOffloadInfo offloadInfo;
- offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
- offloadInfo.base.channelMask = portConfig.channelMask.value();
- offloadInfo.base.format = portConfig.format.value();
- offloadInfo.bitRatePerSecond = 256000; // Arbitrary value.
- offloadInfo.durationUs = std::chrono::microseconds(1min).count(); // Arbitrary value.
- offloadInfo.usage = AudioUsage::MEDIA;
- offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
- return offloadInfo;
- }
- return {};
-}
-
-// static
std::vector<aidl::android::media::audio::common::AudioPort>
ModuleConfig::getAudioPortsForDeviceTypes(
const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index 27286e5..d45ccda 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -34,10 +34,6 @@
using SrcSinkGroup =
std::pair<aidl::android::hardware::audio::core::AudioRoute, std::vector<SrcSinkPair>>;
- static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
- generateOffloadInfoIfNeeded(
- const aidl::android::media::audio::common::AudioPortConfig& portConfig);
-
static std::vector<aidl::android::media::audio::common::AudioPort> getAudioPortsForDeviceTypes(
const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
const std::vector<aidl::android::media::audio::common::AudioDeviceType>& deviceTypes,
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 750e54d..21b7aff 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -19,6 +19,7 @@
#include <cmath>
#include <condition_variable>
#include <forward_list>
+#include <fstream>
#include <limits>
#include <memory>
#include <mutex>
@@ -81,12 +82,15 @@
using aidl::android::hardware::audio::core::sounddose::ISoundDose;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioConfigBase;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioDualMonoMode;
+using aidl::android::media::audio::common::AudioEncapsulationMode;
+using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioGainConfig;
using aidl::android::media::audio::common::AudioInputFlags;
@@ -96,6 +100,7 @@
using aidl::android::media::audio::common::AudioMMapPolicyInfo;
using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPlaybackRate;
using aidl::android::media::audio::common::AudioPort;
@@ -217,6 +222,59 @@
return result;
}
+static const AudioFormatDescription kApeFileAudioFormat = {.encoding = "audio/x-ape"};
+static const AudioChannelLayout kApeFileChannelMask =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(AudioChannelLayout::LAYOUT_MONO);
+struct MediaFileInfo {
+ std::string path;
+ int32_t bps;
+ int32_t durationMs;
+};
+static const std::map<AudioConfigBase, MediaFileInfo> kMediaFileDataInfos = {
+ {{44100, kApeFileChannelMask, kApeFileAudioFormat},
+ {"/data/local/tmp/sine882hz_44100_3s.ape", 217704, 3000}},
+ {{48000, kApeFileChannelMask, kApeFileAudioFormat},
+ {"/data/local/tmp/sine960hz_48000_3s.ape", 236256, 3000}},
+};
+
+std::optional<MediaFileInfo> getMediaFileInfoForConfig(const AudioConfigBase& config) {
+ const auto it = kMediaFileDataInfos.find(config);
+ if (it != kMediaFileDataInfos.end()) return it->second;
+ return std::nullopt;
+}
+
+std::optional<MediaFileInfo> getMediaFileInfoForConfig(const AudioPortConfig& config) {
+ if (!config.sampleRate.has_value() || !config.format.has_value() ||
+ !config.channelMask.has_value()) {
+ return std::nullopt;
+ }
+ return getMediaFileInfoForConfig(AudioConfigBase{
+ config.sampleRate->value, config.channelMask.value(), config.format.value()});
+}
+
+std::optional<AudioOffloadInfo> generateOffloadInfoIfNeeded(const AudioPortConfig& portConfig) {
+ if (portConfig.flags.has_value() &&
+ portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
+ isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::COMPRESS_OFFLOAD)) {
+ AudioOffloadInfo offloadInfo;
+ offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
+ offloadInfo.base.channelMask = portConfig.channelMask.value();
+ offloadInfo.base.format = portConfig.format.value();
+ if (auto info = getMediaFileInfoForConfig(portConfig); info.has_value()) {
+ offloadInfo.bitRatePerSecond = info->bps;
+ offloadInfo.durationUs = info->durationMs * 1000LL;
+ } else {
+ offloadInfo.bitRatePerSecond = 256000; // Arbitrary value.
+ offloadInfo.durationUs = std::chrono::microseconds(1min).count(); // Arbitrary value.
+ }
+ offloadInfo.usage = AudioUsage::MEDIA;
+ offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
+ return offloadInfo;
+ }
+ return {};
+}
+
// All 'With*' classes are move-only because they are associated with some
// resource or state of a HAL module.
class WithDebugFlags {
@@ -652,11 +710,14 @@
typedef AidlMessageQueue<StreamDescriptor::Reply, SynchronizedReadWrite> ReplyMQ;
typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> DataMQ;
- explicit StreamContext(const StreamDescriptor& descriptor)
+ explicit StreamContext(const StreamDescriptor& descriptor, const AudioConfigBase& config,
+ AudioIoFlags flags)
: mFrameSizeBytes(descriptor.frameSizeBytes),
+ mConfig(config),
mCommandMQ(new CommandMQ(descriptor.command)),
mReplyMQ(new ReplyMQ(descriptor.reply)),
mBufferSizeFrames(descriptor.bufferSizeFrames),
+ mFlags(flags),
mDataMQ(maybeCreateDataMQ(descriptor)),
mIsMmapped(isMmapped(descriptor)),
mSharedMemoryFd(maybeGetMmapFd(descriptor)) {
@@ -695,9 +756,12 @@
size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+ const AudioConfigBase& getConfig() const { return mConfig; }
DataMQ* getDataMQ() const { return mDataMQ.get(); }
+ AudioIoFlags getFlags() const { return mFlags; }
size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+ int getSampleRate() const { return mConfig.sampleRate; }
bool isMmapped() const { return mIsMmapped; }
int8_t* getMmapMemory() const { return mSharedMemory; }
@@ -722,9 +786,11 @@
}
const size_t mFrameSizeBytes;
+ const AudioConfigBase mConfig;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<ReplyMQ> mReplyMQ;
const size_t mBufferSizeFrames;
+ const AudioIoFlags mFlags;
std::unique_ptr<DataMQ> mDataMQ;
const bool mIsMmapped;
const int32_t mSharedMemoryFd;
@@ -926,12 +992,19 @@
mDriver(driver),
mEventReceiver(eventReceiver),
mIsMmapped(context.isMmapped()),
- mSharedMemory(context.getMmapMemory()) {}
+ mSharedMemory(context.getMmapMemory()),
+ mIsCompressOffload(context.getFlags().getTag() == AudioIoFlags::output &&
+ isBitPositionFlagSet(context.getFlags().get<AudioIoFlags::output>(),
+ AudioOutputFlags::COMPRESS_OFFLOAD)),
+ mConfig(context.getConfig()) {}
StreamContext::CommandMQ* getCommandMQ() const { return mCommandMQ; }
+ const AudioConfigBase& getConfig() const { return mConfig; }
StreamContext::ReplyMQ* getReplyMQ() const { return mReplyMQ; }
StreamContext::DataMQ* getDataMQ() const { return mDataMQ; }
StreamLogicDriver* getDriver() const { return mDriver; }
StreamEventReceiver* getEventReceiver() const { return mEventReceiver; }
+ int getSampleRate() const { return mConfig.sampleRate; }
+ bool isCompressOffload() const { return mIsCompressOffload; }
bool isMmapped() const { return mIsMmapped; }
std::string init() override {
@@ -940,6 +1013,10 @@
}
const std::vector<int8_t>& getData() const { return mData; }
void fillData(int8_t filler) { std::fill(mData.begin(), mData.end(), filler); }
+ void loadData(std::ifstream& is, size_t* size) {
+ *size = std::min(*size, mData.size());
+ is.read(reinterpret_cast<char*>(mData.data()), *size);
+ }
std::optional<StreamDescriptor::Command> maybeGetNextCommand(int* actualSize = nullptr) {
TransitionTrigger trigger = mDriver->getNextTrigger(mData.size(), actualSize);
if (StreamEventReceiver::Event* expEvent =
@@ -1002,6 +1079,8 @@
int mLastEventSeq = StreamEventReceiver::kEventSeqInit;
const bool mIsMmapped;
int8_t* mSharedMemory = nullptr;
+ const bool mIsCompressOffload;
+ const AudioConfigBase mConfig;
};
class StreamReaderLogic : public StreamCommonLogic {
@@ -1102,6 +1181,24 @@
const std::vector<int8_t>& getData() const { return StreamCommonLogic::getData(); }
protected:
+ std::string init() override {
+ if (auto status = StreamCommonLogic::init(); !status.empty()) return status;
+ if (isCompressOffload()) {
+ const auto info = getMediaFileInfoForConfig(getConfig());
+ if (info) {
+ mCompressedMedia.open(info->path, std::ios::in | std::ios::binary);
+ if (!mCompressedMedia.is_open()) {
+ return std::string("failed to open media file \"") + info->path + "\"";
+ }
+ mCompressedMedia.seekg(0, mCompressedMedia.end);
+ mCompressedMediaSize = mCompressedMedia.tellg();
+ mCompressedMedia.seekg(0, mCompressedMedia.beg);
+ LOG(DEBUG) << __func__ << ": using media file \"" << info->path << "\", size "
+ << mCompressedMediaSize << " bytes";
+ }
+ }
+ return "";
+ }
Status cycle() override {
if (getDriver()->done()) {
LOG(DEBUG) << __func__ << ": clean exit";
@@ -1115,13 +1212,31 @@
LOG(ERROR) << __func__ << ": no next command";
return Status::ABORT;
}
- if (actualSize != 0) {
+ if (actualSize > 0) {
if (command.getTag() == StreamDescriptor::Command::burst) {
- fillData(mBurstIteration);
- if (mBurstIteration < std::numeric_limits<int8_t>::max()) {
- mBurstIteration++;
+ if (!isCompressOffload()) {
+ fillData(mBurstIteration);
+ if (mBurstIteration < std::numeric_limits<int8_t>::max()) {
+ mBurstIteration++;
+ } else {
+ mBurstIteration = 0;
+ }
} else {
- mBurstIteration = 0;
+ fillData(0);
+ size_t size = std::min(static_cast<size_t>(actualSize),
+ mCompressedMediaSize - mCompressedMediaPos);
+ loadData(mCompressedMedia, &size);
+ if (!mCompressedMedia.good()) {
+ LOG(ERROR) << __func__ << ": read failed";
+ return Status::ABORT;
+ }
+ LOG(DEBUG) << __func__ << ": read from file " << size << " bytes";
+ mCompressedMediaPos += size;
+ if (mCompressedMediaPos >= mCompressedMediaSize) {
+ mCompressedMedia.seekg(0, mCompressedMedia.beg);
+ mCompressedMediaPos = 0;
+ LOG(DEBUG) << __func__ << ": rewound to the beginning of the file";
+ }
}
}
if (isMmapped() ? !writeDataToMmap() : !writeDataToMQ()) {
@@ -1185,6 +1300,9 @@
private:
int8_t mBurstIteration = 1;
+ std::ifstream mCompressedMedia;
+ size_t mCompressedMediaSize = 0;
+ size_t mCompressedMediaPos = 0;
};
using StreamWriter = StreamWorker<StreamWriterLogic>;
@@ -1293,7 +1411,13 @@
ASSERT_NE(nullptr, mStream) << "port config id " << getPortId();
EXPECT_GE(mDescriptor.bufferSizeFrames, bufferSizeFrames)
<< "actual buffer size must be no less than requested";
- mContext.emplace(mDescriptor);
+ const auto& config = mPortConfig.get();
+ ASSERT_TRUE(config.channelMask.has_value());
+ ASSERT_TRUE(config.format.has_value());
+ ASSERT_TRUE(config.sampleRate.has_value());
+ ASSERT_TRUE(config.flags.has_value());
+ const AudioConfigBase cfg{config.sampleRate->value, *config.channelMask, *config.format};
+ mContext.emplace(mDescriptor, cfg, config.flags.value());
ASSERT_NO_FATAL_FAILURE(mContext.value().checkIsValid());
}
void SetUp(IModule* module, long bufferSizeFrames) {
@@ -1364,7 +1488,7 @@
aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = portConfig.id;
args.sourceMetadata = GenerateSourceMetadata(portConfig);
- args.offloadInfo = ModuleConfig::generateOffloadInfoIfNeeded(portConfig);
+ args.offloadInfo = generateOffloadInfoIfNeeded(portConfig);
args.bufferSizeFrames = bufferSizeFrames;
auto callback = ndk::SharedRefBase::make<DefaultStreamCallback>();
args.callback = callback;
@@ -3192,10 +3316,12 @@
{AudioInputFlags::MMAP_NOIRQ, AudioInputFlags::VOIP_TX,
AudioInputFlags::HW_HOTWORD, AudioInputFlags::HOTWORD_TAP})) ||
(portConfig.flags.value().getTag() == AudioIoFlags::output &&
- isAnyBitPositionFlagSet(
- portConfig.flags.value().template get<AudioIoFlags::output>(),
- {AudioOutputFlags::MMAP_NOIRQ, AudioOutputFlags::VOIP_RX,
- AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::INCALL_MUSIC}));
+ (isAnyBitPositionFlagSet(portConfig.flags.value().template get<AudioIoFlags::output>(),
+ {AudioOutputFlags::MMAP_NOIRQ, AudioOutputFlags::VOIP_RX,
+ AudioOutputFlags::INCALL_MUSIC}) ||
+ (isBitPositionFlagSet(portConfig.flags.value().template get<AudioIoFlags::output>(),
+ AudioOutputFlags::COMPRESS_OFFLOAD) &&
+ !getMediaFileInfoForConfig(portConfig))));
}
// Certain types of devices can not be used without special preconditions.
@@ -3863,7 +3989,7 @@
aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = portConfig.id;
args.sourceMetadata = GenerateSourceMetadata(portConfig);
- args.offloadInfo = ModuleConfig::generateOffloadInfoIfNeeded(portConfig);
+ args.offloadInfo = generateOffloadInfoIfNeeded(portConfig);
args.bufferSizeFrames = stream.getPatch().minimumStreamBufferSizeFrames;
aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
@@ -4185,18 +4311,6 @@
std::get<NAMED_CMD_DELAY_MS>(std::get<PARAM_CMD_SEQ>(GetParam()));
ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
- if (aidlVersion >= kAidlVersion3 && isNonBlocking && !IOTraits<Stream>::is_input) {
- // Also try running the same sequence with "aosp.forceDrainToDraining" set.
- // This will only work with the default implementation. When it works, the stream
- // tries always to move to the 'DRAINING' state after an "early notify" drain.
- // This helps to check more paths for our test scenarios.
- WithModuleParameter forceDrainToDraining("aosp.forceDrainToDraining",
- Boolean{true});
- if (forceDrainToDraining.SetUpNoChecks(module.get(), true /*failureExpected*/)
- .isOk()) {
- ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
- }
- }
if (isNonBlocking) {
// Also try running the same sequence with "aosp.forceTransientBurst" set.
// This will only work with the default implementation. When it works, the stream
@@ -4744,9 +4858,14 @@
std::shared_ptr<StateSequence> makeDrainEarlyOutCommands() {
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
- StateDag::Node last = d->makeFinalNode(State::IDLE);
- StateDag::Node draining = d->makeNode(State::DRAINING, kDrainReadyEvent, last);
- draining.children().push_back(d->makeNode(State::DRAINING, kGetStatusCommand, last));
+ // In the "early notify" case, the transition to the `IDLE` state following
+ // the 'onDrainReady' event can take some time. Waiting for an arbitrary amount
+ // of time may make the test fragile. Instead, for successful completion
+ // is registered if the stream has entered `IDLE` or `DRAINING` state.
+ StateDag::Node lastIdle = d->makeFinalNode(State::IDLE);
+ StateDag::Node lastDraining = d->makeFinalNode(State::DRAINING);
+ StateDag::Node draining =
+ d->makeNode(State::DRAINING, kDrainReadyEvent, lastIdle, lastDraining);
StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
@@ -4893,7 +5012,7 @@
std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makePauseCommands(false, true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kPauseOutAsyncSeq =
- std::make_tuple(std::string("Pause"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+ std::make_tuple(std::string("Pause"), kAidlVersion3, kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::ASYNC, makePauseCommands(false, false),
false /*validatePositionIncrease*/);
@@ -4998,9 +5117,8 @@
kDrainOutSyncSeq, kDrainOutAsyncSeq,
kDrainEarlyOutAsyncSeq, kDrainPauseOutSyncSeq,
kDrainPauseOutAsyncSeq, kDrainEarlyPauseOutAsyncSeq,
- kStandbyOutSyncSeq, kStandbyOutAsyncSeq,
- kPauseOutSyncSeq, // kPauseOutAsyncSeq,
- kFlushOutSyncSeq, kFlushOutAsyncSeq,
+ kStandbyOutSyncSeq, kStandbyOutAsyncSeq, kPauseOutSyncSeq,
+ kPauseOutAsyncSeq, kFlushOutSyncSeq, kFlushOutAsyncSeq,
kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),
testing::Values(false, true)),
GetStreamIoTestName);
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTestTemplate.xml b/audio/aidl/vts/VtsHalAudioCoreTargetTestTemplate.xml
new file mode 100644
index 0000000..94db58d
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTestTemplate.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 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 {MODULE}.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+ <option name="push" value="sine882hz_44100_3s.ape->/data/local/tmp/sine882hz_44100_3s.ape" />
+ <option name="push" value="sine960hz_48000_3s.ape->/data/local/tmp/sine960hz_48000_3s.ape" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ <option name="native-test-timeout" value="30m" />
+ </test>
+</configuration>
diff --git a/audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml b/audio/aidl/vts/VtsHalAudioEffectTargetTestTemplate.xml
similarity index 100%
rename from audio/aidl/vts/VtsHalAudioTargetTestTemplate.xml
rename to audio/aidl/vts/VtsHalAudioEffectTargetTestTemplate.xml
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 0d4c74e..2bb0a72 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -120,6 +120,14 @@
float calculateDb(const std::vector<float>& input, size_t startSamplePos);
+ void getMagnitudeValue(const std::vector<float>& output, std::vector<float>& bufferMag);
+
+ void checkInputAndOutputEquality(const std::vector<float>& outputMag);
+
+ void setUpDataTest(const std::vector<int>& testFrequencies, float fullScaleSineDb);
+
+ void createChannelConfig();
+
// enqueue test parameters
void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
void addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
@@ -137,7 +145,24 @@
static constexpr int kFrameCount = 2048;
static constexpr int kInputFrequency = 1000;
static constexpr size_t kStartIndex = 15 * kSamplingFrequency / 1000; // skip 15ms
- static constexpr float kToleranceDb = 0.05;
+ static constexpr float kToleranceDb = 0.5;
+ static constexpr int kNPointFFT = 1024;
+ static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
+ // Full scale sine wave with 1000 Hz frequency is -3 dB
+ static constexpr float kSineFullScaleDb = -3;
+ // Full scale sine wave with 100 Hz and 1000 Hz frequency is -6 dB
+ static constexpr float kSineMultitoneFullScaleDb = -6;
+ const std::vector<int> kCutoffFreqHz = {200 /*0th band cutoff*/, 2000 /*1st band cutoff*/};
+ std::vector<int> mMultitoneTestFrequencies = {100, 1000};
+ // Calculating normalizing factor by dividing the number of FFT points by half and the number of
+ // test frequencies. The normalization accounts for the FFT splitting the signal into positive
+ // and negative frequencies. Additionally, during multi-tone input generation, sample values are
+ // normalized to the range [-1, 1] by dividing them by the number of test frequencies.
+ float mNormalizingFactor = (kNPointFFT / (2 * mMultitoneTestFrequencies.size()));
+ std::vector<int> mBinOffsets;
+ std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
+ std::vector<float> mInput;
+ float mInputDb;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
Descriptor mDescriptor;
@@ -416,6 +441,38 @@
}
}
+void DynamicsProcessingTestHelper::getMagnitudeValue(const std::vector<float>& output,
+ std::vector<float>& bufferMag) {
+ std::vector<float> subOutput(output.begin() + kStartIndex, output.end());
+ EXPECT_NO_FATAL_FAILURE(calculateMagnitudeMono(bufferMag, subOutput, mBinOffsets, kNPointFFT));
+}
+
+void DynamicsProcessingTestHelper::checkInputAndOutputEquality(
+ const std::vector<float>& outputMag) {
+ std::vector<float> inputMag(mBinOffsets.size());
+ EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(mInput, inputMag));
+ for (size_t i = 0; i < inputMag.size(); i++) {
+ EXPECT_NEAR(calculateDb({inputMag[i] / mNormalizingFactor}),
+ calculateDb({outputMag[i] / mNormalizingFactor}), kToleranceDb);
+ }
+}
+
+void DynamicsProcessingTestHelper::setUpDataTest(const std::vector<int>& testFrequencies,
+ float fullScaleSineDb) {
+ ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect());
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(
+ generateSineWave(testFrequencies, mInput, 1.0, kSamplingFrequency, mChannelLayout));
+ mInputDb = calculateDb(mInput);
+ ASSERT_NEAR(mInputDb, fullScaleSineDb, kToleranceDb);
+}
+
+void DynamicsProcessingTestHelper::createChannelConfig() {
+ for (int i = 0; i < mChannelCount; i++) {
+ mChannelConfig.push_back(DynamicsProcessing::ChannelConfig(i, true));
+ }
+}
+
void DynamicsProcessingTestHelper::addEngineConfig(
const DynamicsProcessing::EngineArchitecture& cfg) {
DynamicsProcessing dp;
@@ -527,6 +584,15 @@
.postGainDb = postGainDb};
}
+DynamicsProcessing::EqBandConfig creatEqBandConfig(int channel, int band, float cutOffFreqHz,
+ float gainDb) {
+ return DynamicsProcessing::EqBandConfig{.channel = channel,
+ .band = band,
+ .enable = true,
+ .cutoffFrequencyHz = cutOffFreqHz,
+ .gainDb = gainDb};
+}
+
/**
* Test DynamicsProcessing Engine Configuration
*/
@@ -649,13 +715,7 @@
mInput.resize(kFrameCount * mChannelCount);
}
- void SetUp() override {
- SetUpDynamicsProcessingEffect();
- SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
- ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency /*Input Frequency*/, mInput, 1.0,
- kSamplingFrequency, mChannelLayout));
- mInputDb = calculateDb(mInput);
- }
+ void SetUp() override { setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb); }
void TearDown() override { TearDownDynamicsProcessingEffect(); }
@@ -665,8 +725,6 @@
}
std::vector<DynamicsProcessing::InputGain> mInputGain;
- std::vector<float> mInput;
- float mInputDb;
};
TEST_P(DynamicsProcessingInputGainDataTest, SetAndGetInputGain) {
@@ -785,14 +843,7 @@
mInput.resize(mBufferSize);
}
- void SetUp() override {
- SetUpDynamicsProcessingEffect();
- SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
- ASSERT_NO_FATAL_FAILURE(
- generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
- mInputDb = calculateDb(mInput);
- ASSERT_NEAR(mInputDb, kSineFullScaleDb, kToleranceDb);
- }
+ void SetUp() override { setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb); }
void TearDown() override { TearDownDynamicsProcessingEffect(); }
@@ -825,11 +876,8 @@
static constexpr float kDefaultThreshold = -10;
static constexpr float kDefaultPostGain = 0;
static constexpr float kInputFrequency = 1000;
- // Full scale sine wave with 1000 Hz frequency is -3 dB
- static constexpr float kSineFullScaleDb = -3;
+ static constexpr float kLimiterTestToleranceDb = 0.05;
std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
- std::vector<float> mInput;
- float mInputDb;
int mBufferSize;
};
@@ -849,7 +897,7 @@
}
float outputDb = calculateDb(output, kStartIndex);
if (threshold >= mInputDb || kDefaultRatio == 1) {
- EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
+ EXPECT_NEAR(mInputDb, outputDb, kLimiterTestToleranceDb);
} else {
float calculatedThreshold = 0;
ASSERT_NO_FATAL_FAILURE(computeThreshold(kDefaultRatio, outputDb, calculatedThreshold));
@@ -876,7 +924,7 @@
float outputDb = calculateDb(output, kStartIndex);
if (kDefaultThreshold >= mInputDb) {
- EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
+ EXPECT_NEAR(mInputDb, outputDb, kLimiterTestToleranceDb);
} else {
float calculatedRatio = 0;
ASSERT_NO_FATAL_FAILURE(computeRatio(kDefaultThreshold, outputDb, calculatedRatio));
@@ -894,7 +942,7 @@
ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, dBToAmplitude(postGainDb),
kSamplingFrequency, mChannelLayout));
mInputDb = calculateDb(mInput);
- EXPECT_NEAR(mInputDb, kSineFullScaleDb - postGainDb, kToleranceDb);
+ EXPECT_NEAR(mInputDb, kSineFullScaleDb - postGainDb, kLimiterTestToleranceDb);
for (int i = 0; i < mChannelCount; i++) {
fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
kDefaultReleaseTime, 1, kDefaultThreshold, postGainDb);
@@ -904,7 +952,7 @@
continue;
}
float outputDb = calculateDb(output, kStartIndex);
- EXPECT_NEAR(outputDb, mInputDb + postGainDb, kToleranceDb)
+ EXPECT_NEAR(outputDb, mInputDb + postGainDb, kLimiterTestToleranceDb)
<< "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
}
}
@@ -927,7 +975,7 @@
if (isEnabled) {
EXPECT_NE(mInputDb, calculateDb(output, kStartIndex));
} else {
- EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), kToleranceDb);
+ EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), kLimiterTestToleranceDb);
}
}
}
@@ -1025,13 +1073,9 @@
const EqBandConfigTestParams& params) {
const std::vector<std::pair<int, float>> cutOffFreqs = std::get<EQ_BAND_CUT_OFF_FREQ>(params);
int bandCount = cutOffFreqs.size();
- cfgs.resize(bandCount);
for (int i = 0; i < bandCount; i++) {
- cfgs[i].channel = std::get<EQ_BAND_CHANNEL>(params);
- cfgs[i].band = cutOffFreqs[i].first;
- cfgs[i].enable = true /*Eqband Enable*/;
- cfgs[i].cutoffFrequencyHz = cutOffFreqs[i].second;
- cfgs[i].gainDb = std::get<EQ_BAND_GAIN>(params);
+ cfgs.push_back(creatEqBandConfig(std::get<EQ_BAND_CHANNEL>(params), cutOffFreqs[i].first,
+ cutOffFreqs[i].second, std::get<EQ_BAND_GAIN>(params)));
}
}
@@ -1083,7 +1127,12 @@
{2, 6000},
{3, 10000},
{4, 16000},
- }, // 5 bands
+ {5, 20000},
+ {6, 26000},
+ {7, 30000},
+ {8, 36000},
+ {9, 40000},
+ }, // 10 bands
{
{0, 800},
{3, 15000},
@@ -1142,6 +1191,119 @@
});
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEqBandConfig);
+class DynamicsProcessingEqBandConfigDataTest
+ : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
+ public DynamicsProcessingTestHelper {
+ public:
+ DynamicsProcessingEqBandConfigDataTest()
+ : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
+ mInput.resize(kFrameCount * mChannelCount);
+ mBinOffsets.resize(mMultitoneTestFrequencies.size());
+ }
+
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ setUpDataTest(mMultitoneTestFrequencies, kSineMultitoneFullScaleDb));
+ }
+
+ void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+ void addEqParam(bool isPreEq) {
+ createChannelConfig();
+ auto stage = isPreEq ? mEngineConfigPreset.preEqStage : mEngineConfigPreset.postEqStage;
+ stage.bandCount = mCfgs.size();
+ addEngineConfig(mEngineConfigPreset);
+ isPreEq ? addPreEqChannelConfig(mChannelConfig) : addPostEqChannelConfig(mChannelConfig);
+ isPreEq ? addPreEqBandConfigs(mCfgs) : addPostEqBandConfigs(mCfgs);
+ }
+
+ void setEqParamAndProcess(std::vector<float>& output, bool isPreEq) {
+ addEqParam(isPreEq);
+ ASSERT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
+ }
+
+ void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs, int channelIndex,
+ int bandIndex, int cutOffFreqHz, float gainDb) {
+ cfgs.push_back(creatEqBandConfig(channelIndex, bandIndex, static_cast<float>(cutOffFreqHz),
+ gainDb));
+ }
+
+ void validateOutput(const std::vector<float>& output, float gainDb, size_t bandIndex) {
+ std::vector<float> outputMag(mBinOffsets.size());
+ EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
+ if (gainDb == 0) {
+ EXPECT_NO_FATAL_FAILURE(checkInputAndOutputEquality(outputMag));
+ } else if (gainDb > 0) {
+ // For positive gain, current band's magnitude is greater than the other band's
+ // magnitude
+ EXPECT_GT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
+ } else {
+ // For negative gain, current band's magnitude is less than the other band's magnitude
+ EXPECT_LT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
+ }
+ }
+
+ void analyseMultiBandOutput(float gainDb, bool isPreEq) {
+ std::vector<float> output(mInput.size());
+ roundToFreqCenteredToFftBin(mMultitoneTestFrequencies, mBinOffsets, kBinWidth);
+ // Set Equalizer values for two bands
+ for (size_t i = 0; i < kCutoffFreqHz.size(); i++) {
+ for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
+ fillEqBandConfig(mCfgs, channelIndex, i, kCutoffFreqHz[i], gainDb);
+ fillEqBandConfig(mCfgs, channelIndex, i ^ 1, kCutoffFreqHz[i ^ 1], 0);
+ }
+ ASSERT_NO_FATAL_FAILURE(setEqParamAndProcess(output, isPreEq));
+
+ if (isAllParamsValid()) {
+ ASSERT_NO_FATAL_FAILURE(validateOutput(output, gainDb, i));
+ }
+ cleanUpEqConfig();
+ }
+ }
+
+ void cleanUpEqConfig() {
+ CleanUp();
+ mCfgs.clear();
+ mChannelConfig.clear();
+ }
+
+ const std::vector<float> kTestGainDbValues = {-200, -100, 0, 100, 200};
+ std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
+};
+
+TEST_P(DynamicsProcessingEqBandConfigDataTest, IncreasingPreEqGain) {
+ for (float gainDb : kTestGainDbValues) {
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
+ dBToAmplitude(gainDb), kSamplingFrequency,
+ mChannelLayout));
+ cleanUpEqConfig();
+ ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(gainDb, true /*pre-equalizer*/));
+ }
+}
+
+TEST_P(DynamicsProcessingEqBandConfigDataTest, IncreasingPostEqGain) {
+ for (float gainDb : kTestGainDbValues) {
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
+ dBToAmplitude(gainDb), kSamplingFrequency,
+ mChannelLayout));
+ cleanUpEqConfig();
+ ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(gainDb, false /*post-equalizer*/));
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingEqBandConfigDataTest,
+ testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
+ [](const auto& info) {
+ auto descriptor = info.param;
+ std::string name = getPrefix(descriptor.second);
+ std::replace_if(
+ name.begin(), name.end(),
+ [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingEqBandConfigDataTest);
+
/**
* Test DynamicsProcessing MbcBandConfig
*/
@@ -1254,24 +1416,18 @@
DynamicsProcessingMbcBandConfigDataTest()
: DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
mInput.resize(kFrameCount * mChannelCount);
- mBinOffsets.resize(mTestFrequencies.size());
+ mBinOffsets.resize(mMultitoneTestFrequencies.size());
}
void SetUp() override {
- SetUpDynamicsProcessingEffect();
- SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
- ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput, 1.0, kSamplingFrequency,
- mChannelLayout));
- mInputDb = calculateDb(mInput);
- ASSERT_NEAR(mInputDb, kFullScaleDb, kToleranceDb);
+ ASSERT_NO_FATAL_FAILURE(
+ setUpDataTest(mMultitoneTestFrequencies, kSineMultitoneFullScaleDb));
}
void TearDown() override { TearDownDynamicsProcessingEffect(); }
void setMbcParamsAndProcess(std::vector<float>& output) {
- for (int i = 0; i < mChannelCount; i++) {
- mChannelConfig.push_back(DynamicsProcessing::ChannelConfig(i, true));
- }
+ createChannelConfig();
mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
addEngineConfig(mEngineConfigPreset);
addMbcChannelConfig(mChannelConfig);
@@ -1288,23 +1444,12 @@
noiseGate, expanderRatio, preGain, postGain));
}
- void getMagnitudeValue(const std::vector<float>& output, std::vector<float>& bufferMag) {
- std::vector<float> subOutput(output.begin() + kStartIndex, output.end());
- EXPECT_NO_FATAL_FAILURE(
- calculateMagnitudeMono(bufferMag, subOutput, mBinOffsets, kNPointFFT));
- }
-
void validateOutput(const std::vector<float>& output, float threshold, float ratio,
size_t bandIndex) {
std::vector<float> outputMag(mBinOffsets.size());
EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
if (threshold >= mInputDb || ratio == 1) {
- std::vector<float> inputMag(mBinOffsets.size());
- EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(mInput, inputMag));
- for (size_t i = 0; i < inputMag.size(); i++) {
- EXPECT_NEAR(calculateDb({inputMag[i] / mNormalizingFactor}),
- calculateDb({outputMag[i] / mNormalizingFactor}), kToleranceDb);
- }
+ EXPECT_NO_FATAL_FAILURE(checkInputAndOutputEquality(outputMag));
} else {
// Current band's magnitude is less than the other band's magnitude
EXPECT_LT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
@@ -1313,17 +1458,16 @@
void analyseMultiBandOutput(float threshold, float ratio) {
std::vector<float> output(mInput.size());
- roundToFreqCenteredToFftBin(mTestFrequencies, mBinOffsets, kBinWidth);
- std::vector<int> cutoffFreqHz = {200 /*0th band cutoff*/, 2000 /*1st band cutoff*/};
+ roundToFreqCenteredToFftBin(mMultitoneTestFrequencies, mBinOffsets, kBinWidth);
// Set MBC values for two bands
- for (size_t i = 0; i < cutoffFreqHz.size(); i++) {
+ for (size_t i = 0; i < kCutoffFreqHz.size(); i++) {
for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
fillMbcBandConfig(mCfgs, channelIndex, threshold, ratio, kDefaultNoiseGateDb,
- kDefaultExpanderRatio, i, cutoffFreqHz[i], kDefaultPreGainDb,
+ kDefaultExpanderRatio, i, kCutoffFreqHz[i], kDefaultPreGainDb,
kDefaultPostGainDb);
fillMbcBandConfig(mCfgs, channelIndex, kDefaultThresholdDb, kDefaultRatio,
kDefaultNoiseGateDb, kDefaultExpanderRatio, i ^ 1,
- cutoffFreqHz[i ^ 1], kDefaultPreGainDb, kDefaultPostGainDb);
+ kCutoffFreqHz[i ^ 1], kDefaultPreGainDb, kDefaultPostGainDb);
}
ASSERT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
@@ -1340,8 +1484,6 @@
mChannelConfig.clear();
}
- static constexpr int kNPointFFT = 1024;
- static constexpr float kToleranceDb = 0.5;
static constexpr float kDefaultPostGainDb = 0;
static constexpr float kDefaultPreGainDb = 0;
static constexpr float kDefaultAttackTime = 0;
@@ -1351,20 +1493,7 @@
static constexpr float kDefaultNoiseGateDb = -10;
static constexpr float kDefaultExpanderRatio = 1;
static constexpr float kDefaultRatio = 1;
- static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
- // Full scale sine wave with 100 Hz and 1000 Hz frequency is -6 dB
- static constexpr float kFullScaleDb = -6;
- std::vector<int> mTestFrequencies = {100, 1000};
- // Calculating normalizing factor by dividing the number of FFT points by half and the number of
- // test frequencies. The normalization accounts for the FFT splitting the signal into positive
- // and negative frequencies. Additionally, during multi-tone input generation, sample values are
- // normalized to the range [-1, 1] by dividing them by the number of test frequencies.
- float mNormalizingFactor = (kNPointFFT / (2 * mTestFrequencies.size()));
std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
- std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
- std::vector<int> mBinOffsets;
- std::vector<float> mInput;
- float mInputDb;
};
TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingThreshold) {
@@ -1391,11 +1520,11 @@
std::vector<float> postGainDbValues = {-55, -30, 0, 30, 55};
std::vector<float> output(mInput.size());
for (float postGainDb : postGainDbValues) {
- ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput,
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
dBToAmplitude(postGainDb), kSamplingFrequency,
mChannelLayout));
mInputDb = calculateDb(mInput);
- EXPECT_NEAR(mInputDb, kFullScaleDb - postGainDb, kToleranceDb);
+ EXPECT_NEAR(mInputDb, kSineMultitoneFullScaleDb - postGainDb, kToleranceDb);
cleanUpMbcConfig();
for (int i = 0; i < mChannelCount; i++) {
fillMbcBandConfig(mCfgs, i, kDefaultThresholdDb, kDefaultRatio, kDefaultNoiseGateDb,
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index 2802bf9..1b0b681 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -275,6 +275,9 @@
enum DataTestParam { EFFECT_INSTANCE, LAYOUT };
using HapticGeneratorDataTestParam = std::tuple<EffectInstance, int32_t>;
+// minimal HAL interface version to run the data path test
+constexpr int32_t kMinDataTestHalVersion = 3;
+
class HapticGeneratorDataTest : public ::testing::TestWithParam<HapticGeneratorDataTestParam>,
public HapticGeneratorHelper {
public:
@@ -293,7 +296,14 @@
mOutput.resize(mHapticSamples + mAudioSamples, 0);
}
- void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator(mChMask)); }
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator(mChMask));
+ if (int32_t version;
+ mEffect->getInterfaceVersion(&version).isOk() && version < kMinDataTestHalVersion) {
+ GTEST_SKIP() << "Skipping the data test for version: " << version << "\n";
+ }
+ }
+
void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
void generateSinePeriod() {
diff --git a/audio/aidl/vts/data/sine882hz_44100_3s.ape b/audio/aidl/vts/data/sine882hz_44100_3s.ape
new file mode 100644
index 0000000..1cefb15
--- /dev/null
+++ b/audio/aidl/vts/data/sine882hz_44100_3s.ape
Binary files differ
diff --git a/audio/aidl/vts/data/sine960hz_48000_3s.ape b/audio/aidl/vts/data/sine960hz_48000_3s.ape
new file mode 100644
index 0000000..149c42a
--- /dev/null
+++ b/audio/aidl/vts/data/sine960hz_48000_3s.ape
Binary files differ
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index cea085c..095bb86 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -52,6 +52,12 @@
"libmedia_headers",
"libmediautils_headers",
],
+
+ cflags: [
+ "-Wall",
+ "-Wthread-safety",
+ "-Werror",
+ ],
}
cc_library_shared {
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 4a9e144..9896653 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -321,8 +321,8 @@
status_t status = mProcessThread->join();
ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
}
- if (mEfGroup) {
- status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+ if (EventFlag* evFlag = mEfGroup.load(std::memory_order_acquire)) {
+ status_t status = EventFlag::deleteEventFlag(&evFlag);
ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
}
mInBuffer.clear();
@@ -437,6 +437,7 @@
Result Effect::analyzeStatus(const char* funcName, const char* subFuncName,
const char* contextDescription, status_t status) {
if (status != OK) {
+ std::lock_guard<std::mutex> lock(mLock);
ALOGW("Effect %p %s %s %s: %s", mHandle, funcName, subFuncName, contextDescription,
strerror(-status));
}
@@ -470,11 +471,14 @@
Return<void> Effect::getConfigImpl(int commandCode, const char* commandName,
GetConfigCallback _hidl_cb) {
- RETURN_RESULT_IF_EFFECT_CLOSED(EffectConfig());
uint32_t halResultSize = sizeof(effect_config_t);
effect_config_t halConfig{};
- status_t status =
- (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
+ status_t status = OK;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_RESULT_IF_EFFECT_CLOSED(EffectConfig());
+ status = (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
+ }
EffectConfig config;
if (status == OK) {
status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
@@ -542,7 +546,10 @@
}
Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
- RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
+ }
status_t status;
// Create message queue.
if (mStatusMQ) {
@@ -556,16 +563,21 @@
_hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
return Void();
}
- status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
- if (status != OK || !mEfGroup) {
+ EventFlag* evFlag = nullptr;
+ status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &evFlag);
+ if (status != OK || !evFlag) {
ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
_hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
return Void();
}
+ mEfGroup.store(evFlag, std::memory_order_release);
- // Create and launch the thread.
- mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
- &mHalOutBufferPtr, tempStatusMQ.get(), mEfGroup, this);
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ // Create and launch the thread.
+ mProcessThread = new ProcessThread(&mStopProcessThread, mHandle, &mHalInBufferPtr,
+ &mHalOutBufferPtr, tempStatusMQ.get(), evFlag, this);
+ }
status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
if (status != OK) {
ALOGW("failed to start effect processing thread: %s", strerror(-status));
@@ -575,11 +587,15 @@
// For a spatializer effect, we perform scheduler adjustments to reduce glitches and power.
// We do it here instead of the ProcessThread::threadLoop to ensure that mHandle is valid.
- if (effect_descriptor_t halDescriptor{};
- (*mHandle)->get_descriptor(mHandle, &halDescriptor) == NO_ERROR &&
- memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0) {
- const status_t status = scheduler::updateSpatializerPriority(mProcessThread->getTid());
- ALOGW_IF(status != OK, "Failed to update Spatializer priority");
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
+ if (effect_descriptor_t halDescriptor{};
+ (*mHandle)->get_descriptor(mHandle, &halDescriptor) == NO_ERROR &&
+ memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0) {
+ const status_t status = scheduler::updateSpatializerPriority(mProcessThread->getTid());
+ ALOGW_IF(status != OK, "Failed to update Spatializer priority");
+ }
}
mStatusMQ = std::move(tempStatusMQ);
@@ -589,7 +605,10 @@
Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) {
- RETURN_IF_EFFECT_CLOSED();
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_IF_EFFECT_CLOSED();
+ }
AudioBufferManager& manager = AudioBufferManager::getInstance();
sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
if (!manager.wrap(inBuffer, &tempInBuffer)) {
@@ -614,8 +633,12 @@
}
Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
- RETURN_IF_EFFECT_CLOSED();
- status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
+ status_t status = OK;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_IF_EFFECT_CLOSED();
+ status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
+ }
return analyzeCommandStatus(commandName, sContextCallToCommand, status);
}
@@ -626,9 +649,13 @@
Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
void* data, uint32_t* replySize, void* replyData) {
- RETURN_IF_EFFECT_CLOSED();
uint32_t expectedReplySize = *replySize;
- status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+ status_t status = OK;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_IF_EFFECT_CLOSED();
+ status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+ }
if (status == OK && *replySize != expectedReplySize) {
status = -ENODATA;
}
@@ -651,8 +678,12 @@
uint32_t size, void* data, uint32_t* replySize,
void* replyData, uint32_t minReplySize,
CommandSuccessCallback onSuccess) {
- RETURN_IF_EFFECT_CLOSED();
- status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+ status_t status = OK;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_IF_EFFECT_CLOSED();
+ status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+ }
Result retval;
if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
@@ -860,10 +891,14 @@
}
Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
- RETURN_RESULT_IF_EFFECT_CLOSED(EffectDescriptor());
effect_descriptor_t halDescriptor;
memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
- status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
+ status_t status = OK;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_RESULT_IF_EFFECT_CLOSED(EffectDescriptor());
+ status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
+ }
EffectDescriptor descriptor;
if (status == OK) {
status = EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
@@ -874,10 +909,6 @@
Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
uint32_t resultMaxSize, command_cb _hidl_cb) {
- if (mHandle == kInvalidEffectHandle) {
- _hidl_cb(-ENODATA, hidl_vec<uint8_t>());
- return Void();
- }
uint32_t halDataSize;
std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
uint32_t halResultSize = resultMaxSize;
@@ -897,8 +928,15 @@
}
[[fallthrough]]; // allow 'gtid' overload (checked halDataSize and resultMaxSize).
default:
- status = (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize,
- resultPtr);
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mHandle == kInvalidEffectHandle) {
+ _hidl_cb(-ENODATA, hidl_vec<uint8_t>());
+ return Void();
+ }
+ status = (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr,
+ &halResultSize, resultPtr);
+ }
break;
}
hidl_vec<uint8_t> result;
@@ -967,11 +1005,17 @@
return {Result::INVALID_STATE, kInvalidEffectHandle};
}
mStopProcessThread.store(true, std::memory_order_release);
- if (mEfGroup) {
- mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
+ EventFlag* evFlag = mEfGroup.load(std::memory_order_acquire);
+ if (evFlag) {
+ evFlag->wake(static_cast<uint32_t>(
+ MessageQueueFlagBits::REQUEST_QUIT));
}
- effect_handle_t handle = mHandle;
- mHandle = kInvalidEffectHandle;
+ effect_handle_t handle;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ handle = mHandle;
+ mHandle = kInvalidEffectHandle;
+ }
#if MAJOR_VERSION <= 5
return {Result::OK, handle};
#elif MAJOR_VERSION >= 6
@@ -984,7 +1028,10 @@
}
Return<Result> Effect::close() {
- RETURN_IF_EFFECT_CLOSED();
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ RETURN_IF_EFFECT_CLOSED();
+ }
auto [result, _] = closeImpl();
return result;
}
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 2bcecec..cc76784 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -25,6 +25,7 @@
#include <memory>
#include <tuple>
#include <vector>
+#include <mutex>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
@@ -194,13 +195,14 @@
static const char* sContextCallFunction;
const bool mIsInput;
- effect_handle_t mHandle;
+ std::mutex mLock;
+ effect_handle_t mHandle GUARDED_BY(mLock);
sp<AudioBufferWrapper> mInBuffer;
sp<AudioBufferWrapper> mOutBuffer;
std::atomic<audio_buffer_t*> mHalInBufferPtr;
std::atomic<audio_buffer_t*> mHalOutBufferPtr;
std::unique_ptr<StatusMQ> mStatusMQ;
- EventFlag* mEfGroup;
+ std::atomic<EventFlag*> mEfGroup;
std::atomic<bool> mStopProcessThread;
sp<Thread> mProcessThread;
diff --git a/automotive/can/OWNERS b/automotive/can/OWNERS
index ffa4828..b738dac 100644
--- a/automotive/can/OWNERS
+++ b/automotive/can/OWNERS
@@ -1,3 +1,2 @@
-kevinme@google.com
chrisweir@google.com
twasilczyk@google.com
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
index f099287..066af9a 100644
--- a/automotive/vehicle/OWNERS
+++ b/automotive/vehicle/OWNERS
@@ -1,9 +1,6 @@
ericjeong@google.com
shanyu@google.com
-# GRPC VHAL
-per-file aidl/impl/grpc/** =egranata@google.com
-
# Property definition
per-file aidl_property/** = tylertrephan@google.com
per-file aidl/generated_lib/** = tylertrephan@google.com
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index d0edfad..ff4ce3d 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -534,6 +534,8 @@
// Check the loopback of the ACL packet
ASSERT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameAclEventReceived)
.no_timeout);
+ ASSERT_FALSE(acl_queue.empty());
+
hidl_vec<uint8_t> acl_loopback = acl_queue.front();
acl_queue.pop();
diff --git a/bluetooth/aidl/Android.bp b/bluetooth/aidl/Android.bp
index 4ee2f49..0daecf7 100644
--- a/bluetooth/aidl/Android.bp
+++ b/bluetooth/aidl/Android.bp
@@ -16,6 +16,13 @@
srcs: ["android/hardware/bluetooth/*.aidl"],
stability: "vintf",
backend: {
+ cpp: {
+ // FIXME should this be disabled?
+ // prefer NDK backend which can be used anywhere
+ // If you disable this, you also need to delete the C++
+ // translate code.
+ enabled: true,
+ },
rust: {
enabled: true,
},
@@ -37,4 +44,5 @@
},
],
frozen: true,
+
}
diff --git a/bluetooth/aidl/default/Android.bp b/bluetooth/aidl/default/Android.bp
index d3f6364..46a6983 100644
--- a/bluetooth/aidl/default/Android.bp
+++ b/bluetooth/aidl/default/Android.bp
@@ -2,61 +2,58 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
- name: "libbluetoothhcihalimpl",
- vendor_available: true,
- host_supported: true,
- srcs: [
- "BluetoothHci.cpp",
- "net_bluetooth_mgmt.cpp",
- ],
+cc_defaults {
+ name: "android.hardware.bluetooth-service-build-defaults",
cflags: [
"-Wall",
"-Wextra",
],
- header_libs: [
- "libbluetooth_offload_hal_headers",
+ shared_libs: [
+ "android.hardware.bluetooth-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libutils",
],
static_libs: [
"android.hardware.bluetooth.async",
"android.hardware.bluetooth.hci",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "liblog",
- "libutils",
+ "libbluetooth_offload_hal",
],
}
-rust_binary {
+cc_library_static {
+ name: "libbluetoothhcihalimpl",
+ vendor_available: true,
+ defaults: ["android.hardware.bluetooth-service-build-defaults"],
+ srcs: [
+ "BluetoothHci.cpp",
+ "net_bluetooth_mgmt.cpp",
+ ],
+}
+
+cc_binary {
name: "android.hardware.bluetooth-service.default",
- crate_name: "bluetooth_hci_hal_server",
relative_install_path: "hw",
init_rc: ["bluetooth-service-default.rc"],
vintf_fragments: [":manifest_android.hardware.bluetooth-service.default.xml"],
vendor: true,
- prefer_rlib: true,
- srcs: ["main.rs"],
- rustlibs: [
- "android.hardware.bluetooth-V1-rust",
- "libbluetooth_offload_hal",
- "libbluetooth_offload_leaudio_hci",
- "libbinder_rs",
- "liblogger",
- "liblog_rust",
- ],
- static_libs: [
- "android.hardware.bluetooth.async",
- "android.hardware.bluetooth.hci",
- "libbluetoothhcihalimpl",
+ defaults: ["android.hardware.bluetooth-service-build-defaults"],
+ srcs: [
+ "service.cpp",
],
shared_libs: [
+ "android.hardware.bluetooth-V1-ndk",
"libbase",
- "libc++",
- "libcutils",
- "liblog",
+ "libbinder_ndk",
+ "libhidlbase",
"libutils",
+ "liblog",
+ ],
+ static_libs: [
+ "libbluetoothhcihalimpl",
],
}
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index bcdb67e..5ac3afe 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2024 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,18 @@
#define LOG_TAG "android.hardware.bluetooth.service.default"
+#include "BluetoothHci.h"
+
#include <cutils/properties.h>
#include <fcntl.h>
-#include <hal/ffi.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
#include <string.h>
+#include <sys/uio.h>
#include <termios.h>
-#include <future>
-#include <memory>
-#include <vector>
-
-#include "async_fd_watcher.h"
-#include "h4_protocol.h"
#include "log/log.h"
-#include "net_bluetooth_mgmt.h"
namespace {
int SetTerminalRaw(int fd) {
@@ -46,6 +44,7 @@
using namespace ::android::hardware::bluetooth::hci;
using namespace ::android::hardware::bluetooth::async;
+using aidl::android::hardware::bluetooth::hal::Status;
namespace aidl::android::hardware::bluetooth::impl {
@@ -62,298 +61,234 @@
return str.compare(0, prefix.length(), prefix) == 0;
}
-class Hal {
- public:
- Hal(const std::string& dev_path = "/dev/hvc5") {
- char property_bytes[PROPERTY_VALUE_MAX];
- property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
- mDevPath = std::string(property_bytes);
- }
+BluetoothHci::BluetoothHci(const std::string& dev_path) {
+ char property_bytes[PROPERTY_VALUE_MAX];
+ property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
+ mDevPath = std::string(property_bytes);
+}
- static void Initialize(void* instance,
- const struct hal_callbacks* callbacks) {
- static_cast<Hal*>(instance)->Initialize(callbacks);
- }
-
- static void Close(void* instance) { static_cast<Hal*>(instance)->Close(); }
-
- static void SendCommand(void* instance, const uint8_t* data, size_t len) {
- static_cast<Hal*>(instance)->SendCommand(
- std::vector<uint8_t>(data, data + len));
- }
-
- static void SendAcl(void* instance, const uint8_t* data, size_t len) {
- static_cast<Hal*>(instance)->SendAcl(
- std::vector<uint8_t>(data, data + len));
- }
-
- static void SendSco(void* instance, const uint8_t* data, size_t len) {
- static_cast<Hal*>(instance)->SendSco(
- std::vector<uint8_t>(data, data + len));
- }
-
- static void SendIso(void* instance, const uint8_t* data, size_t len) {
- static_cast<Hal*>(instance)->SendIso(
- std::vector<uint8_t>(data, data + len));
- }
-
- private:
- int getFdFromDevPath() {
- int fd = open(mDevPath.c_str(), O_RDWR);
- if (fd < 0) {
- ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
- strerror(errno));
- return fd;
- }
- if (int ret = SetTerminalRaw(fd) < 0) {
- ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
- strerror(errno));
- }
+int BluetoothHci::getFdFromDevPath() {
+ int fd = open(mDevPath.c_str(), O_RDWR);
+ if (fd < 0) {
+ ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
+ strerror(errno));
return fd;
}
+ if (int ret = SetTerminalRaw(fd) < 0) {
+ ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
+ strerror(errno));
+ }
+ return fd;
+}
- void reset() {
- // Send a reset command and wait until the command complete comes back.
+void BluetoothHci::reset() {
+ // Send a reset command and wait until the command complete comes back.
- std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
+ std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
- auto resetPromise = std::make_shared<std::promise<void>>();
- auto resetFuture = resetPromise->get_future();
+ auto resetPromise = std::make_shared<std::promise<void>>();
+ auto resetFuture = resetPromise->get_future();
- mH4 = std::make_shared<H4Protocol>(
- mFd,
- [](const std::vector<uint8_t>& raw_command) {
- ALOGI("Discarding %d bytes with command type",
- static_cast<int>(raw_command.size()));
- },
- [](const std::vector<uint8_t>& raw_acl) {
- ALOGI("Discarding %d bytes with acl type",
- static_cast<int>(raw_acl.size()));
- },
- [](const std::vector<uint8_t>& raw_sco) {
- ALOGI("Discarding %d bytes with sco type",
- static_cast<int>(raw_sco.size()));
- },
- [resetPromise](const std::vector<uint8_t>& raw_event) {
- std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
- 0x03, 0x0c, 0x00};
- bool valid = raw_event.size() == 6 &&
- raw_event[0] == reset_complete[0] &&
- raw_event[1] == reset_complete[1] &&
- // Don't compare the number of packets field.
- raw_event[3] == reset_complete[3] &&
- raw_event[4] == reset_complete[4] &&
- raw_event[5] == reset_complete[5];
- if (valid) {
- resetPromise->set_value();
- } else {
- ALOGI("Discarding %d bytes with event type",
- static_cast<int>(raw_event.size()));
- }
- },
- [](const std::vector<uint8_t>& raw_iso) {
- ALOGI("Discarding %d bytes with iso type",
- static_cast<int>(raw_iso.size()));
- },
- [this]() {
- ALOGI("HCI socket device disconnected while waiting for reset");
- mFdWatcher.StopWatchingFileDescriptors();
- });
- mFdWatcher.WatchFdForNonBlockingReads(mFd,
- [this](int) { mH4->OnDataReady(); });
+ mH4 = std::make_shared<H4Protocol>(
+ mFd,
+ [](const std::vector<uint8_t>& raw_command) {
+ ALOGI("Discarding %d bytes with command type",
+ static_cast<int>(raw_command.size()));
+ },
+ [](const std::vector<uint8_t>& raw_acl) {
+ ALOGI("Discarding %d bytes with acl type",
+ static_cast<int>(raw_acl.size()));
+ },
+ [](const std::vector<uint8_t>& raw_sco) {
+ ALOGI("Discarding %d bytes with sco type",
+ static_cast<int>(raw_sco.size()));
+ },
+ [resetPromise](const std::vector<uint8_t>& raw_event) {
+ std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
+ 0x03, 0x0c, 0x00};
+ bool valid = raw_event.size() == 6 &&
+ raw_event[0] == reset_complete[0] &&
+ raw_event[1] == reset_complete[1] &&
+ // Don't compare the number of packets field.
+ raw_event[3] == reset_complete[3] &&
+ raw_event[4] == reset_complete[4] &&
+ raw_event[5] == reset_complete[5];
+ if (valid) {
+ resetPromise->set_value();
+ } else {
+ ALOGI("Discarding %d bytes with event type",
+ static_cast<int>(raw_event.size()));
+ }
+ },
+ [](const std::vector<uint8_t>& raw_iso) {
+ ALOGI("Discarding %d bytes with iso type",
+ static_cast<int>(raw_iso.size()));
+ },
+ [this]() {
+ ALOGI("HCI socket device disconnected while waiting for reset");
+ mFdWatcher.StopWatchingFileDescriptors();
+ });
+ mFdWatcher.WatchFdForNonBlockingReads(mFd,
+ [this](int) { mH4->OnDataReady(); });
- if (!send(PacketType::COMMAND, reset)) {
- ALOGE("Error sending reset command");
- }
- auto status = resetFuture.wait_for(std::chrono::seconds(1));
- mFdWatcher.StopWatchingFileDescriptors();
- if (status == std::future_status::ready) {
- ALOGI("HCI Reset successful");
- } else {
- ALOGE("HCI Reset Response not received in one second");
- }
-
- resetPromise.reset();
+ send(PacketType::COMMAND, reset);
+ auto status = resetFuture.wait_for(std::chrono::seconds(1));
+ mFdWatcher.StopWatchingFileDescriptors();
+ if (status == std::future_status::ready) {
+ ALOGI("HCI Reset successful");
+ } else {
+ ALOGE("HCI Reset Response not received in one second");
}
- void Initialize(const struct hal_callbacks* callbacks) {
- ALOGI(__func__);
+ resetPromise.reset();
+}
- HalState old_state = HalState::READY;
- {
- std::lock_guard<std::mutex> guard(mStateMutex);
- if (mState != HalState::READY) {
- old_state = mState;
- } else {
- mState = HalState::INITIALIZING;
- }
- }
+void BluetoothHci::initialize(
+ const std::shared_ptr<hal::IBluetoothHciCallbacks>& cb) {
+ ALOGI(__func__);
- if (old_state != HalState::READY) {
- ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
- Close();
- callbacks->initialization_complete(callbacks->handle,
- STATUS_ALREADY_INITIALIZED);
- return;
- }
-
- mCallbacks = std::make_unique<struct hal_callbacks>(*callbacks);
- management_.reset(new NetBluetoothMgmt);
- mFd = management_->openHci();
- if (mFd < 0) {
- management_.reset();
-
- ALOGI("Unable to open Linux interface, trying default path.");
- mFd = getFdFromDevPath();
- if (mFd < 0) {
- mState = HalState::READY;
- mCallbacks->initialization_complete(mCallbacks->handle,
- STATUS_UNABLE_TO_OPEN_INTERFACE);
- return;
- }
- }
-
- // TODO: HCI Reset on emulators since the bluetooth controller
- // cannot be powered on/off during the HAL setup; and the stack
- // might received spurious packets/events during boottime.
- // Proper solution would be to use bt-virtio or vsock to better
- // control the link to rootcanal and the controller lifetime.
- const std::string kBoardProperty = "ro.product.board";
- const std::string kCuttlefishBoard = "cutf";
- auto board_name = GetSystemProperty(kBoardProperty);
- if (board_name.has_value() &&
- (starts_with(board_name.value(), "cutf") ||
- starts_with(board_name.value(), "goldfish"))) {
- reset();
- }
-
- mH4 = std::make_shared<H4Protocol>(
- mFd,
- [](const std::vector<uint8_t>& /* raw_command */) {
- LOG_ALWAYS_FATAL("Unexpected command!");
- },
- [this](const std::vector<uint8_t>& raw_acl) {
- mCallbacks->acl_received(mCallbacks->handle, raw_acl.data(),
- raw_acl.size());
- },
- [this](const std::vector<uint8_t>& raw_sco) {
- mCallbacks->sco_received(mCallbacks->handle, raw_sco.data(),
- raw_sco.size());
- },
- [this](const std::vector<uint8_t>& raw_event) {
- mCallbacks->event_received(mCallbacks->handle, raw_event.data(),
- raw_event.size());
- },
- [this](const std::vector<uint8_t>& raw_iso) {
- mCallbacks->iso_received(mCallbacks->handle, raw_iso.data(),
- raw_iso.size());
- },
- [this]() {
- ALOGI("HCI socket device disconnected");
- mFdWatcher.StopWatchingFileDescriptors();
- });
- mFdWatcher.WatchFdForNonBlockingReads(mFd,
- [this](int) { mH4->OnDataReady(); });
-
- {
- std::lock_guard<std::mutex> guard(mStateMutex);
- mState = HalState::ONE_CLIENT;
- }
-
- ALOGI("initialization complete");
- mCallbacks->initialization_complete(mCallbacks->handle, STATUS_SUCCESS);
+ if (cb == nullptr) {
+ ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+ abort();
}
- void Close() {
- ALOGI(__func__);
- {
- std::lock_guard<std::mutex> guard(mStateMutex);
- if (mState != HalState::ONE_CLIENT) {
- LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
- "mState is INITIALIZING");
- ALOGI("Already closed");
- return;
- }
- mCallbacks.reset();
- mState = HalState::CLOSING;
- }
-
- mFdWatcher.StopWatchingFileDescriptors();
-
- if (management_) {
- management_->closeHci();
- } else {
- ::close(mFd);
- }
-
- {
- std::lock_guard<std::mutex> guard(mStateMutex);
- mState = HalState::READY;
- mH4 = nullptr;
- }
- }
-
- void SendCommand(const std::vector<uint8_t>& data) {
- send(PacketType::COMMAND, data);
- }
- void SendAcl(const std::vector<uint8_t>& data) {
- send(PacketType::ACL_DATA, data);
- }
- void SendSco(const std::vector<uint8_t>& data) {
- send(PacketType::SCO_DATA, data);
- }
- void SendIso(const std::vector<uint8_t>& data) {
- send(PacketType::ISO_DATA, data);
- }
-
- bool send(PacketType type, const std::vector<uint8_t>& v) {
- if (v.empty()) {
- ALOGE("Packet is empty, no data was found to be sent");
- return false;
- }
-
+ HalState old_state = HalState::READY;
+ {
std::lock_guard<std::mutex> guard(mStateMutex);
- if (mH4 == nullptr) {
- ALOGE("Illegal State");
- return false;
+ if (mState != HalState::READY) {
+ old_state = mState;
+ } else {
+ mState = HalState::INITIALIZING;
}
-
- mH4->Send(type, v);
- return true;
}
- std::unique_ptr<struct hal_callbacks> mCallbacks;
- std::string mDevPath;
- int mFd{-1};
- ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
- std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
- std::unique_ptr<NetBluetoothMgmt> management_{};
+ if (old_state != HalState::READY) {
+ ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
+ close();
+ cb->initializationComplete(Status::ALREADY_INITIALIZED);
+ }
- // Don't close twice or open before close is complete
- std::mutex mStateMutex;
- enum class HalState {
- READY,
- INITIALIZING,
- ONE_CLIENT,
- CLOSING,
- } mState{HalState::READY};
-};
+ mCb = cb;
+ management_.reset(new NetBluetoothMgmt);
+ mFd = management_->openHci();
+ if (mFd < 0) {
+ management_.reset();
+
+ ALOGI("Unable to open Linux interface, trying default path.");
+ mFd = getFdFromDevPath();
+ if (mFd < 0) {
+ mState = HalState::READY;
+ cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
+ }
+ }
+
+ // TODO: HCI Reset on emulators since the bluetooth controller
+ // cannot be powered on/off during the HAL setup; and the stack
+ // might received spurious packets/events during boottime.
+ // Proper solution would be to use bt-virtio or vsock to better
+ // control the link to rootcanal and the controller lifetime.
+ const std::string kBoardProperty = "ro.product.board";
+ const std::string kCuttlefishBoard = "cutf";
+ auto board_name = GetSystemProperty(kBoardProperty);
+ if (board_name.has_value() && (
+ starts_with(board_name.value(), "cutf") ||
+ starts_with(board_name.value(), "goldfish"))) {
+ reset();
+ }
+
+ mH4 = std::make_shared<H4Protocol>(
+ mFd,
+ [](const std::vector<uint8_t>& /* raw_command */) {
+ LOG_ALWAYS_FATAL("Unexpected command!");
+ },
+ [this](const std::vector<uint8_t>& raw_acl) {
+ mCb->aclDataReceived(raw_acl);
+ },
+ [this](const std::vector<uint8_t>& raw_sco) {
+ mCb->scoDataReceived(raw_sco);
+ },
+ [this](const std::vector<uint8_t>& raw_event) {
+ mCb->hciEventReceived(raw_event);
+ },
+ [this](const std::vector<uint8_t>& raw_iso) {
+ mCb->isoDataReceived(raw_iso);
+ },
+ [this]() {
+ ALOGI("HCI socket device disconnected");
+ mFdWatcher.StopWatchingFileDescriptors();
+ });
+ mFdWatcher.WatchFdForNonBlockingReads(mFd,
+ [this](int) { mH4->OnDataReady(); });
+
+ {
+ std::lock_guard<std::mutex> guard(mStateMutex);
+ mState = HalState::ONE_CLIENT;
+ }
+ ALOGI("initialization complete");
+ mCb->initializationComplete(Status::SUCCESS);
+}
+
+void BluetoothHci::close() {
+ ALOGI(__func__);
+ {
+ std::lock_guard<std::mutex> guard(mStateMutex);
+ if (mState != HalState::ONE_CLIENT) {
+ LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
+ "mState is INITIALIZING");
+ ALOGI("Already closed");
+ }
+ mState = HalState::CLOSING;
+ }
+
+ mFdWatcher.StopWatchingFileDescriptors();
+
+ if (management_) {
+ management_->closeHci();
+ } else {
+ ::close(mFd);
+ }
+
+ {
+ std::lock_guard<std::mutex> guard(mStateMutex);
+ mState = HalState::READY;
+ mH4 = nullptr;
+ }
+}
+
+void BluetoothHci::clientDied() {
+ ALOGI(__func__);
+ close();
+}
+
+void BluetoothHci::sendHciCommand(const std::vector<uint8_t>& packet) {
+ return send(PacketType::COMMAND, packet);
+}
+
+void BluetoothHci::sendAclData(const std::vector<uint8_t>& packet) {
+ return send(PacketType::ACL_DATA, packet);
+}
+
+void BluetoothHci::sendScoData(const std::vector<uint8_t>& packet) {
+ return send(PacketType::SCO_DATA, packet);
+}
+
+void BluetoothHci::sendIsoData(const std::vector<uint8_t>& packet) {
+ return send(PacketType::ISO_DATA, packet);
+}
+
+void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
+ if (v.empty()) {
+ ALOGE("Packet is empty, no data was found to be sent");
+ abort();
+ }
+
+ std::lock_guard<std::mutex> guard(mStateMutex);
+ if (mH4 == nullptr) {
+ ALOGE("Illegal State");
+ abort();
+ }
+
+ mH4->Send(type, v);
+}
} // namespace aidl::android::hardware::bluetooth::impl
-
-extern "C" {
-
-using namespace aidl::android::hardware::bluetooth::impl;
-
-struct hal_interface hal_new() {
- return (struct hal_interface){
- .handle = new Hal(),
- .initialize = &Hal::Initialize,
- .close = &Hal::Close,
- .send_command = &Hal::SendCommand,
- .send_acl = &Hal::SendAcl,
- .send_sco = &Hal::SendSco,
- .send_iso = &Hal::SendIso,
- };
-}
-}
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
new file mode 100644
index 0000000..5c31468
--- /dev/null
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hal/ffi.h>
+
+#include <future>
+#include <string>
+
+#include "async_fd_watcher.h"
+#include "h4_protocol.h"
+#include "net_bluetooth_mgmt.h"
+
+namespace aidl::android::hardware::bluetooth::impl {
+
+// This Bluetooth HAL implementation connects with a serial port at dev_path_.
+class BluetoothHci : public hal::IBluetoothHci {
+ public:
+ BluetoothHci(const std::string& dev_path = "/dev/hvc5");
+
+ void initialize(
+ const std::shared_ptr<hal::IBluetoothHciCallbacks>& cb) override;
+
+ void sendHciCommand(const std::vector<uint8_t>& packet) override;
+
+ void sendAclData(const std::vector<uint8_t>& packet) override;
+
+ void sendScoData(const std::vector<uint8_t>& packet) override;
+
+ void sendIsoData(const std::vector<uint8_t>& packet) override;
+
+ void close() override;
+
+ void clientDied() override;
+
+ static void OnPacketReady();
+
+ static BluetoothHci* get();
+
+ private:
+ int mFd{-1};
+ std::shared_ptr<hal::IBluetoothHciCallbacks> mCb = nullptr;
+
+ std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
+
+ std::string mDevPath;
+
+ ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
+
+ int getFdFromDevPath();
+ void send(::android::hardware::bluetooth::hci::PacketType type,
+ const std::vector<uint8_t>& packet);
+ std::unique_ptr<NetBluetoothMgmt> management_{};
+
+ // Send a reset command and discard all packets until a reset is received.
+ void reset();
+
+ // Don't close twice or open before close is complete
+ std::mutex mStateMutex;
+ enum class HalState {
+ READY,
+ INITIALIZING,
+ ONE_CLIENT,
+ CLOSING,
+ } mState{HalState::READY};
+};
+
+} // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/main.rs b/bluetooth/aidl/default/main.rs
deleted file mode 100644
index b30162a..0000000
--- a/bluetooth/aidl/default/main.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2024, 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.
-
-use android_hardware_bluetooth::aidl::android::hardware::bluetooth::IBluetoothHci::{
- self,
- IBluetoothHci as _
-};
-use android_hardware_bluetooth::binder;
-use bluetooth_offload_hal::{ HciHalProxy, CInterface };
-use bluetooth_offload_leaudio_hci::LeAudioModuleBuilder;
-use log;
-use std::panic;
-
-fn new_hal() -> CInterface {
- extern "C" { fn hal_new() -> CInterface; }
- unsafe { hal_new() }
-}
-
-fn main() {
- logger::init(
- logger::Config::default()
- .with_max_level(log::LevelFilter::Debug)
- .with_tag_on_device("android.hardware.bluetooth"),
- );
-
- panic::set_hook(Box::new(|panic_info| {
- log::error!("{}", panic_info);
- }));
-
- log::info!("Bluetooth HAL starting up");
-
- binder::ProcessState::set_thread_pool_max_thread_count(0);
- binder::ProcessState::start_thread_pool();
-
- binder::add_service(
- &format!("{}/default", IBluetoothHci::BpBluetoothHci::get_descriptor()),
- IBluetoothHci::BnBluetoothHci::new_binder(
- HciHalProxy::new(
- vec![ Box::new(LeAudioModuleBuilder {}) ],
- new_hal()
- ),
- binder::BinderFeatures::default(),
- ).as_binder()
- ).expect("Failed to register service");
-
- binder::ProcessState::join_thread_pool();
-}
diff --git a/bluetooth/aidl/default/service.cpp b/bluetooth/aidl/default/service.cpp
new file mode 100644
index 0000000..9e1a22c
--- /dev/null
+++ b/bluetooth/aidl/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "aidl.android.hardware.bluetooth.service.default"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BluetoothHci.h"
+
+using ::aidl::android::hardware::bluetooth::hal::IBluetoothHci_addService;
+using ::aidl::android::hardware::bluetooth::impl::BluetoothHci;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+
+int main(int /* argc */, char** /* argv */) {
+ ALOGI("Bluetooth HAL starting");
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(0)) {
+ ALOGI("failed to set thread pool max thread count");
+ return 1;
+ }
+
+ IBluetoothHci_addService(new BluetoothHci());
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
index 6b9046c..10c347b 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
@@ -102,7 +102,7 @@
kBlockLength16
};
-enum { kSubbands8 = kSubbands.first, kSubbands4 };
+enum { kSubbands4 = kSubbands.first, kSubbands8 };
enum {
kAllocationMethodSnr = kAllocationMethod.first,
@@ -486,7 +486,7 @@
}
min_bitpool = std::max(min_bitpool, uint8_t(lcaps.get(kMinimumBitpool)));
- max_bitpool = std::max(max_bitpool, uint8_t(lcaps.get(kMaximumBitpool)));
+ max_bitpool = std::min(max_bitpool, uint8_t(lcaps.get(kMaximumBitpool)));
if (hint) {
min_bitpool =
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index 8d03fae..d68113d 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -78,8 +78,7 @@
cookie);
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
- onSessionReady(_aidl_return);
- return ndk::ScopedAStatus::ok();
+ return onSessionReady(_aidl_return);
}
ndk::ScopedAStatus BluetoothAudioProvider::endSession() {
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 3f1f5f6..3d7c376 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -123,40 +123,6 @@
return (sessionType == session_type_);
}
-std::string getSettingOutputString(
- IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting) {
- std::stringstream ss;
- std::string name = "";
- if (!setting.sinkAseConfiguration.has_value() &&
- !setting.sourceAseConfiguration.has_value())
- return "";
- std::vector<
- std::optional<LeAudioAseConfigurationSetting::AseDirectionConfiguration>>*
- directionAseConfiguration;
- if (setting.sinkAseConfiguration.has_value() &&
- !setting.sinkAseConfiguration.value().empty())
- directionAseConfiguration = &setting.sinkAseConfiguration.value();
- else
- directionAseConfiguration = &setting.sourceAseConfiguration.value();
- for (auto& aseConfiguration : *directionAseConfiguration) {
- if (aseConfiguration.has_value() &&
- aseConfiguration.value().aseConfiguration.metadata.has_value()) {
- for (auto& meta :
- aseConfiguration.value().aseConfiguration.metadata.value()) {
- if (meta.has_value() &&
- meta.value().getTag() == MetadataLtv::vendorSpecific) {
- auto k = meta.value().get<MetadataLtv::vendorSpecific>().opaqueValue;
- name = std::string(k.begin(), k.end());
- break;
- }
- }
- }
- }
-
- ss << "setting name: " << name << ", setting: " << setting.toString();
- return ss.str();
-}
-
ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
@@ -742,9 +708,11 @@
return filtered_setting;
}
-std::optional<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+std::optional<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
LeAudioOffloadAudioProvider::matchWithRequirement(
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>&
matched_ase_configuration_settings,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
bool isMatchContext, bool isExact, bool isMatchFlags) {
@@ -758,14 +726,15 @@
if (!requirement.flags.has_value()) return std::nullopt;
requirement_flags_bitmask = requirement.flags.value().bitmask;
}
- for (auto& setting : matched_ase_configuration_settings) {
+ for (auto& [setting_name, setting] : matched_ase_configuration_settings) {
// Try to match context.
if (isMatchContext) {
if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
requirement.audioContext.bitmask)
continue;
- LOG(DEBUG) << __func__ << ": Setting with matched context: "
- << getSettingOutputString(setting);
+ LOG(DEBUG) << __func__
+ << ": Setting with matched context: name: " << setting_name
+ << ", setting: " << setting.toString();
}
// Try to match configuration flags
@@ -774,19 +743,20 @@
if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
requirement_flags_bitmask)
continue;
- LOG(DEBUG) << __func__ << ": Setting with matched flags: "
- << getSettingOutputString(setting);
+ LOG(DEBUG) << __func__
+ << ": Setting with matched flags: name: " << setting_name
+ << ", setting: " << setting.toString();
}
auto filtered_ase_configuration_setting =
getRequirementMatchedAseConfigurationSettings(setting, requirement,
isExact);
if (filtered_ase_configuration_setting.has_value()) {
- LOG(INFO) << __func__ << ": Result found: "
- << getSettingOutputString(
- filtered_ase_configuration_setting.value());
+ LOG(INFO) << __func__ << ": Result found: name: " << setting_name
+ << ", setting: "
+ << filtered_ase_configuration_setting.value().toString();
// Found a matched setting, ignore other settings
- return filtered_ase_configuration_setting;
+ return {{setting_name, filtered_ase_configuration_setting.value()}};
}
}
// If cannot satisfy this requirement, return nullopt
@@ -812,7 +782,8 @@
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
_aidl_return) {
// Get all configuration settings
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
ase_configuration_settings =
BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
@@ -822,15 +793,17 @@
}
// Matched ASE configuration with ignored audio context
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
sink_matched_ase_configuration_settings;
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
matched_ase_configuration_settings;
// A setting must match both source and sink.
// First filter all setting matched with sink capability
if (in_remoteSinkAudioCapabilities.has_value()) {
- for (auto& setting : ase_configuration_settings) {
+ for (auto& [setting_name, setting] : ase_configuration_settings) {
for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
@@ -838,7 +811,7 @@
setting, capability.value(), kLeAudioDirectionSink);
if (filtered_ase_configuration_setting.has_value()) {
sink_matched_ase_configuration_settings.push_back(
- filtered_ase_configuration_setting.value());
+ {setting_name, filtered_ase_configuration_setting.value()});
}
}
}
@@ -848,7 +821,8 @@
// Combine filter every source capability
if (in_remoteSourceAudioCapabilities.has_value()) {
- for (auto& setting : sink_matched_ase_configuration_settings)
+ for (auto& [setting_name, setting] :
+ sink_matched_ase_configuration_settings)
for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
@@ -856,7 +830,7 @@
setting, capability.value(), kLeAudioDirectionSource);
if (filtered_ase_configuration_setting.has_value()) {
matched_ase_configuration_settings.push_back(
- filtered_ase_configuration_setting.value());
+ {setting_name, filtered_ase_configuration_setting.value()});
}
}
} else {
@@ -864,7 +838,11 @@
sink_matched_ase_configuration_settings;
}
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ result_no_name;
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
+ result;
for (auto& requirement : in_requirements) {
// For each requirement, try to match with a setting.
// If we cannot match, return an empty result.
@@ -896,18 +874,19 @@
if (!found) {
LOG(ERROR) << __func__
<< ": Cannot find any match for this requirement, exitting...";
- result.clear();
- *_aidl_return = result;
+ *_aidl_return = result_no_name;
return ndk::ScopedAStatus::ok();
}
}
LOG(INFO) << __func__
<< ": Found matches for all requirements, chosen settings:";
- for (auto& setting : result) {
- LOG(INFO) << __func__ << ": " << getSettingOutputString(setting);
+ for (auto& [setting_name, setting] : result) {
+ LOG(INFO) << __func__ << ": name: " << setting_name
+ << ", setting: " << setting.toString();
+ result_no_name.push_back(setting);
}
- *_aidl_return = result;
+ *_aidl_return = result_no_name;
return ndk::ScopedAStatus::ok();
};
@@ -937,7 +916,8 @@
uint8_t direction,
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
- std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+ std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>&
+ ase_configuration_settings,
bool isExact, bool isMatchFlags) {
auto requirement_flags_bitmask = 0;
if (isMatchFlags) {
@@ -955,13 +935,14 @@
direction_qos_requirement = qosRequirement.sourceAseQosRequirement.value();
}
- for (auto& setting : ase_configuration_settings) {
+ for (auto& [setting_name, setting] : ase_configuration_settings) {
// Context matching
if ((setting.audioContext.bitmask & qosRequirement.audioContext.bitmask) !=
qosRequirement.audioContext.bitmask)
continue;
- LOG(DEBUG) << __func__ << ": Setting with matched context: "
- << getSettingOutputString(setting);
+ LOG(DEBUG) << __func__
+ << ": Setting with matched context: name: " << setting_name
+ << ", setting: " << setting.toString();
// Match configuration flags
if (isMatchFlags) {
@@ -969,8 +950,9 @@
if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
requirement_flags_bitmask)
continue;
- LOG(DEBUG) << __func__ << ": Setting with matched flags: "
- << getSettingOutputString(setting);
+ LOG(DEBUG) << __func__
+ << ": Setting with matched flags: name: " << setting_name
+ << ", setting: " << setting.toString();
}
// Get a list of all matched AseDirectionConfiguration
@@ -1041,7 +1023,8 @@
IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
// Get all configuration settings
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ std::vector<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
ase_configuration_settings =
BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 8c4f543..6d402a4 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -163,15 +163,19 @@
uint8_t direction,
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
- std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+ std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>&
+ ase_configuration_settings,
bool isExact, bool isMatchedFlag);
bool isSubgroupConfigurationMatchedContext(
AudioContext requirement_context,
IBluetoothAudioProvider::BroadcastQuality quality,
LeAudioBroadcastSubgroupConfiguration configuration);
- std::optional<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ std::optional<std::pair<
+ std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
matchWithRequirement(
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+ std::vector<
+ std::pair<std::string,
+ IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>&
matched_ase_configuration_settings,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
requirements,
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index db2528e..89472e6 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -452,7 +452,7 @@
return kDefaultOffloadHfpCodecInfo;
}
-std::vector<LeAudioAseConfigurationSetting>
+std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings() {
return AudioSetConfigurationProviderJson::
GetLeAudioAseConfigurationSettings();
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
index 0a1f708..c77de61 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -54,7 +54,7 @@
static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo(
const SessionType& session_type);
- static std::vector<LeAudioAseConfigurationSetting>
+ static std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
GetLeAudioAseConfigurationSettings();
static std::vector<CodecInfo> GetHfpOffloadCodecInfo();
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
index 2474916..feb4cda 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -65,7 +65,8 @@
ConfigurationFlags>>
configurations_;
-std::vector<LeAudioAseConfigurationSetting> ase_configuration_settings_;
+std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
+ ase_configuration_settings_;
constexpr uint8_t kIsoDataPathHci = 0x00;
constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
@@ -273,7 +274,7 @@
/* Implementation */
-std::vector<LeAudioAseConfigurationSetting>
+std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
AudioSetConfigurationProviderJson::GetLeAudioAseConfigurationSettings() {
AudioSetConfigurationProviderJson::LoadAudioSetConfigurationProviderJson();
return ase_configuration_settings_;
@@ -392,7 +393,7 @@
}
void AudioSetConfigurationProviderJson::populateAseConfiguration(
- const std::string& name, LeAudioAseConfiguration& ase,
+ LeAudioAseConfiguration& ase,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg,
ConfigurationFlags& configurationFlags) {
@@ -431,12 +432,6 @@
}
// Codec configuration data
populateConfigurationData(ase, flat_subconfig->codec_configuration());
- // Populate the config name for easier debug
- auto meta = std::vector<std::optional<MetadataLtv>>();
- MetadataLtv::VendorSpecific cfg_name;
- cfg_name.opaqueValue = std::vector<uint8_t>(name.begin(), name.end());
- meta.push_back(cfg_name);
- ase.metadata = meta;
}
void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
@@ -507,7 +502,6 @@
// Parse into AseDirectionConfiguration
AseDirectionConfiguration
AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
- const std::string& name,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg, CodecLocation location,
ConfigurationFlags& configurationFlags) {
@@ -518,8 +512,7 @@
LeAudioDataPathConfiguration path;
// Translate into LeAudioAseConfiguration
- populateAseConfiguration(name, ase, flat_subconfig, qos_cfg,
- configurationFlags);
+ populateAseConfiguration(ase, flat_subconfig, qos_cfg, configurationFlags);
// Translate into LeAudioAseQosConfiguration
populateAseQosConfiguration(qos, qos_cfg, ase,
@@ -553,15 +546,14 @@
// Parse into AseDirectionConfiguration and the ConfigurationFlags
// and put them in the given list.
void AudioSetConfigurationProviderJson::processSubconfig(
- const std::string& name,
const le_audio::AudioSetSubConfiguration* subconfig,
const le_audio::QosConfiguration* qos_cfg,
std::vector<std::optional<AseDirectionConfiguration>>&
directionAseConfiguration,
CodecLocation location, ConfigurationFlags& configurationFlags) {
auto ase_cnt = subconfig->ase_cnt();
- auto config = SetConfigurationFromFlatSubconfig(name, subconfig, qos_cfg,
- location, configurationFlags);
+ auto config = SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location,
+ configurationFlags);
directionAseConfiguration.push_back(config);
// Put the same setting again.
if (ase_cnt == 2) directionAseConfiguration.push_back(config);
@@ -646,11 +638,11 @@
/* Load subconfigurations */
for (auto subconfig : *codec_cfg->subconfigurations()) {
if (subconfig->direction() == kLeAudioDirectionSink) {
- processSubconfig(flat_cfg->name()->str(), subconfig, qos_sink_cfg,
- sinkAseConfiguration, location, configurationFlags);
+ processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
+ location, configurationFlags);
} else {
- processSubconfig(flat_cfg->name()->str(), subconfig, qos_source_cfg,
- sourceAseConfiguration, location, configurationFlags);
+ processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
+ location, configurationFlags);
}
}
@@ -860,7 +852,7 @@
setting.flags = flags;
// Add to list of setting
LOG(DEBUG) << "Pushing configuration to list: " << config_name;
- ase_configuration_settings_.push_back(setting);
+ ase_configuration_settings_.push_back({config_name, setting});
}
}
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
index 8e12618..f115d61 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
@@ -50,7 +50,7 @@
class AudioSetConfigurationProviderJson {
public:
- static std::vector<LeAudioAseConfigurationSetting>
+ static std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
GetLeAudioAseConfigurationSettings();
private:
@@ -73,7 +73,7 @@
flat_codec_specific_params);
static void populateAseConfiguration(
- const std::string& name, LeAudioAseConfiguration& ase,
+ LeAudioAseConfiguration& ase,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg,
ConfigurationFlags& configurationFlags);
@@ -84,13 +84,11 @@
uint8_t ase_channel_cnt);
static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
- const std::string& name,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg, CodecLocation location,
ConfigurationFlags& configurationFlags);
static void processSubconfig(
- const std::string& name,
const le_audio::AudioSetSubConfiguration* subconfig,
const le_audio::QosConfiguration* qos_cfg,
std::vector<std::optional<AseDirectionConfiguration>>&
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
index 003da11..9cd63d6 100644
--- a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
@@ -37,8 +37,9 @@
/**
* The value used by the Host stack for the local Maximum Packet Size shall be the value
* LE_ACL_Data_Packet_Length returned by the controller in response to the command HCI LE Read
- * Buffer Size. Then, the MPS size must be in range 1 to 255. We do not make the MPS
- * configurable in HAL because using the maximum value does not require a large amount of
- * memory.
+ * Buffer Size if Total_Num_LE_ACL_Data_Packets is not zero. The MPS shall be the value
+ * ACL_Data_Packet_Length returned in response to the command HCI Read Buffer Size if
+ * Total_Num_LE_ACL_Data_Packets is zero. We do not make the MPS configurable in HAL because
+ * using the maximum value does not require a large amount of memory.
*/
}
diff --git a/broadcastradio/aidl/OWNERS b/broadcastradio/aidl/OWNERS
index 302fdd7..51a85e4 100644
--- a/broadcastradio/aidl/OWNERS
+++ b/broadcastradio/aidl/OWNERS
@@ -1,4 +1,3 @@
xuweilin@google.com
oscarazu@google.com
ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/aidl/vts/OWNERS b/broadcastradio/aidl/vts/OWNERS
index 302fdd7..51a85e4 100644
--- a/broadcastradio/aidl/vts/OWNERS
+++ b/broadcastradio/aidl/vts/OWNERS
@@ -1,4 +1,3 @@
xuweilin@google.com
oscarazu@google.com
ericjeong@google.com
-keunyoung@google.com
diff --git a/configstore/OWNERS b/configstore/OWNERS
index 70ad434..74789b5 100644
--- a/configstore/OWNERS
+++ b/configstore/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 24939
-lpy@google.com
diff --git a/confirmationui/1.0/default/OWNERS b/confirmationui/1.0/default/OWNERS
index 17aed51..d8b8840 100644
--- a/confirmationui/1.0/default/OWNERS
+++ b/confirmationui/1.0/default/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1124672
-jdanis@google.com
swillden@google.com
diff --git a/confirmationui/1.0/vts/OWNERS b/confirmationui/1.0/vts/OWNERS
index aa07242..b0ee996 100644
--- a/confirmationui/1.0/vts/OWNERS
+++ b/confirmationui/1.0/vts/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 1124672
-jdanis@google.com
swillden@google.com
yim@google.com
diff --git a/confirmationui/support/OWNERS b/confirmationui/support/OWNERS
index 17aed51..d8b8840 100644
--- a/confirmationui/support/OWNERS
+++ b/confirmationui/support/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1124672
-jdanis@google.com
swillden@google.com
diff --git a/gatekeeper/1.0/default/OWNERS b/gatekeeper/1.0/default/OWNERS
index c97fba6..d552a9a 100644
--- a/gatekeeper/1.0/default/OWNERS
+++ b/gatekeeper/1.0/default/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1124862
-jdanis@google.com
swillden@google.com
diff --git a/gatekeeper/1.0/software/OWNERS b/gatekeeper/1.0/software/OWNERS
index c97fba6..d552a9a 100644
--- a/gatekeeper/1.0/software/OWNERS
+++ b/gatekeeper/1.0/software/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1124862
-jdanis@google.com
swillden@google.com
diff --git a/gnss/OWNERS b/gnss/OWNERS
index 57982e7..2c54f9f 100644
--- a/gnss/OWNERS
+++ b/gnss/OWNERS
@@ -2,7 +2,6 @@
gomo@google.com
smalkos@google.com
-trong@google.com
wyattriley@google.com
yim@google.com
yuhany@google.com
diff --git a/graphics/OWNERS b/graphics/OWNERS
index 1cb6015..9ba1ee0 100644
--- a/graphics/OWNERS
+++ b/graphics/OWNERS
@@ -5,6 +5,4 @@
alecmouri@google.com
chrisforbes@google.com
jreck@google.com
-lpy@google.com
-scroggo@google.com
-sumir@google.com
\ No newline at end of file
+sumir@google.com
diff --git a/graphics/composer/aidl/libhwc_aidl_test/Android.bp b/graphics/composer/aidl/libhwc_aidl_test/Android.bp
new file mode 100644
index 0000000..1955fcf
--- /dev/null
+++ b/graphics/composer/aidl/libhwc_aidl_test/Android.bp
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2025, 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 {
+ default_team: "trendy_team_android_core_graphics_stack",
+ // 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
+}
+
+cc_library_static {
+ name: "libhwc_aidl_test",
+ export_include_dirs: ["include"],
+ defaults: [
+ "use_libaidlvintf_gtest_helper_static",
+ "librenderengine_deps",
+ "android.hardware.graphics.common-ndk_static",
+ "android.hardware.graphics.composer3-ndk_static",
+ ],
+ srcs: [
+ "ComposerClientWrapper.cpp",
+ "GraphicsComposerCallback.cpp",
+ "Readback.cpp",
+ "RenderEngine.cpp",
+ ],
+ shared_libs: [
+ "libEGL",
+ "libGLESv2",
+ "libbinder_ndk",
+ "libbinder",
+ "libfmq",
+ "libbase",
+ "libsync",
+ "libui",
+ "libgui",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer3-command-buffer",
+ ],
+ static_libs: [
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "libaidlcommonsupport",
+ "libarect",
+ "libbase",
+ "libfmq",
+ "libgtest",
+ "librenderengine",
+ "libsync",
+ "libsurfaceflinger_common",
+ ],
+ cflags: [
+ "-Wconversion",
+ ],
+}
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp
similarity index 65%
rename from graphics/composer/aidl/vts/VtsComposerClient.cpp
rename to graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp
index 89ba2e6..a81af8f 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-#include "VtsComposerClient.h"
+#include "ComposerClientWrapper.h"
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
#include <log/log_main.h>
#undef LOG_TAG
-#define LOG_TAG "VtsComposerClient"
+#define LOG_TAG "ComposerClientWrapper"
using namespace std::chrono_literals;
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
-VtsComposerClient::VtsComposerClient(const std::string& name) {
+ComposerClientWrapper::ComposerClientWrapper(const std::string& name) {
SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
ALOGE_IF(binder == nullptr, "Could not initialize the service binder");
if (binder != nullptr) {
@@ -43,7 +43,7 @@
}
}
-ScopedAStatus VtsComposerClient::createClient() {
+ScopedAStatus ComposerClientWrapper::createClient() {
if (mComposer == nullptr) {
ALOGE("IComposer not initialized");
return ScopedAStatus::fromServiceSpecificError(IComposerClient::INVALID_CONFIGURATION);
@@ -62,11 +62,12 @@
return mComposerClient->registerCallback(mComposerCallback);
}
-bool VtsComposerClient::tearDown(ComposerClientWriter* writer) {
- return verifyComposerCallbackParams() && destroyAllLayers(writer);
+bool ComposerClientWrapper::tearDown(
+ std::unordered_map<int64_t, ComposerClientWriter*> displayWriters) {
+ return verifyComposerCallbackParams() && destroyAllLayers(displayWriters);
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() const {
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getInterfaceVersion() const {
int32_t version = 1;
if (!mComposerClient) {
return {ScopedAStatus{nullptr}, version};
@@ -75,7 +76,7 @@
return {std::move(status), version};
}
-std::pair<ScopedAStatus, VirtualDisplay> VtsComposerClient::createVirtualDisplay(
+std::pair<ScopedAStatus, VirtualDisplay> ComposerClientWrapper::createVirtualDisplay(
int32_t width, int32_t height, PixelFormat pixelFormat, int32_t bufferSlotCount) {
VirtualDisplay outVirtualDisplay;
auto status = mComposerClient->createVirtualDisplay(width, height, pixelFormat, bufferSlotCount,
@@ -87,7 +88,7 @@
outVirtualDisplay};
}
-ScopedAStatus VtsComposerClient::destroyVirtualDisplay(int64_t display) {
+ScopedAStatus ComposerClientWrapper::destroyVirtualDisplay(int64_t display) {
auto status = mComposerClient->destroyVirtualDisplay(display);
if (!status.isOk()) {
return status;
@@ -96,9 +97,9 @@
return status;
}
-std::pair<ScopedAStatus, int64_t> VtsComposerClient::createLayer(int64_t display,
- int32_t bufferSlotCount,
- ComposerClientWriter* writer) {
+std::pair<ScopedAStatus, int64_t> ComposerClientWrapper::createLayer(int64_t display,
+ int32_t bufferSlotCount,
+ ComposerClientWriter* writer) {
if (mSupportsBatchedCreateLayer) {
int64_t layer = mNextLayerHandle++;
writer->setLayerLifecycleBatchCommandType(display, layer,
@@ -116,8 +117,8 @@
return {addLayerToDisplayResources(display, outLayer), outLayer};
}
-ScopedAStatus VtsComposerClient::destroyLayer(int64_t display, int64_t layer,
- ComposerClientWriter* writer) {
+ScopedAStatus ComposerClientWrapper::destroyLayer(int64_t display, int64_t layer,
+ ComposerClientWriter* writer) {
if (mSupportsBatchedCreateLayer) {
writer->setLayerLifecycleBatchCommandType(display, layer,
LayerLifecycleBatchCommandType::DESTROY);
@@ -132,27 +133,27 @@
return ScopedAStatus::ok();
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getActiveConfig(int64_t display) {
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getActiveConfig(int64_t display) {
int32_t outConfig;
return {mComposerClient->getActiveConfig(display, &outConfig), outConfig};
}
-ScopedAStatus VtsComposerClient::setActiveConfig(VtsDisplay* vtsDisplay, int32_t config) {
- auto status = mComposerClient->setActiveConfig(vtsDisplay->getDisplayId(), config);
+ScopedAStatus ComposerClientWrapper::setActiveConfig(DisplayWrapper* display, int32_t config) {
+ auto status = mComposerClient->setActiveConfig(display->getDisplayId(), config);
if (!status.isOk()) {
return status;
}
- return updateDisplayProperties(vtsDisplay, config);
+ return updateDisplayProperties(display, config);
}
-ScopedAStatus VtsComposerClient::setPeakRefreshRateConfig(VtsDisplay* vtsDisplay) {
- const auto displayId = vtsDisplay->getDisplayId();
+ScopedAStatus ComposerClientWrapper::setPeakRefreshRateConfig(DisplayWrapper* display) {
+ const auto displayId = display->getDisplayId();
auto [activeStatus, activeConfig] = getActiveConfig(displayId);
EXPECT_TRUE(activeStatus.isOk());
- auto peakDisplayConfig = vtsDisplay->getDisplayConfig(activeConfig);
+ auto peakDisplayConfig = display->getDisplayConfig(activeConfig);
auto peakConfig = activeConfig;
- const auto displayConfigs = vtsDisplay->getDisplayConfigs();
+ const auto displayConfigs = display->getDisplayConfigs();
for (const auto [config, displayConfig] : displayConfigs) {
if (displayConfig.configGroup == peakDisplayConfig.configGroup &&
displayConfig.vsyncPeriod < peakDisplayConfig.vsyncPeriod) {
@@ -160,10 +161,10 @@
peakConfig = config;
}
}
- return setActiveConfig(vtsDisplay, peakConfig);
+ return setActiveConfig(display, peakConfig);
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayAttribute(
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getDisplayAttribute(
int64_t display, int32_t config, DisplayAttribute displayAttribute) {
int32_t outDisplayAttribute;
return {mComposerClient->getDisplayAttribute(display, config, displayAttribute,
@@ -171,58 +172,59 @@
outDisplayAttribute};
}
-ScopedAStatus VtsComposerClient::setPowerMode(int64_t display, PowerMode powerMode) {
+ScopedAStatus ComposerClientWrapper::setPowerMode(int64_t display, PowerMode powerMode) {
return mComposerClient->setPowerMode(display, powerMode);
}
-ScopedAStatus VtsComposerClient::setVsync(int64_t display, bool enable) {
+ScopedAStatus ComposerClientWrapper::setVsync(int64_t display, bool enable) {
return mComposerClient->setVsyncEnabled(display, enable);
}
-void VtsComposerClient::setVsyncAllowed(bool isAllowed) {
+void ComposerClientWrapper::setVsyncAllowed(bool isAllowed) {
mComposerCallback->setVsyncAllowed(isAllowed);
}
-std::pair<ScopedAStatus, std::vector<float>> VtsComposerClient::getDataspaceSaturationMatrix(
+std::pair<ScopedAStatus, std::vector<float>> ComposerClientWrapper::getDataspaceSaturationMatrix(
Dataspace dataspace) {
std::vector<float> outMatrix;
return {mComposerClient->getDataspaceSaturationMatrix(dataspace, &outMatrix), outMatrix};
}
-std::pair<ScopedAStatus, std::vector<CommandResultPayload>> VtsComposerClient::executeCommands(
+std::pair<ScopedAStatus, std::vector<CommandResultPayload>> ComposerClientWrapper::executeCommands(
const std::vector<DisplayCommand>& commands) {
std::vector<CommandResultPayload> outResultPayload;
return {mComposerClient->executeCommands(commands, &outResultPayload),
std::move(outResultPayload)};
}
-std::optional<VsyncPeriodChangeTimeline> VtsComposerClient::takeLastVsyncPeriodChangeTimeline() {
+std::optional<VsyncPeriodChangeTimeline>
+ComposerClientWrapper::takeLastVsyncPeriodChangeTimeline() {
return mComposerCallback->takeLastVsyncPeriodChangeTimeline();
}
-ScopedAStatus VtsComposerClient::setContentType(int64_t display, ContentType contentType) {
+ScopedAStatus ComposerClientWrapper::setContentType(int64_t display, ContentType contentType) {
return mComposerClient->setContentType(display, contentType);
}
std::pair<ScopedAStatus, VsyncPeriodChangeTimeline>
-VtsComposerClient::setActiveConfigWithConstraints(VtsDisplay* vtsDisplay, int32_t config,
- const VsyncPeriodChangeConstraints& constraints) {
+ComposerClientWrapper::setActiveConfigWithConstraints(
+ DisplayWrapper* display, int32_t config, const VsyncPeriodChangeConstraints& constraints) {
VsyncPeriodChangeTimeline outTimeline;
- auto status = mComposerClient->setActiveConfigWithConstraints(
- vtsDisplay->getDisplayId(), config, constraints, &outTimeline);
+ auto status = mComposerClient->setActiveConfigWithConstraints(display->getDisplayId(), config,
+ constraints, &outTimeline);
if (!status.isOk()) {
return {std::move(status), outTimeline};
}
- return {updateDisplayProperties(vtsDisplay, config), outTimeline};
+ return {updateDisplayProperties(display, config), outTimeline};
}
-std::pair<ScopedAStatus, std::vector<DisplayCapability>> VtsComposerClient::getDisplayCapabilities(
- int64_t display) {
+std::pair<ScopedAStatus, std::vector<DisplayCapability>>
+ComposerClientWrapper::getDisplayCapabilities(int64_t display) {
std::vector<DisplayCapability> outCapabilities;
return {mComposerClient->getDisplayCapabilities(display, &outCapabilities), outCapabilities};
}
-ScopedAStatus VtsComposerClient::dumpDebugInfo() {
+ScopedAStatus ComposerClientWrapper::dumpDebugInfo() {
int pipefds[2];
if (pipe(pipefds) < 0) {
return ScopedAStatus::fromServiceSpecificError(IComposer::EX_NO_RESOURCES);
@@ -234,76 +236,79 @@
return ScopedAStatus::fromStatus(status);
}
-std::pair<ScopedAStatus, DisplayIdentification> VtsComposerClient::getDisplayIdentificationData(
+std::pair<ScopedAStatus, DisplayIdentification> ComposerClientWrapper::getDisplayIdentificationData(
int64_t display) {
DisplayIdentification outDisplayIdentification;
return {mComposerClient->getDisplayIdentificationData(display, &outDisplayIdentification),
outDisplayIdentification};
}
-std::pair<ScopedAStatus, HdrCapabilities> VtsComposerClient::getHdrCapabilities(int64_t display) {
+std::pair<ScopedAStatus, HdrCapabilities> ComposerClientWrapper::getHdrCapabilities(
+ int64_t display) {
HdrCapabilities outHdrCapabilities;
return {mComposerClient->getHdrCapabilities(display, &outHdrCapabilities), outHdrCapabilities};
}
std::pair<ScopedAStatus, std::vector<PerFrameMetadataKey>>
-VtsComposerClient::getPerFrameMetadataKeys(int64_t display) {
+ComposerClientWrapper::getPerFrameMetadataKeys(int64_t display) {
std::vector<PerFrameMetadataKey> outPerFrameMetadataKeys;
return {mComposerClient->getPerFrameMetadataKeys(display, &outPerFrameMetadataKeys),
outPerFrameMetadataKeys};
}
-std::pair<ScopedAStatus, ReadbackBufferAttributes> VtsComposerClient::getReadbackBufferAttributes(
- int64_t display) {
+std::pair<ScopedAStatus, ReadbackBufferAttributes>
+ComposerClientWrapper::getReadbackBufferAttributes(int64_t display) {
ReadbackBufferAttributes outReadbackBufferAttributes;
return {mComposerClient->getReadbackBufferAttributes(display, &outReadbackBufferAttributes),
outReadbackBufferAttributes};
}
-ScopedAStatus VtsComposerClient::setReadbackBuffer(int64_t display, const native_handle_t* buffer,
- const ScopedFileDescriptor& releaseFence) {
+ScopedAStatus ComposerClientWrapper::setReadbackBuffer(int64_t display,
+ const native_handle_t* buffer,
+ const ScopedFileDescriptor& releaseFence) {
return mComposerClient->setReadbackBuffer(display, ::android::dupToAidl(buffer), releaseFence);
}
-std::pair<ScopedAStatus, ScopedFileDescriptor> VtsComposerClient::getReadbackBufferFence(
+std::pair<ScopedAStatus, ScopedFileDescriptor> ComposerClientWrapper::getReadbackBufferFence(
int64_t display) {
ScopedFileDescriptor outReleaseFence;
return {mComposerClient->getReadbackBufferFence(display, &outReleaseFence),
std::move(outReleaseFence)};
}
-std::pair<ScopedAStatus, std::vector<ColorMode>> VtsComposerClient::getColorModes(int64_t display) {
+std::pair<ScopedAStatus, std::vector<ColorMode>> ComposerClientWrapper::getColorModes(
+ int64_t display) {
std::vector<ColorMode> outColorModes;
return {mComposerClient->getColorModes(display, &outColorModes), outColorModes};
}
-std::pair<ScopedAStatus, std::vector<RenderIntent>> VtsComposerClient::getRenderIntents(
+std::pair<ScopedAStatus, std::vector<RenderIntent>> ComposerClientWrapper::getRenderIntents(
int64_t display, ColorMode colorMode) {
std::vector<RenderIntent> outRenderIntents;
return {mComposerClient->getRenderIntents(display, colorMode, &outRenderIntents),
outRenderIntents};
}
-ScopedAStatus VtsComposerClient::setColorMode(int64_t display, ColorMode colorMode,
- RenderIntent renderIntent) {
+ScopedAStatus ComposerClientWrapper::setColorMode(int64_t display, ColorMode colorMode,
+ RenderIntent renderIntent) {
return mComposerClient->setColorMode(display, colorMode, renderIntent);
}
std::pair<ScopedAStatus, DisplayContentSamplingAttributes>
-VtsComposerClient::getDisplayedContentSamplingAttributes(int64_t display) {
+ComposerClientWrapper::getDisplayedContentSamplingAttributes(int64_t display) {
DisplayContentSamplingAttributes outAttributes;
return {mComposerClient->getDisplayedContentSamplingAttributes(display, &outAttributes),
outAttributes};
}
-ScopedAStatus VtsComposerClient::setDisplayedContentSamplingEnabled(
+ScopedAStatus ComposerClientWrapper::setDisplayedContentSamplingEnabled(
int64_t display, bool isEnabled, FormatColorComponent formatColorComponent,
int64_t maxFrames) {
return mComposerClient->setDisplayedContentSamplingEnabled(display, isEnabled,
formatColorComponent, maxFrames);
}
-std::pair<ScopedAStatus, DisplayContentSample> VtsComposerClient::getDisplayedContentSample(
+std::pair<ScopedAStatus, DisplayContentSample> ComposerClientWrapper::getDisplayedContentSample(
int64_t display, int64_t maxFrames, int64_t timestamp) {
DisplayContentSample outDisplayContentSample;
return {mComposerClient->getDisplayedContentSample(display, maxFrames, timestamp,
@@ -311,14 +316,14 @@
outDisplayContentSample};
}
-std::pair<ScopedAStatus, DisplayConnectionType> VtsComposerClient::getDisplayConnectionType(
+std::pair<ScopedAStatus, DisplayConnectionType> ComposerClientWrapper::getDisplayConnectionType(
int64_t display) {
DisplayConnectionType outDisplayConnectionType;
return {mComposerClient->getDisplayConnectionType(display, &outDisplayConnectionType),
outDisplayConnectionType};
}
-std::pair<ScopedAStatus, std::vector<int32_t>> VtsComposerClient::getDisplayConfigs(
+std::pair<ScopedAStatus, std::vector<int32_t>> ComposerClientWrapper::getDisplayConfigs(
int64_t display) {
std::vector<int32_t> outConfigs;
if (!getDisplayConfigurationSupported()) {
@@ -336,132 +341,131 @@
}
std::pair<ScopedAStatus, std::vector<DisplayConfiguration>>
-VtsComposerClient::getDisplayConfigurations(int64_t display) {
+ComposerClientWrapper::getDisplayConfigurations(int64_t display) {
std::vector<DisplayConfiguration> outConfigs;
return {mComposerClient->getDisplayConfigurations(display, kMaxFrameIntervalNs, &outConfigs),
outConfigs};
}
-ScopedAStatus VtsComposerClient::notifyExpectedPresent(int64_t display,
- ClockMonotonicTimestamp expectedPresentTime,
- int frameIntervalNs) {
+ScopedAStatus ComposerClientWrapper::notifyExpectedPresent(
+ int64_t display, ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs) {
return mComposerClient->notifyExpectedPresent(display, expectedPresentTime, frameIntervalNs);
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getDisplayVsyncPeriod(int64_t display) {
int32_t outVsyncPeriodNanos;
return {mComposerClient->getDisplayVsyncPeriod(display, &outVsyncPeriodNanos),
outVsyncPeriodNanos};
}
-ScopedAStatus VtsComposerClient::setAutoLowLatencyMode(int64_t display, bool isEnabled) {
+ScopedAStatus ComposerClientWrapper::setAutoLowLatencyMode(int64_t display, bool isEnabled) {
return mComposerClient->setAutoLowLatencyMode(display, isEnabled);
}
-std::pair<ScopedAStatus, std::vector<ContentType>> VtsComposerClient::getSupportedContentTypes(
+std::pair<ScopedAStatus, std::vector<ContentType>> ComposerClientWrapper::getSupportedContentTypes(
int64_t display) {
std::vector<ContentType> outContentTypes;
return {mComposerClient->getSupportedContentTypes(display, &outContentTypes), outContentTypes};
}
std::pair<ScopedAStatus, std::optional<DisplayDecorationSupport>>
-VtsComposerClient::getDisplayDecorationSupport(int64_t display) {
+ComposerClientWrapper::getDisplayDecorationSupport(int64_t display) {
std::optional<DisplayDecorationSupport> outSupport;
return {mComposerClient->getDisplayDecorationSupport(display, &outSupport), outSupport};
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getMaxVirtualDisplayCount() {
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getMaxVirtualDisplayCount() {
int32_t outMaxVirtualDisplayCount;
return {mComposerClient->getMaxVirtualDisplayCount(&outMaxVirtualDisplayCount),
outMaxVirtualDisplayCount};
}
-std::pair<ScopedAStatus, std::string> VtsComposerClient::getDisplayName(int64_t display) {
+std::pair<ScopedAStatus, std::string> ComposerClientWrapper::getDisplayName(int64_t display) {
std::string outDisplayName;
return {mComposerClient->getDisplayName(display, &outDisplayName), outDisplayName};
}
-ScopedAStatus VtsComposerClient::setClientTargetSlotCount(int64_t display,
- int32_t bufferSlotCount) {
+ScopedAStatus ComposerClientWrapper::setClientTargetSlotCount(int64_t display,
+ int32_t bufferSlotCount) {
return mComposerClient->setClientTargetSlotCount(display, bufferSlotCount);
}
-std::pair<ScopedAStatus, std::vector<Capability>> VtsComposerClient::getCapabilities() {
+std::pair<ScopedAStatus, std::vector<Capability>> ComposerClientWrapper::getCapabilities() {
std::vector<Capability> outCapabilities;
return {mComposer->getCapabilities(&outCapabilities), outCapabilities};
}
-ScopedAStatus VtsComposerClient::setBootDisplayConfig(int64_t display, int32_t config) {
+ScopedAStatus ComposerClientWrapper::setBootDisplayConfig(int64_t display, int32_t config) {
return mComposerClient->setBootDisplayConfig(display, config);
}
-ScopedAStatus VtsComposerClient::clearBootDisplayConfig(int64_t display) {
+ScopedAStatus ComposerClientWrapper::clearBootDisplayConfig(int64_t display) {
return mComposerClient->clearBootDisplayConfig(display);
}
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getPreferredBootDisplayConfig(
+std::pair<ScopedAStatus, int32_t> ComposerClientWrapper::getPreferredBootDisplayConfig(
int64_t display) {
int32_t outConfig;
return {mComposerClient->getPreferredBootDisplayConfig(display, &outConfig), outConfig};
}
std::pair<ScopedAStatus, std::vector<common::HdrConversionCapability>>
-VtsComposerClient::getHdrConversionCapabilities() {
+ComposerClientWrapper::getHdrConversionCapabilities() {
std::vector<common::HdrConversionCapability> hdrConversionCapability;
return {mComposerClient->getHdrConversionCapabilities(&hdrConversionCapability),
hdrConversionCapability};
}
-std::pair<ScopedAStatus, common::Hdr> VtsComposerClient::setHdrConversionStrategy(
+std::pair<ScopedAStatus, common::Hdr> ComposerClientWrapper::setHdrConversionStrategy(
const common::HdrConversionStrategy& conversionStrategy) {
common::Hdr preferredHdrOutputType;
return {mComposerClient->setHdrConversionStrategy(conversionStrategy, &preferredHdrOutputType),
preferredHdrOutputType};
}
-std::pair<ScopedAStatus, common::Transform> VtsComposerClient::getDisplayPhysicalOrientation(
+std::pair<ScopedAStatus, common::Transform> ComposerClientWrapper::getDisplayPhysicalOrientation(
int64_t display) {
common::Transform outDisplayOrientation;
return {mComposerClient->getDisplayPhysicalOrientation(display, &outDisplayOrientation),
outDisplayOrientation};
}
-std::pair<ScopedAStatus, composer3::OverlayProperties> VtsComposerClient::getOverlaySupport() {
+std::pair<ScopedAStatus, composer3::OverlayProperties> ComposerClientWrapper::getOverlaySupport() {
OverlayProperties properties;
return {mComposerClient->getOverlaySupport(&properties), properties};
}
-ScopedAStatus VtsComposerClient::setIdleTimerEnabled(int64_t display, int32_t timeoutMs) {
+ScopedAStatus ComposerClientWrapper::setIdleTimerEnabled(int64_t display, int32_t timeoutMs) {
return mComposerClient->setIdleTimerEnabled(display, timeoutMs);
}
-int32_t VtsComposerClient::getVsyncIdleCount() {
+int32_t ComposerClientWrapper::getVsyncIdleCount() {
return mComposerCallback->getVsyncIdleCount();
}
-int64_t VtsComposerClient::getVsyncIdleTime() {
+int64_t ComposerClientWrapper::getVsyncIdleTime() {
return mComposerCallback->getVsyncIdleTime();
}
-ndk::ScopedAStatus VtsComposerClient::setRefreshRateChangedCallbackDebugEnabled(int64_t display,
- bool enabled) {
+ndk::ScopedAStatus ComposerClientWrapper::setRefreshRateChangedCallbackDebugEnabled(int64_t display,
+ bool enabled) {
mComposerCallback->setRefreshRateChangedDebugDataEnabledCallbackAllowed(enabled);
return mComposerClient->setRefreshRateChangedCallbackDebugEnabled(display, enabled);
}
std::vector<RefreshRateChangedDebugData>
-VtsComposerClient::takeListOfRefreshRateChangedDebugData() {
+ComposerClientWrapper::takeListOfRefreshRateChangedDebugData() {
return mComposerCallback->takeListOfRefreshRateChangedDebugData();
}
-int64_t VtsComposerClient::getInvalidDisplayId() {
+int64_t ComposerClientWrapper::getInvalidDisplayId() {
// returns an invalid display id (one that has not been registered to a
// display. Currently assuming that a device will never have close to
// std::numeric_limit<uint64_t>::max() displays registered while running tests
int64_t id = std::numeric_limits<int64_t>::max();
- std::vector<int64_t> displays = mComposerCallback->getDisplays();
+ std::vector<int64_t> displayIds = mComposerCallback->getDisplays();
while (id > 0) {
- if (std::none_of(displays.begin(), displays.end(),
+ if (std::none_of(displayIds.begin(), displayIds.end(),
[id](const auto& display) { return id == display; })) {
return id;
}
@@ -475,86 +479,87 @@
return id;
}
-std::pair<ScopedAStatus, std::vector<VtsDisplay>> VtsComposerClient::getDisplays() {
+std::pair<ScopedAStatus, std::vector<DisplayWrapper>> ComposerClientWrapper::getDisplays() {
while (true) {
// Sleep for a small period of time to allow all built-in displays
// to post hotplug events
std::this_thread::sleep_for(5ms);
- std::vector<int64_t> displays = mComposerCallback->getDisplays();
- if (displays.empty()) {
+ std::vector<int64_t> displayIds = mComposerCallback->getDisplays();
+ if (displayIds.empty()) {
continue;
}
- std::vector<VtsDisplay> vtsDisplays;
- vtsDisplays.reserve(displays.size());
- for (int64_t display : displays) {
- auto vtsDisplay = VtsDisplay{display};
+ std::vector<DisplayWrapper> displays;
+ displays.reserve(displayIds.size());
+ for (int64_t displayId : displayIds) {
+ auto display = DisplayWrapper{displayId};
if (getDisplayConfigurationSupported()) {
- auto [status, configs] = getDisplayConfigurations(display);
+ auto [status, configs] = getDisplayConfigurations(displayId);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to get the DisplayConfigs "
- "for display %" PRId64,
- display);
- return {std::move(status), vtsDisplays};
+ "for displayId %" PRId64,
+ displayId);
+ return {std::move(status), displays};
}
- addDisplayConfigs(&vtsDisplay, configs);
+ addDisplayConfigs(&display, configs);
} else {
- auto [status, configs] = getDisplayConfigs(display);
+ auto [status, configs] = getDisplayConfigs(displayId);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to get the configs "
- "for display %" PRId64,
- display);
- return {std::move(status), vtsDisplays};
+ "for displayId %" PRId64,
+ displayId);
+ return {std::move(status), displays};
}
for (int config : configs) {
- status = addDisplayConfigLegacy(&vtsDisplay, config);
+ status = addDisplayConfigLegacy(&display, config);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to add config "
- "for display %" PRId64,
- display);
- return {std::move(status), vtsDisplays};
+ "for displayId %" PRId64,
+ displayId);
+ return {std::move(status), displays};
}
}
}
- auto activeConfig = getActiveConfig(display);
+ auto activeConfig = getActiveConfig(displayId);
if (!activeConfig.first.isOk()) {
ALOGE("Unable to get the displays for test, failed to get active config "
- "for display %" PRId64,
- display);
- return {std::move(activeConfig.first), vtsDisplays};
+ "for displayId %" PRId64,
+ displayId);
+ return {std::move(activeConfig.first), displays};
}
- auto status = updateDisplayProperties(&vtsDisplay, activeConfig.second);
+ auto status = updateDisplayProperties(&display, activeConfig.second);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, "
"failed to update the properties "
- "for display %" PRId64,
- display);
- return {std::move(status), vtsDisplays};
+ "for displayId %" PRId64,
+ displayId);
+ return {std::move(status), displays};
}
- vtsDisplays.emplace_back(vtsDisplay);
- addDisplayToDisplayResources(display, /*isVirtual*/ false);
+ displays.emplace_back(display);
+ addDisplayToDisplayResources(displayId, /*isVirtual*/ false);
}
- return {ScopedAStatus::ok(), vtsDisplays};
+ return {ScopedAStatus::ok(), displays};
}
}
-void VtsComposerClient::addDisplayConfigs(VtsDisplay* vtsDisplay,
- const std::vector<DisplayConfiguration>& configs) {
+void ComposerClientWrapper::addDisplayConfigs(DisplayWrapper* display,
+ const std::vector<DisplayConfiguration>& configs) {
for (const auto& config : configs) {
- vtsDisplay->addDisplayConfig(config.configId,
- {config.vsyncPeriod, config.configGroup, config.vrrConfig});
+ display->addDisplayConfig(config.configId,
+ {config.vsyncPeriod, config.configGroup, config.vrrConfig});
}
}
-ScopedAStatus VtsComposerClient::addDisplayConfigLegacy(VtsDisplay* vtsDisplay, int32_t config) {
+ScopedAStatus ComposerClientWrapper::addDisplayConfigLegacy(DisplayWrapper* display,
+ int32_t config) {
const auto vsyncPeriod =
- getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
+ getDisplayAttribute(display->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
const auto configGroup =
- getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
+ getDisplayAttribute(display->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
if (vsyncPeriod.first.isOk() && configGroup.first.isOk()) {
- vtsDisplay->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
+ display->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
return ScopedAStatus::ok();
}
@@ -563,13 +568,14 @@
return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
}
-ScopedAStatus VtsComposerClient::updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config) {
+ScopedAStatus ComposerClientWrapper::updateDisplayProperties(DisplayWrapper* display,
+ int32_t config) {
if (getDisplayConfigurationSupported()) {
- auto [status, configs] = getDisplayConfigurations(vtsDisplay->getDisplayId());
+ auto [status, configs] = getDisplayConfigurations(display->getDisplayId());
if (status.isOk()) {
for (const auto& displayConfig : configs) {
if (displayConfig.configId == config) {
- vtsDisplay->setDimensions(displayConfig.width, displayConfig.height);
+ display->setDimensions(displayConfig.width, displayConfig.height);
return ScopedAStatus::ok();
}
}
@@ -577,11 +583,11 @@
LOG(ERROR) << "Failed to update display property with DisplayConfig";
} else {
const auto width =
- getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
+ getDisplayAttribute(display->getDisplayId(), config, DisplayAttribute::WIDTH);
const auto height =
- getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
+ getDisplayAttribute(display->getDisplayId(), config, DisplayAttribute::HEIGHT);
if (width.first.isOk() && height.first.isOk()) {
- vtsDisplay->setDimensions(width.second, height.second);
+ display->setDimensions(width.second, height.second);
return ScopedAStatus::ok();
}
@@ -591,7 +597,7 @@
return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
}
-ScopedAStatus VtsComposerClient::addDisplayToDisplayResources(int64_t display, bool isVirtual) {
+ScopedAStatus ComposerClientWrapper::addDisplayToDisplayResources(int64_t display, bool isVirtual) {
if (mDisplayResources.insert({display, DisplayResource(isVirtual)}).second) {
return ScopedAStatus::ok();
}
@@ -600,7 +606,7 @@
return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_DISPLAY);
}
-ScopedAStatus VtsComposerClient::addLayerToDisplayResources(int64_t display, int64_t layer) {
+ScopedAStatus ComposerClientWrapper::addLayerToDisplayResources(int64_t display, int64_t layer) {
auto resource = mDisplayResources.find(display);
if (resource == mDisplayResources.end()) {
resource = mDisplayResources.insert({display, DisplayResource(false)}).first;
@@ -613,14 +619,14 @@
return ScopedAStatus::ok();
}
-void VtsComposerClient::removeLayerFromDisplayResources(int64_t display, int64_t layer) {
+void ComposerClientWrapper::removeLayerFromDisplayResources(int64_t display, int64_t layer) {
auto resource = mDisplayResources.find(display);
if (resource != mDisplayResources.end()) {
resource->second.layers.erase(layer);
}
}
-bool VtsComposerClient::verifyComposerCallbackParams() {
+bool ComposerClientWrapper::verifyComposerCallbackParams() {
bool isValid = true;
if (mComposerCallback != nullptr) {
if (mComposerCallback->getInvalidHotplugCount() != 0) {
@@ -651,19 +657,23 @@
return isValid;
}
-bool VtsComposerClient::getDisplayConfigurationSupported() const {
+bool ComposerClientWrapper::getDisplayConfigurationSupported() const {
auto [status, interfaceVersion] = getInterfaceVersion();
EXPECT_TRUE(status.isOk());
// getDisplayConfigurations api is supported starting interface version 3
return interfaceVersion >= 3;
}
-bool VtsComposerClient::destroyAllLayers(ComposerClientWriter* writer) {
+bool ComposerClientWrapper::destroyAllLayers(
+ std::unordered_map<int64_t, ComposerClientWriter*> displayWriters) {
std::unordered_map<int64_t, DisplayResource> physicalDisplays;
while (!mDisplayResources.empty()) {
const auto& it = mDisplayResources.begin();
const auto& [display, resource] = *it;
+ ComposerClientWriter* writer =
+ displayWriters.count(display) > 0 ? displayWriters.at(display) : nullptr;
+
while (!resource.layers.empty()) {
auto layer = *resource.layers.begin();
const auto status = destroyLayer(display, layer, writer);
@@ -690,4 +700,4 @@
mDisplayResources.clear();
return true;
}
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp b/graphics/composer/aidl/libhwc_aidl_test/GraphicsComposerCallback.cpp
similarity index 97%
rename from graphics/composer/aidl/vts/GraphicsComposerCallback.cpp
rename to graphics/composer/aidl/libhwc_aidl_test/GraphicsComposerCallback.cpp
index 1f7972c..ba16348 100644
--- a/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/aidl/libhwc_aidl_test/GraphicsComposerCallback.cpp
@@ -23,7 +23,7 @@
#undef LOG_TAG
#define LOG_TAG "GraphicsComposerCallback"
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
std::scoped_lock lock(mMutex);
@@ -219,4 +219,4 @@
return ::ndk::ScopedAStatus::ok();
}
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/libhwc_aidl_test/Readback.cpp
similarity index 97%
rename from graphics/composer/aidl/vts/ReadbackVts.cpp
rename to graphics/composer/aidl/libhwc_aidl_test/Readback.cpp
index 9d5928d..9918385 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/libhwc_aidl_test/Readback.cpp
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#include "ReadbackVts.h"
+#include "Readback.h"
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
-#include <cmath>
-#include "RenderEngineVts.h"
-#include "renderengine/ExternalTexture.h"
+#include "RenderEngine.h"
#include "renderengine/impl/ExternalTexture.h"
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
const std::vector<Dataspace> ReadbackHelper::dataspaces = {common::Dataspace::SRGB,
@@ -320,8 +318,9 @@
}
}
-ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client,
- int32_t width, int32_t height, common::PixelFormat pixelFormat,
+ReadbackBuffer::ReadbackBuffer(int64_t display,
+ const std::shared_ptr<ComposerClientWrapper>& client, int32_t width,
+ int32_t height, common::PixelFormat pixelFormat,
common::Dataspace dataspace)
: mComposerClient(client) {
mDisplay = display;
@@ -403,7 +402,7 @@
return layerSettings;
}
-TestBufferLayer::TestBufferLayer(const std::shared_ptr<VtsComposerClient>& client,
+TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClientWrapper>& client,
TestRenderEngine& renderEngine, int64_t display, uint32_t width,
uint32_t height, common::PixelFormat format,
ComposerClientWriter& writer, Composition composition)
@@ -489,4 +488,4 @@
writer.setLayerCompositionType(mDisplay, mLayer, Composition::CLIENT);
}
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/libhwc_aidl_test/RenderEngine.cpp
similarity index 96%
rename from graphics/composer/aidl/vts/RenderEngineVts.cpp
rename to graphics/composer/aidl/libhwc_aidl_test/RenderEngine.cpp
index 8f8b5fd..6715ea4 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/libhwc_aidl_test/RenderEngine.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "RenderEngineVts.h"
+#include "RenderEngine.h"
#include "renderengine/impl/ExternalTexture.h"
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
using ::android::renderengine::DisplaySettings;
using ::android::renderengine::LayerSettings;
@@ -115,4 +115,4 @@
ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
}
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h
similarity index 89%
rename from graphics/composer/aidl/vts/VtsComposerClient.h
rename to graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h
index da6116f..2ad081d 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h
@@ -46,21 +46,21 @@
using aidl::android::hardware::graphics::common::Rect;
using namespace ::ndk;
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
-class VtsDisplay;
+class DisplayWrapper;
/**
* A wrapper to IComposerClient.
* This wrapper manages the IComposerClient instance and manages the resources for
* the tests with respect to the IComposerClient calls.
*/
-class VtsComposerClient {
+class ComposerClientWrapper {
public:
- VtsComposerClient(const std::string& name);
+ ComposerClientWrapper(const std::string& name);
ScopedAStatus createClient();
- bool tearDown(ComposerClientWriter*);
+ bool tearDown(std::unordered_map<int64_t, ComposerClientWriter*> displayWriters);
std::pair<ScopedAStatus, int32_t> getInterfaceVersion() const;
@@ -77,9 +77,9 @@
std::pair<ScopedAStatus, int32_t> getActiveConfig(int64_t display);
- ScopedAStatus setActiveConfig(VtsDisplay* vtsDisplay, int32_t config);
+ ScopedAStatus setActiveConfig(DisplayWrapper* display, int32_t config);
- ScopedAStatus setPeakRefreshRateConfig(VtsDisplay* vtsDisplay);
+ ScopedAStatus setPeakRefreshRateConfig(DisplayWrapper* display);
std::pair<ScopedAStatus, int32_t> getDisplayAttribute(int64_t display, int32_t config,
DisplayAttribute displayAttribute);
@@ -100,7 +100,7 @@
ScopedAStatus setContentType(int64_t display, ContentType contentType);
std::pair<ScopedAStatus, VsyncPeriodChangeTimeline> setActiveConfigWithConstraints(
- VtsDisplay* vtsDisplay, int32_t config,
+ DisplayWrapper* display, int32_t config,
const VsyncPeriodChangeConstraints& constraints);
std::pair<ScopedAStatus, std::vector<DisplayCapability>> getDisplayCapabilities(
@@ -190,7 +190,7 @@
int64_t getInvalidDisplayId();
- std::pair<ScopedAStatus, std::vector<VtsDisplay>> getDisplays();
+ std::pair<ScopedAStatus, std::vector<DisplayWrapper>> getDisplays();
std::pair<ScopedAStatus, OverlayProperties> getOverlaySupport();
@@ -202,10 +202,10 @@
static constexpr int32_t kNoFrameIntervalNs = 0;
private:
- void addDisplayConfigs(VtsDisplay*, const std::vector<DisplayConfiguration>&);
- ScopedAStatus addDisplayConfigLegacy(VtsDisplay*, int32_t config);
+ void addDisplayConfigs(DisplayWrapper*, const std::vector<DisplayConfiguration>&);
+ ScopedAStatus addDisplayConfigLegacy(DisplayWrapper*, int32_t config);
bool getDisplayConfigurationSupported() const;
- ScopedAStatus updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config);
+ ScopedAStatus updateDisplayProperties(DisplayWrapper* display, int32_t config);
ScopedAStatus addDisplayToDisplayResources(int64_t display, bool isVirtual);
@@ -213,12 +213,12 @@
void removeLayerFromDisplayResources(int64_t display, int64_t layer);
- bool destroyAllLayers(ComposerClientWriter*);
+ bool destroyAllLayers(std::unordered_map<int64_t, ComposerClientWriter*> displayWriters);
bool verifyComposerCallbackParams();
// Keep track of displays and layers. When a test fails/ends,
- // the VtsComposerClient::tearDown should be called from the
+ // the ComposerClientWrapper::tearDown should be called from the
// test tearDown to clean up the resources for the test.
struct DisplayResource {
DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
@@ -235,9 +235,10 @@
std::atomic<int64_t> mNextLayerHandle = 1;
};
-class VtsDisplay {
+class DisplayWrapper {
public:
- VtsDisplay(int64_t displayId) : mDisplayId(displayId), mDisplayWidth(0), mDisplayHeight(0) {}
+ explicit DisplayWrapper(int64_t displayId)
+ : mDisplayId(displayId), mDisplayWidth(0), mDisplayHeight(0) {}
int64_t getDisplayId() const { return mDisplayId; }
@@ -294,9 +295,8 @@
std::stringstream ss;
if (displayConfig.vrrConfigOpt) {
ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod
- << ", minFrameIntervalNs " << vrrConfigOpt->minFrameIntervalNs << "}";
- }
- else {
+ << ", minFrameIntervalNs " << vrrConfigOpt->minFrameIntervalNs << "}";
+ } else {
ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod << "}";
}
return ss.str();
@@ -310,4 +310,4 @@
int32_t mDisplayHeight;
std::unordered_map<int32_t, DisplayConfig> mDisplayConfigs;
};
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/GraphicsComposerCallback.h b/graphics/composer/aidl/libhwc_aidl_test/include/GraphicsComposerCallback.h
similarity index 95%
rename from graphics/composer/aidl/vts/GraphicsComposerCallback.h
rename to graphics/composer/aidl/libhwc_aidl_test/include/GraphicsComposerCallback.h
index 97f8e2b..ff379b7 100644
--- a/graphics/composer/aidl/vts/GraphicsComposerCallback.h
+++ b/graphics/composer/aidl/libhwc_aidl_test/include/GraphicsComposerCallback.h
@@ -20,7 +20,7 @@
#include <mutex>
#include <vector>
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
class GraphicsComposerCallback : public BnComposerCallback {
public:
@@ -93,4 +93,4 @@
int32_t mHdcpLevelChangedCount GUARDED_BY(mMutex) = 0;
};
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/libhwc_aidl_test/include/Readback.h
similarity index 90%
rename from graphics/composer/aidl/vts/ReadbackVts.h
rename to graphics/composer/aidl/libhwc_aidl_test/include/Readback.h
index e3b2384..48a993c 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/libhwc_aidl_test/include/Readback.h
@@ -23,10 +23,9 @@
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
#include <memory>
-#include "GraphicsComposerCallback.h"
-#include "VtsComposerClient.h"
+#include "ComposerClientWrapper.h"
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
using ::android::renderengine::LayerSettings;
using common::Dataspace;
@@ -50,7 +49,7 @@
class TestLayer {
public:
- TestLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display,
+ TestLayer(const std::shared_ptr<ComposerClientWrapper>& client, int64_t display,
ComposerClientWriter& writer)
: mDisplay(display) {
const auto& [status, layer] = client->createLayer(display, kBufferSlotCount, &writer);
@@ -60,7 +59,7 @@
// ComposerClient will take care of destroying layers, no need to explicitly
// call destroyLayers here
- virtual ~TestLayer(){};
+ virtual ~TestLayer() {};
virtual void write(ComposerClientWriter& writer);
virtual LayerSettings toRenderEngineLayerSettings();
@@ -109,7 +108,7 @@
class TestColorLayer : public TestLayer {
public:
- TestColorLayer(const std::shared_ptr<VtsComposerClient>& client, int64_t display,
+ TestColorLayer(const std::shared_ptr<ComposerClientWrapper>& client, int64_t display,
ComposerClientWriter& writer)
: TestLayer{client, display, writer} {}
@@ -125,7 +124,7 @@
class TestBufferLayer : public TestLayer {
public:
- TestBufferLayer(const std::shared_ptr<VtsComposerClient>& client,
+ TestBufferLayer(const std::shared_ptr<ComposerClientWrapper>& client,
TestRenderEngine& renderEngine, int64_t display, uint32_t width,
uint32_t height, common::PixelFormat format, ComposerClientWriter& writer,
Composition composition = Composition::DEVICE);
@@ -201,8 +200,9 @@
class ReadbackBuffer {
public:
- ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client, int32_t width,
- int32_t height, common::PixelFormat pixelFormat, common::Dataspace dataspace);
+ ReadbackBuffer(int64_t display, const std::shared_ptr<ComposerClientWrapper>& client,
+ int32_t width, int32_t height, common::PixelFormat pixelFormat,
+ common::Dataspace dataspace);
void setReadbackBuffer();
@@ -219,7 +219,7 @@
Dataspace mDataspace;
int64_t mDisplay;
::android::sp<::android::GraphicBuffer> mGraphicBuffer;
- std::shared_ptr<VtsComposerClient> mComposerClient;
+ std::shared_ptr<ComposerClientWrapper> mComposerClient;
::android::Rect mAccessRegion;
native_handle_t mBufferHandle;
@@ -227,4 +227,4 @@
::android::sp<::android::GraphicBuffer> allocateBuffer();
};
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.h b/graphics/composer/aidl/libhwc_aidl_test/include/RenderEngine.h
similarity index 91%
rename from graphics/composer/aidl/vts/RenderEngineVts.h
rename to graphics/composer/aidl/libhwc_aidl_test/include/RenderEngine.h
index 6553720..6b8b82f 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.h
+++ b/graphics/composer/aidl/libhwc_aidl_test/include/RenderEngine.h
@@ -23,9 +23,9 @@
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
-#include "ReadbackVts.h"
+#include "Readback.h"
-namespace aidl::android::hardware::graphics::composer3::vts {
+namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test {
using ::android::renderengine::DisplaySettings;
using ::android::renderengine::ExternalTexture;
@@ -60,4 +60,4 @@
DisplaySettings mDisplaySettings;
};
-} // namespace aidl::android::hardware::graphics::composer3::vts
+} // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 894ca52..8f5c7d2 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -36,28 +36,19 @@
srcs: [
"VtsHalGraphicsComposer3_TargetTest.cpp",
"VtsHalGraphicsComposer3_ReadbackTest.cpp",
- "GraphicsComposerCallback.cpp",
- "ReadbackVts.cpp",
- "RenderEngineVts.cpp",
- "VtsComposerClient.cpp",
],
-
shared_libs: [
"libEGL",
- "libGLESv1_CM",
"libGLESv2",
"libbinder_ndk",
"libbinder",
- "libfmq",
"libbase",
"libsync",
"libui",
"libgui",
- "libhidlbase",
"libprocessgroup",
- "libvndksupport",
- "server_configurable_flags",
"libtracing_perfetto",
+ "server_configurable_flags",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
@@ -66,18 +57,16 @@
"android.hardware.graphics.common@1.2",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.drm.common-V1-ndk",
"libaidlcommonsupport",
"libarect",
"libbase",
- "libfmq",
"libgtest",
- "libmath",
+ "libhwc_aidl_test",
"librenderengine",
- "libshaders",
"libsync",
- "libtonemap",
"libsurfaceflinger_common",
+ "libshaders",
+ "libtonemap",
],
cflags: [
"-Wconversion",
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 9db8794..1429935 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -26,14 +26,16 @@
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
+#include "ComposerClientWrapper.h"
#include "GraphicsComposerCallback.h"
-#include "ReadbackVts.h"
-#include "RenderEngineVts.h"
-#include "VtsComposerClient.h"
+#include "Readback.h"
+#include "RenderEngine.h"
namespace aidl::android::hardware::graphics::composer3::vts {
namespace {
+using namespace ::aidl::android::hardware::graphics::composer3::libhwc_aidl_test;
+
using ::android::Rect;
using common::Dataspace;
using common::PixelFormat;
@@ -41,7 +43,7 @@
class GraphicsCompositionTestBase : public ::testing::Test {
protected:
void SetUpBase(const std::string& name) {
- mComposerClient = std::make_shared<VtsComposerClient>(name);
+ mComposerClient = std::make_shared<ComposerClientWrapper>(name);
ASSERT_TRUE(mComposerClient->createClient().isOk());
const auto& [status, displays] = mComposerClient->getDisplays();
@@ -89,14 +91,16 @@
void TearDown() override {
ASSERT_FALSE(mDisplays.empty());
ASSERT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk());
- ASSERT_TRUE(mComposerClient->tearDown(mWriter.get()));
+ std::unordered_map<int64_t, ComposerClientWriter*> displayWriters;
+ displayWriters.emplace(getPrimaryDisplayId(), mWriter.get());
+ ASSERT_TRUE(mComposerClient->tearDown(displayWriters));
mComposerClient.reset();
const auto errors = mReader.takeErrors();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
}
- const VtsDisplay& getPrimaryDisplay() const { return mDisplays[0]; }
+ const DisplayWrapper& getPrimaryDisplay() const { return mDisplays[0]; }
int64_t getPrimaryDisplayId() const { return getPrimaryDisplay().getDisplayId(); }
@@ -157,8 +161,8 @@
return false;
}
- std::shared_ptr<VtsComposerClient> mComposerClient;
- std::vector<VtsDisplay> mDisplays;
+ std::shared_ptr<ComposerClientWrapper> mComposerClient;
+ std::vector<DisplayWrapper> mDisplays;
// use the slot count usually set by SF
std::vector<ColorMode> mTestColorModes;
std::unique_ptr<ComposerClientWriter> mWriter;
@@ -225,7 +229,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
// if hwc cannot handle and asks for composition change,
// just succeed the test
@@ -285,7 +289,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
@@ -346,7 +350,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
@@ -461,7 +465,7 @@
auto layer = std::make_shared<TestBufferLayer>(
mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
- getDisplayHeight(), PixelFormat::RGBA_FP16, *mWriter);
+ getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
@@ -474,7 +478,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
@@ -511,7 +515,7 @@
clientDataspace, std::vector<common::Rect>(1, damage), 1.f);
layer->setToClientComposition(*mWriter);
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
ASSERT_TRUE(changedCompositionTypes.empty());
@@ -589,7 +593,7 @@
writeLayers({srgbLayer, displayP3Layer});
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
@@ -666,7 +670,7 @@
clientLayer->setZOrder(0);
clientLayer->write(*mWriter);
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
@@ -699,7 +703,7 @@
clientDataspace, std::vector<common::Rect>(1, clientFrame), 1.f);
clientLayer->setToClientComposition(*mWriter);
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
ASSERT_TRUE(changedCompositionTypes.empty());
@@ -748,7 +752,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -777,7 +781,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
@@ -820,7 +824,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -885,7 +889,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -946,7 +950,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -969,7 +973,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1035,7 +1039,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED()
@@ -1171,7 +1175,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1217,7 +1221,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1258,7 +1262,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1343,7 +1347,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1390,7 +1394,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1437,7 +1441,7 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -1531,7 +1535,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
continue;
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index eaf23b5..77d8cdd 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -39,8 +39,8 @@
#include <string>
#include <thread>
#include <unordered_map>
+#include "ComposerClientWrapper.h"
#include "GraphicsComposerCallback.h"
-#include "VtsComposerClient.h"
#undef LOG_TAG
#define LOG_TAG "VtsHalGraphicsComposer3_TargetTest"
@@ -48,6 +48,7 @@
namespace aidl::android::hardware::graphics::composer3::vts {
using namespace std::chrono_literals;
+using namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test;
using ::android::GraphicBuffer;
using ::android::sp;
@@ -55,7 +56,7 @@
class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
protected:
void SetUp() override {
- mComposerClient = std::make_unique<VtsComposerClient>(GetParam());
+ mComposerClient = std::make_unique<ComposerClientWrapper>(GetParam());
ASSERT_TRUE(mComposerClient->createClient().isOk());
const auto& [status, displays] = mComposerClient->getDisplays();
@@ -70,7 +71,8 @@
}
void TearDown() override {
- ASSERT_TRUE(mComposerClient->tearDown(nullptr));
+ ASSERT_TRUE(
+ mComposerClient->tearDown(std::unordered_map<int64_t, ComposerClientWriter*>{}));
mComposerClient.reset();
}
@@ -124,21 +126,21 @@
return version;
}
- const VtsDisplay& getPrimaryDisplay() const { return mDisplays[0]; }
+ const DisplayWrapper& getPrimaryDisplay() const { return mDisplays[0]; }
int64_t getPrimaryDisplayId() const { return getPrimaryDisplay().getDisplayId(); }
int64_t getInvalidDisplayId() const { return mComposerClient->getInvalidDisplayId(); }
- VtsDisplay& getEditablePrimaryDisplay() { return mDisplays[0]; }
+ DisplayWrapper& getEditablePrimaryDisplay() { return mDisplays[0]; }
struct TestParameters {
nsecs_t delayForChange;
bool refreshMiss;
};
- std::unique_ptr<VtsComposerClient> mComposerClient;
- std::vector<VtsDisplay> mDisplays;
+ std::unique_ptr<ComposerClientWrapper> mComposerClient;
+ std::vector<DisplayWrapper> mDisplays;
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
};
@@ -233,7 +235,6 @@
GTEST_SUCCEED() << "getReadbackBufferAttributes is not supported";
return;
}
-
ASSERT_TRUE(status.isOk());
}
@@ -497,7 +498,7 @@
VsyncPeriodChangeConstraints constraints;
constraints.seamlessRequired = false;
constraints.desiredTimeNanos = systemTime();
- auto invalidDisplay = VtsDisplay(getInvalidDisplayId());
+ auto invalidDisplay = DisplayWrapper(getInvalidDisplayId());
const auto& [status, timeline] = mComposerClient->setActiveConfigWithConstraints(
&invalidDisplay, /*config*/ 0, constraints);
@@ -511,7 +512,7 @@
constraints.seamlessRequired = false;
constraints.desiredTimeNanos = systemTime();
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
int32_t constexpr kInvalidConfigId = IComposerClient::INVALID_CONFIGURATION;
const auto& [status, _] = mComposerClient->setActiveConfigWithConstraints(
&display, kInvalidConfigId, constraints);
@@ -537,7 +538,7 @@
GTEST_SUCCEED() << "Boot Display Config not supported";
return;
}
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
int32_t constexpr kInvalidConfigId = IComposerClient::INVALID_CONFIGURATION;
const auto& status =
mComposerClient->setBootDisplayConfig(display.getDisplayId(), kInvalidConfigId);
@@ -1290,7 +1291,7 @@
const auto minFrameInterval = *min_element(frameIntervalPowerHints.cbegin(),
frameIntervalPowerHints.cend());
EXPECT_LE(minFrameInterval->frameIntervalNs,
- VtsComposerClient::kMaxFrameIntervalNs);
+ ComposerClientWrapper::kMaxFrameIntervalNs);
const auto maxFrameInterval = *max_element(frameIntervalPowerHints.cbegin(),
frameIntervalPowerHints.cend());
EXPECT_GE(maxFrameInterval->frameIntervalNs, vrrConfig.minFrameIntervalNs);
@@ -1396,7 +1397,9 @@
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
- ASSERT_TRUE(mComposerClient->tearDown(&getWriter(getPrimaryDisplayId())));
+ std::unordered_map<int64_t, ComposerClientWriter*> displayWriters;
+ displayWriters.emplace(getPrimaryDisplayId(), &getWriter(getPrimaryDisplayId()));
+ ASSERT_TRUE(mComposerClient->tearDown(displayWriters));
ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
}
@@ -1470,7 +1473,8 @@
static_cast<uint32_t>(getPrimaryDisplay().getDisplayHeight()), pixelFormat);
}
- void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
+ void sendRefreshFrame(const DisplayWrapper& display,
+ const VsyncPeriodChangeTimeline* timeline) {
if (timeline != nullptr) {
// Refresh time should be before newVsyncAppliedTimeNanos
EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
@@ -1501,7 +1505,7 @@
writer.setLayerDataspace(display.getDisplayId(), layer, common::Dataspace::UNKNOWN);
writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1519,7 +1523,7 @@
writer.setLayerSurfaceDamage(display.getDisplayId(), layer,
std::vector<Rect>(1, {0, 0, 10, 10}));
writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1532,8 +1536,8 @@
sp<::android::Fence> presentAndGetFence(
std::optional<ClockMonotonicTimestamp> expectedPresentTime,
- std::optional<int64_t> displayIdOpt = {},
- int32_t frameIntervalNs = VtsComposerClient::kNoFrameIntervalNs) {
+ std::optional<int> displayIdOpt = {},
+ int32_t frameIntervalNs = ComposerClientWrapper::kNoFrameIntervalNs) {
const auto displayId = displayIdOpt.value_or(getPrimaryDisplayId());
auto& writer = getWriter(displayId);
writer.validateDisplay(displayId, expectedPresentTime, frameIntervalNs);
@@ -1563,7 +1567,7 @@
return vsyncPeriod;
}
- int64_t createOnScreenLayer(const VtsDisplay& display,
+ int64_t createOnScreenLayer(const DisplayWrapper& display,
Composition composition = Composition::DEVICE) {
auto& writer = getWriter(display.getDisplayId());
const auto& [status, layer] =
@@ -1598,7 +1602,7 @@
}
void Test_setActiveConfigWithConstraints(const TestParameters& params) {
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
forEachTwoConfigs(display.getDisplayId(), [&](int32_t config1, int32_t config2) {
EXPECT_TRUE(mComposerClient->setActiveConfig(&display, config1).isOk());
sendRefreshFrame(display, nullptr);
@@ -1725,8 +1729,8 @@
}
void forEachNotifyExpectedPresentConfig(
- std::function<void(VtsDisplay&, const DisplayConfiguration&)> func) {
- for (VtsDisplay& display : mDisplays) {
+ std::function<void(DisplayWrapper&, const DisplayConfiguration&)> func) {
+ for (DisplayWrapper& display : mDisplays) {
const auto displayId = display.getDisplayId();
EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
const auto& [status, displayConfigurations] =
@@ -1756,7 +1760,7 @@
}
}
- void configureLayer(const VtsDisplay& display, int64_t layer, Composition composition,
+ void configureLayer(const DisplayWrapper& display, int64_t layer, Composition composition,
const Rect& displayFrame, const FRect& cropRect) {
auto& writer = getWriter(display.getDisplayId());
writer.setLayerCompositionType(display.getDisplayId(), layer, composition);
@@ -1918,14 +1922,14 @@
TEST_P(GraphicsComposerAidlCommandTest, ValidDisplay) {
auto& writer = getWriter(getPrimaryDisplayId());
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, AcceptDisplayChanges) {
auto& writer = getWriter(getPrimaryDisplayId());
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
writer.acceptDisplayChanges(getPrimaryDisplayId());
execute();
}
@@ -1933,7 +1937,7 @@
TEST_P(GraphicsComposerAidlCommandTest, PresentDisplay) {
auto& writer = getWriter(getPrimaryDisplayId());
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
writer.presentDisplay(getPrimaryDisplayId());
execute();
}
@@ -1973,7 +1977,7 @@
/*acquireFence*/ -1);
writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED() << "Composition change requested, skipping test";
@@ -2016,7 +2020,7 @@
configureLayer(getPrimaryDisplay(), layer, Composition::CURSOR, displayFrame, cropRect);
writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
@@ -2032,7 +2036,7 @@
writer.setLayerCursorPosition(getPrimaryDisplayId(), layer, /*x*/ 0, /*y*/ 0);
writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
writer.presentDisplay(getPrimaryDisplayId());
execute();
}
@@ -2202,7 +2206,7 @@
}
TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) {
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
const auto displayId = display.getDisplayId();
auto& writer = getWriter(displayId);
const auto [layerStatus, layer] =
@@ -2232,7 +2236,7 @@
writer.setLayerBuffer(displayId, layer, /*slot*/ 0, decorBuffer->handle,
/*acquireFence*/ -1);
writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute();
if (support) {
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -2483,7 +2487,7 @@
}
TEST_P(GraphicsComposerAidlCommandTest, GetDisplayVsyncPeriod) {
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
const auto& [status, configs] = mComposerClient->getDisplayConfigs(display.getDisplayId());
EXPECT_TRUE(status.isOk());
@@ -2542,7 +2546,7 @@
constraints.seamlessRequired = true;
constraints.desiredTimeNanos = systemTime();
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
forEachTwoConfigs(display.getDisplayId(), [&](int32_t config1, int32_t config2) {
int32_t configGroup1 = display.getDisplayConfig(config1).configGroup;
int32_t configGroup2 = display.getDisplayConfig(config2).configGroup;
@@ -2729,7 +2733,7 @@
return;
}
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
const auto displayId = display.getDisplayId();
EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
// Enable the callback
@@ -2833,7 +2837,7 @@
constraints.seamlessRequired = false;
constraints.desiredTimeNanos = systemTime();
- for (VtsDisplay& display : mDisplays) {
+ for (DisplayWrapper& display : mDisplays) {
const auto displayId = display.getDisplayId();
EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
@@ -2891,7 +2895,7 @@
}
TEST_P(GraphicsComposerAidlCommandTest, MultiThreadedPresent) {
- std::vector<VtsDisplay*> displays;
+ std::vector<DisplayWrapper*> displays;
for (auto& display : mDisplays) {
if (hasDisplayCapability(display.getDisplayId(),
DisplayCapability::MULTI_THREADED_PRESENT)) {
@@ -2954,7 +2958,7 @@
lock.unlock();
writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ ComposerClientWrapper::kNoFrameIntervalNs);
execute(writer, reader);
threads.emplace_back([this, displayId, &readers, &readersMutex]() {
@@ -3089,7 +3093,7 @@
GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping";
return;
}
- forEachNotifyExpectedPresentConfig([&](VtsDisplay& display,
+ forEachNotifyExpectedPresentConfig([&](DisplayWrapper& display,
const DisplayConfiguration& config) {
const auto displayId = display.getDisplayId();
auto minFrameIntervalNs = config.vrrConfig->minFrameIntervalNs;
@@ -3129,7 +3133,7 @@
GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping";
return;
}
- forEachNotifyExpectedPresentConfig([&](VtsDisplay& display,
+ forEachNotifyExpectedPresentConfig([&](DisplayWrapper& display,
const DisplayConfiguration& config) {
const auto displayId = display.getDisplayId();
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
@@ -3145,7 +3149,7 @@
auto lastPresentTimeNs = presentFence->getSignalTime();
auto vsyncPeriod = config.vsyncPeriod;
- int32_t highestDivisor = VtsComposerClient::kMaxFrameIntervalNs / vsyncPeriod;
+ int32_t highestDivisor = ComposerClientWrapper::kMaxFrameIntervalNs / vsyncPeriod;
int32_t lowestDivisor = minFrameIntervalNs / vsyncPeriod;
const auto headsUpNs = config.vrrConfig->notifyExpectedPresentConfig->headsUpNs;
float totalDivisorsPassed = 0.f;
@@ -3176,7 +3180,7 @@
GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping";
return;
}
- forEachNotifyExpectedPresentConfig([&](VtsDisplay& display,
+ forEachNotifyExpectedPresentConfig([&](DisplayWrapper& display,
const DisplayConfiguration& config) {
const auto displayId = display.getDisplayId();
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
@@ -3188,7 +3192,7 @@
auto minFrameIntervalNs = config.vrrConfig->minFrameIntervalNs;
auto vsyncPeriod = config.vsyncPeriod;
- int32_t highestDivisor = VtsComposerClient::kMaxFrameIntervalNs / vsyncPeriod;
+ int32_t highestDivisor = ComposerClientWrapper::kMaxFrameIntervalNs / vsyncPeriod;
int32_t lowestDivisor = minFrameIntervalNs / vsyncPeriod;
const auto headsUpNs = config.vrrConfig->notifyExpectedPresentConfig->headsUpNs;
float totalDivisorsPassed = 0.f;
diff --git a/ir/OWNERS b/ir/OWNERS
index 04de9ef..376fe0a 100644
--- a/ir/OWNERS
+++ b/ir/OWNERS
@@ -1,2 +1,2 @@
# Bug component: 163905
-connoro@google.com
+devinmoore@google.com
\ No newline at end of file
diff --git a/nfc/1.0/default/OWNERS b/nfc/1.0/default/OWNERS
index 5febd1d..e681870 100644
--- a/nfc/1.0/default/OWNERS
+++ b/nfc/1.0/default/OWNERS
@@ -1,2 +1 @@
rmojumder@google.com
-zachoverflow@google.com
diff --git a/nfc/1.2/vts/OWNERS b/nfc/1.2/vts/OWNERS
index 21d4df1..eeeadd1 100644
--- a/nfc/1.2/vts/OWNERS
+++ b/nfc/1.2/vts/OWNERS
@@ -1,3 +1,2 @@
-zachoverflow@google.com
jackcwyu@google.com
georgekgchang@google.com
diff --git a/nfc/OWNERS b/nfc/OWNERS
index f46dccd..47f209f 100644
--- a/nfc/OWNERS
+++ b/nfc/OWNERS
@@ -1,2 +1,2 @@
# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
\ No newline at end of file
+include platform/packages/modules/Nfc:/OWNERS
\ No newline at end of file
diff --git a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
index 6db7e14..d3fcbb3 100644
--- a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
+++ b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
@@ -153,8 +153,7 @@
SyncEventGuard guard(sNfaVsCommand);
sNfaVsCommand.notifyOne();
} break;
- case NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH:
- case NCI_ANDROID_PASSIVE_OBSERVE: {
+ case NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH: {
if (param_len == 5) {
if ((p_param[0] & NCI_MT_MASK) == (NCI_MT_RSP << NCI_MT_SHIFT)) {
sVSCmdStatus = p_param[4];
@@ -190,36 +189,6 @@
}
/*
- * Enable passive observe mode.
- */
-tNFA_STATUS static nfaObserveModeEnable(bool enable) {
- tNFA_STATUS status = NFA_STATUS_FAILED;
-
- status = NFA_StopRfDiscovery();
- if (status == NFA_STATUS_OK) {
- if (!sNfaEnableDisablePollingEvent.wait(1000)) {
- LOG(WARNING) << "Timeout waiting to disable NFC RF discovery";
- return NFA_STATUS_TIMEOUT;
- }
- }
-
- uint8_t cmd[] = {NCI_ANDROID_PASSIVE_OBSERVE,
- static_cast<uint8_t>(enable ? NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE
- : NCI_ANDROID_PASSIVE_OBSERVE_PARAM_DISABLE)};
-
- status = NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, sizeof(cmd), cmd, nfaVSCallback);
-
- if (status == NFA_STATUS_OK) {
- if (!sNfaVsCommand.wait(1000)) {
- LOG(WARNING) << "Timeout waiting for set observe mode command response";
- return NFA_STATUS_TIMEOUT;
- }
- }
-
- return status;
-}
-
-/*
* Get observe mode state.
*/
tNFA_STATUS static nfaQueryObserveModeState() {
@@ -322,71 +291,18 @@
};
/*
- * ObserveModeEnableDisable:
- * Attempts to enable observe mode. Does not test Observe Mode functionality,
- * but simply verifies that the enable command responds successfully.
- *
- * @VsrTest = GMS-VSR-3.2.8-001
+ * SetPassiveObserverTech_getCaps:
+ * Verifies GET_CAPS returns get correct value for observe mode capabilities.
*/
-TEST_P(NfcBehaviorChanges, ObserveModeEnableDisable) {
- if (get_vsr_api_level() < 202404) {
- GTEST_SKIP() << "Skipping test for board API level < 202404";
- }
-
- tNFA_STATUS status = nfaObserveModeEnable(true);
- ASSERT_EQ(status, NFA_STATUS_OK);
-
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_NE(sObserveModeState, 0);
-
- status = nfaObserveModeEnable(false);
- ASSERT_EQ(status, NFA_STATUS_OK);
-
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_EQ(sObserveModeState, 0);
-}
-
-/*
- * SetPassiveObserverTech_individualTechnologies:
- * Verifies per-technology observe mode is supported as a capability. Then sets observe mode
- * for each individual technology and verifies the command succeeds.
- *
- * @VsrTest = GMS-VSR-3.2.8-002
- */
-TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_individualTechnologies) {
+TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_getCaps) {
if (get_vsr_api_level() < 202504) {
GTEST_SKIP() << "Skipping test for board API level < 202504";
}
tNFC_STATUS status = nfaGetCaps();
+
ASSERT_EQ(status, NFC_STATUS_OK);
ASSERT_EQ(getCapsPassiveObserverModeValue(), 0x2);
-
- status = nfaSetPassiveObserverTech(NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_A);
- ASSERT_EQ(status, NFA_STATUS_OK);
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_EQ(sObserveModeState, NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_A);
-
- status = nfaSetPassiveObserverTech(NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_B);
- ASSERT_EQ(status, NFA_STATUS_OK);
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_EQ(sObserveModeState, NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_B);
-
- status = nfaSetPassiveObserverTech(NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_V);
- ASSERT_EQ(status, NFA_STATUS_OK);
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_EQ(sObserveModeState, NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_V);
-
- status = nfaSetPassiveObserverTech(NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_F);
- ASSERT_EQ(status, NFA_STATUS_OK);
- status = nfaQueryObserveModeState();
- ASSERT_EQ(status, NFA_STATUS_OK);
- ASSERT_EQ(sObserveModeState, NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_F);
}
/*
diff --git a/power/1.0/vts/OWNERS b/power/1.0/vts/OWNERS
index 6de2cd5..53948b9 100644
--- a/power/1.0/vts/OWNERS
+++ b/power/1.0/vts/OWNERS
@@ -1,2 +1 @@
# Bug component: 158088
-connoro@google.com
diff --git a/power/1.1/vts/functional/OWNERS b/power/1.1/vts/functional/OWNERS
index 6de2cd5..53948b9 100644
--- a/power/1.1/vts/functional/OWNERS
+++ b/power/1.1/vts/functional/OWNERS
@@ -1,2 +1 @@
# Bug component: 158088
-connoro@google.com
diff --git a/power/stats/1.0/default/OWNERS b/power/stats/1.0/default/OWNERS
index 2d95a97..0557220 100644
--- a/power/stats/1.0/default/OWNERS
+++ b/power/stats/1.0/default/OWNERS
@@ -1,3 +1,2 @@
krossmo@google.com
bsschwar@google.com
-tstrudel@google.com
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index fc703e9..0ae4b96 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -479,8 +479,8 @@
* structure.
*
* @param unwrappingParams must contain any parameters needed to perform the unwrapping
- * operation. For example, if the wrapping key is an AES key the block and padding modes
- * must be specified in this argument.
+ * operation. For example, the padding mode for the RSA wrapping key must be specified
+ * in this argument.
*
* @param passwordSid specifies the password secure ID (SID) of the user that owns the key being
* installed. If the authorization list in wrappedKeyData contains a
@@ -550,8 +550,14 @@
void deleteKey(in byte[] keyBlob);
/**
- * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
- * this function is called all keys created previously must be rendered permanently unusable.
+ * Deletes all keys in the hardware keystore. Used when keystore is reset completely.
+ *
+ * For StrongBox KeyMint: After this function is called all keys created previously must be
+ * rendered permanently unusable.
+ *
+ * For TEE KeyMint: After this function is called all keys with Tag::ROLLBACK_RESISTANCE in
+ * their hardware-enforced authorization lists must be rendered permanently unusable. Keys
+ * without Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
*/
void deleteAllKeys();
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 0197141..0d03651 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -192,7 +192,6 @@
],
prebuilts: [
"keymint_aidl_nonsecure_init_rc",
- "keymint_aidl_nonsecure_vintf",
"android.hardware.hardware_keystore.xml", // permissions
],
}
@@ -210,14 +209,3 @@
out: ["android.hardware.security.keymint-service.nonsecure.apex.rc"],
cmd: "sed -E 's%/vendor/bin/%/apex/com.android.hardware.keymint/bin/%' $(in) > $(out)",
}
-
-prebuilt_etc {
- name: "keymint_aidl_nonsecure_vintf",
- sub_dir: "vintf",
- vendor: true,
- srcs: [
- "android.hardware.security.keymint-service.xml",
- "android.hardware.security.sharedsecret-service.xml",
- "android.hardware.security.secureclock-service.xml",
- ],
-}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 06e0f58..0c86a27 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -328,7 +328,16 @@
* which is mandatory for KeyMint version 2 and first_api_level 33 or greater.
*/
bool KeyMintAidlTestBase::isDeviceIdAttestationRequired() {
- return AidlVersion() >= 2 && property_get_int32("ro.vendor.api_level", 0) >= __ANDROID_API_T__;
+ if (!is_gsi_image()) {
+ return AidlVersion() >= 2 &&
+ get_vendor_api_level() >= AVendorSupport_getVendorApiLevelOf(__ANDROID_API_T__);
+ } else {
+ // The device ID properties may not be set properly when testing earlier implementations
+ // under GSI, e.g. `ro.product.<id>` is overridden by the GSI image, but the
+ // `ro.product.vendor.<id>` value (which does survive GSI installation) was not set.
+ return AidlVersion() >= 2 &&
+ get_vendor_api_level() >= AVendorSupport_getVendorApiLevelOf(__ANDROID_API_U__);
+ }
}
/**
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp
index c1b5d48..5944908 100644
--- a/security/keymint/support/authorization_set.cpp
+++ b/security/keymint/support/authorization_set.cpp
@@ -22,6 +22,8 @@
#include <aidl/android/hardware/security/keymint/KeyParameter.h>
#include <aidl/android/hardware/security/keymint/KeyPurpose.h>
+#include <algorithm>
+
namespace aidl::android::hardware::security::keymint {
void AuthorizationSet::Sort() {
diff --git a/security/secretkeeper/OWNERS b/security/secretkeeper/OWNERS
index acf4c6c..d63ba9b 100644
--- a/security/secretkeeper/OWNERS
+++ b/security/secretkeeper/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 867125
-alanstokes@google.com
drysdale@google.com
hasinitg@google.com
shikhapanwar@google.com
diff --git a/security/see/authmgr/aidl/README.md b/security/see/authmgr/aidl/README.md
new file mode 100644
index 0000000..97b2b1d
--- /dev/null
+++ b/security/see/authmgr/aidl/README.md
@@ -0,0 +1,21 @@
+# AuthMgr
+
+The AuthMgr protocol authenticates and authorizes clients before they can
+access trusted HALs, AIDL-defined services in trusted execution environments.
+Version 1 was designed to allow applications running in a protected virtual
+machine (pVM) to access services running in a TEE in ARM TrustZone. An
+implementation of `IAuthMgrAuthorization` is referred to as an AuthMgr Backend.
+An implementation of a client of the AuthMgr Backend is referred to as an
+AuthMgr Frontend.
+
+
+## Additional Requirements by Android Version
+
+The comments on `IAuthMgrAuthorization` describe the requirements for implementing
+an AuthMgr Backend (implementor of the interface) itself. There are some additional
+requirements that are specific to Android release versions.
+
+### Android 16
+If implementing `IAuthMgrAuthorization` in Android 16 only one AuthMgr Backend is
+supported and dynamic service discovery is not supported. The AuthMgr Backend
+service must be exposed on secure partition ID 0x8001 over VSOCK port 1.
\ No newline at end of file
diff --git a/security/see/hwcrypto/aidl/vts/functional/Android.bp b/security/see/hwcrypto/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..beb8976
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/Android.bp
@@ -0,0 +1,83 @@
+// Copyright (C) 2024 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "hw_crypto_hal_aidl_rust_defaults",
+ enabled: false,
+ rustlibs: [
+ "libbinder_rs",
+ "android.hardware.security.see.hwcrypto-V1-rust",
+ "liblogger",
+ "liblog_rust",
+ "libanyhow",
+ "libvsock",
+ "librpcbinder_rs",
+ "librustutils",
+ ],
+ arch: {
+ x86_64: {
+ enabled: true,
+ },
+ },
+}
+
+rust_library {
+ name: "libhwcryptohal_vts_test",
+ crate_name: "hwcryptohal_vts_test",
+ srcs: [
+ "lib.rs",
+ ],
+ defaults: [
+ "hw_crypto_hal_aidl_rust_defaults",
+ ],
+}
+
+rust_binary {
+ name: "wait_hw_crypto",
+ prefer_rlib: true,
+ defaults: [
+ "hw_crypto_hal_aidl_rust_defaults",
+ ],
+ srcs: ["wait_service.rs"],
+ rustlibs: [
+ "libhwcryptohal_vts_test",
+ "liblogger",
+ "liblog_rust",
+ "libanyhow",
+ "libclap",
+ ],
+}
+
+rust_test {
+ name: "VtsAidlHwCryptoConnTest",
+ srcs: ["connection_test.rs"],
+ require_root: true,
+ defaults: [
+ "hw_crypto_hal_aidl_rust_defaults",
+ ],
+ rustlibs: [
+ "libhwcryptohal_vts_test",
+ ],
+ data: [
+ ":trusty_test_vm_elf",
+ ":trusty_test_vm_config",
+ ":trusty_vm_launcher_sh",
+ ":trusty_wait_ready_sh",
+ ":wait_hw_crypto",
+ ],
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml b/security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..73290cf
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/AndroidTest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2025 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 {MODULE}">
+ <!-- object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController" -->
+ <!--Skip the test when trusty VM is not enabled. -->
+ <!--option name="run-command" value="getprop trusty.test_vm.nonsecure_vm_ready | grep 1" /-->
+ <!--/object-->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <!-- Target Preparers - Run Shell Commands -->
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="trusty-vm-launcher.sh" value="/data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
+ <option name="push-file" key="trusty-wait-ready.sh" value="/data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
+ <option name="push-file" key="wait_hw_crypto" value="/data/local/tmp/trusty_test_vm/wait_hw_crypto" />
+ <option name="push-file" key="trusty-test_vm-config.json" value="/data/local/tmp/trusty_test_vm/trusty-test_vm-config.json" />
+ <option name="push-file" key="trusty_test_vm_elf" value="/data/local/tmp/trusty_test_vm/trusty_test_vm_elf" />
+ <option name="push-file" key="VtsAidlHwCryptoConnTest" value="/data/local/tmp/VtsAidlHwCryptoConnTest" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="throw-if-cmd-fail" value="true" />
+ <!--Note: the first run-command shall not expect the background command to have started -->
+ <option name="run-bg-command" value="sh /data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
+ <option name="run-command" value="sh /data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
+ <option name="run-bg-command" value="start trusty-hwcryptohal" />
+ <option name="run-command" value="/data/local/tmp/trusty_test_vm/wait_hw_crypto" />
+ <option name="run-command" value="start storageproxyd_test_system" />
+ <option name="teardown-command" value="stop storageproxyd_test_system" />
+ <option name="teardown-command" value="stop trusty-hwcryptohal" />
+ <option name="teardown-command" value="killall storageproxyd_test_system || true" />
+ <option name="teardown-command" value="stop trusty-hwcryptohal" />
+ <option name="teardown-command" value="killall trusty || true" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+ <option name="test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsAidlHwCryptoConnTest" />
+ <!-- Rust tests are run in parallel by default. Run these ones
+ single-threaded, so that one test's secrets don't affect
+ the behaviour of a different test. -->
+ <option name="native-test-flag" value="--test-threads=1" />
+ </test>
+ </configuration>
diff --git a/security/see/hwcrypto/aidl/vts/functional/connection_test.rs b/security/see/hwcrypto/aidl/vts/functional/connection_test.rs
new file mode 100644
index 0000000..338923d
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/connection_test.rs
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! HwCrypto Connection tests.
+
+#[test]
+fn test_hwcrypto_key_connection() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey();
+ assert!(hw_crypto_key.is_ok(), "Couldn't get back a hwcryptokey binder object");
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/lib.rs b/security/see/hwcrypto/aidl/vts/functional/lib.rs
new file mode 100644
index 0000000..e14ac83
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/lib.rs
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! VTS test library for HwCrypto functionality.
+//! It provides the base clases necessaries to write HwCrypto VTS tests
+
+use anyhow::{Context, Result};
+use binder::{ExceptionCode, FromIBinder, IntoBinderResult, ParcelFileDescriptor};
+use rpcbinder::RpcSession;
+use vsock::VsockStream;
+use std::os::fd::{FromRawFd, IntoRawFd};
+use std::fs::File;
+use std::io::Read;
+use rustutils::system_properties;
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::IHwCryptoKey;
+
+const HWCRYPTO_SERVICE_PORT: u32 = 4;
+
+/// Local function to connect to service
+pub fn connect_service<T: FromIBinder + ?Sized>(
+ cid: u32,
+ port: u32,
+) -> Result<binder::Strong<T>, binder::StatusCode> {
+ RpcSession::new().setup_preconnected_client(|| {
+ let mut stream = VsockStream::connect_with_cid_port(cid, port).ok()?;
+ let mut buffer = [0];
+ let _ = stream.read(&mut buffer);
+ // SAFETY: ownership is transferred from stream to f
+ let f = unsafe { File::from_raw_fd(stream.into_raw_fd()) };
+ Some(ParcelFileDescriptor::new(f).into_raw_fd())
+ })
+}
+
+/// Get a HwCryptoKey binder service object
+pub fn get_hwcryptokey() -> Result<binder::Strong<dyn IHwCryptoKey>, binder::Status> {
+ let cid = system_properties::read("trusty.test_vm.vm_cid")
+ .context("couldn't get vm cid")
+ .or_binder_exception(ExceptionCode::ILLEGAL_STATE)?
+ .ok_or(ExceptionCode::ILLEGAL_STATE)?
+ .parse::<u32>()
+ .context("couldn't parse vm cid")
+ .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?;
+ Ok(connect_service(cid, HWCRYPTO_SERVICE_PORT)?)
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/wait_service.rs b/security/see/hwcrypto/aidl/vts/functional/wait_service.rs
new file mode 100644
index 0000000..13cbcb1
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/wait_service.rs
@@ -0,0 +1,47 @@
+// Copyright 2025, 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.
+
+//! Small utility to wait for hwcrypto service to be up
+
+use anyhow::{/*Context,*/ Result};
+use clap::Parser;
+use log::info;
+use std::{thread, time};
+
+#[derive(Parser)]
+/// Collection of CLI for trusty_security_vm_launcher
+pub struct Args {
+ /// Number of repetitions for the wait
+ #[arg(long, default_value_t = 20)]
+ number_repetitions: u32,
+
+ /// Delay between repetitiond
+ #[arg(long, default_value_t = 2)]
+ delay_between_repetitions: u32,
+}
+
+fn main() -> Result<()> {
+ let args = Args::parse();
+
+ info!("Waiting for hwcrypto service");
+ let delay = time::Duration::new(args.delay_between_repetitions.into(), 0);
+ for _ in 0..args.number_repetitions {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey();
+ if hw_crypto_key.is_ok() {
+ break;
+ }
+ thread::sleep(delay);
+ }
+ Ok(())
+}
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 7f33e2d..687b5ed 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -38,6 +38,7 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/binder_status.h>
+#include <cutils/properties.h>
#include <gtest/gtest.h>
#include <unistd.h>
@@ -175,6 +176,34 @@
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
}
}
+
+ bool isEmulator() {
+ if (property_get_bool("ro.boot.qemu", false)) {
+ return true;
+ }
+ char device[PROP_VALUE_MAX];
+ char model[PROP_VALUE_MAX];
+ char name[PROP_VALUE_MAX];
+ char hardware[PROP_VALUE_MAX];
+
+ property_get("ro.product.device", device, "");
+ property_get("ro.product.model", model, "");
+ property_get("ro.product.name", name, "");
+ property_get("ro.hardware", hardware, "");
+
+ std::string deviceStr(device);
+ std::string modelStr(model);
+ std::string nameStr(name);
+ std::string hardwareStr(hardware);
+
+ return deviceStr.rfind("vsoc_", 0) == 0 || modelStr.rfind("Cuttlefish ", 0) == 0 ||
+ nameStr.rfind("cf_", 0) == 0 || nameStr.rfind("aosp_cf_", 0) == 0 ||
+ hardwareStr.find("goldfish") != std::string::npos ||
+ hardwareStr.find("ranchu") != std::string::npos ||
+ hardwareStr.find("cutf_cvm") != std::string::npos ||
+ hardwareStr.find("starfish") != std::string::npos;
+ }
+
// Stores thermal version
int32_t thermal_version;
@@ -355,6 +384,9 @@
if (apiLevel < 202404) {
GTEST_SKIP() << "Skipping test as the vendor level is below 202404: " << apiLevel;
}
+ if (isEmulator()) {
+ GTEST_SKIP() << "Skipping test on emulator";
+ }
for (const auto& feature : kNonHandheldFeatures) {
if (::testing::deviceSupportsFeature(feature.c_str())) {
GTEST_SKIP() << "Skipping test as the device has feature: " << feature;
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
index a840fa3..481f027 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -45,6 +45,41 @@
],
}
+cc_library_static {
+ name: "android.hardware.threadnetwork.lib",
+
+ vendor: true,
+ export_include_dirs: ["."],
+
+ defaults: ["android.hardware.threadnetwork-service.defaults"],
+
+ srcs: [
+ "service.cpp",
+ "thread_chip.cpp",
+ "utils.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder_ndk",
+ "liblog",
+ ],
+
+ static_libs: [
+ "android.hardware.threadnetwork-V1-ndk",
+ "libbase",
+ "libcutils",
+ "libutils",
+ "openthread-common",
+ "openthread-hdlc",
+ "openthread-platform",
+ "openthread-posix",
+ "openthread-spi",
+ "openthread-url",
+ ],
+
+ stl: "c++_static",
+}
+
cc_defaults {
name: "android.hardware.threadnetwork-service.defaults",
product_variables: {
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index e312728..ba0baf2 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -83,6 +83,11 @@
mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetFrame() + mRxFrameBuffer.GetLength()));
}
+ if (mVendorCallback != nullptr) {
+ mVendorCallback->onReceiveSpinelFrame(std::vector<uint8_t>(
+ mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetFrame() + mRxFrameBuffer.GetLength()));
+ }
+
mRxFrameBuffer.DiscardFrame();
}
@@ -193,6 +198,10 @@
}
}
+void ThreadChip::setVendorCallback(const std::shared_ptr<IThreadChipCallback>& vendorCallback) {
+ mVendorCallback = vendorCallback;
+}
+
ndk::ScopedAStatus ThreadChip::errorStatus(int32_t error, const char* message) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(error, message));
}
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index d07d049..6f23efe 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -43,6 +43,7 @@
ndk::ScopedAStatus hardwareReset() override;
void Update(otSysMainloopContext& context) override;
void Process(const otSysMainloopContext& context) override;
+ void setVendorCallback(const std::shared_ptr<IThreadChipCallback>& vendorCallback);
private:
static void onBinderDiedJump(void* context);
@@ -59,6 +60,7 @@
std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface;
ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
std::shared_ptr<IThreadChipCallback> mCallback;
+ std::shared_ptr<IThreadChipCallback> mVendorCallback;
::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
};
diff --git a/wifi/OWNERS b/wifi/OWNERS
index c10bbab..ec21f2e 100644
--- a/wifi/OWNERS
+++ b/wifi/OWNERS
@@ -7,4 +7,3 @@
# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
#
arabawy@google.com
-etancohen@google.com
diff --git a/wifi/apex/Android.bp b/wifi/apex/Android.bp
index f8c8e6f..5052ebb 100644
--- a/wifi/apex/Android.bp
+++ b/wifi/apex/Android.bp
@@ -15,13 +15,6 @@
installable: false,
}
-prebuilt_etc {
- name: "com.android.hardware.wifi.xml",
- src: ":default-android.hardware.wifi-service.xml",
- installable: false,
- sub_dir: "vintf",
-}
-
apex {
name: "com.android.hardware.wifi",
manifest: "apex_manifest.json",
@@ -36,7 +29,6 @@
],
prebuilts: [
"com.android.hardware.wifi.rc",
- "com.android.hardware.wifi.xml",
],
overrides: [
"android.hardware.wifi-service",