Merge "VtsHalTargetTest: Configure channel layout and generate input data correctly" into main
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 0f2fe99..97577d1 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -60,7 +60,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "31",
},
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index b80e6ac..75d4d9e 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -74,13 +74,18 @@
/**
* Called by the framework to destroy the effect and free up all currently allocated resources.
- * It is recommended to destroy the effect from the client side as soon as it is becomes unused.
+ * This method can be called at any time to destroy an effect instance. It is recommended to
+ * destroy the effect from the client side as soon as it becomes unused to free up resources.
*
- * The client must ensure effect instance is closed before destroy.
+ * The effect instance must handle any necessary cleanup and resource deallocation.
+ * If the effect is in the **PROCESSING** or **DRAINING** state, it must gracefully stop
+ * processing before destruction.
+ * The effect must ensure that all internal states are properly cleaned up to prevent resource
+ * leaks.
*
* @param handle The handle of effect instance to be destroyed.
* @throws EX_ILLEGAL_ARGUMENT if the effect handle is not valid.
- * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+ * @throws EX_ILLEGAL_STATE if the effect instance can not be destroyed.
*/
void destroyEffect(in IEffect handle);
}
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
index 1b698d7..ecd1bbe 100644
--- a/audio/aidl/android/hardware/audio/effect/State.aidl
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -24,6 +24,8 @@
* it should transfer to IDLE state after handle the command successfully. Effect instance should
* consume minimal resource and transfer to INIT state after it was close().
*
+ * An effect instance can be destroyed from any state using `IFactory.destroyEffect()`.
+ *
* Refer to the state machine diagram `state.gv` for a detailed state diagram.
*/
@VintfStability
@@ -66,6 +68,7 @@
* - Transitions to **INIT** on `IEffect.close()`.
* - Remains in **IDLE** on `IEffect.getParameter()`, `IEffect.setParameter()`,
* `IEffect.getDescriptor()`, `IEffect.command(CommandId.RESET)`, and `IEffect.reopen()`.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
IDLE,
@@ -98,6 +101,7 @@
* stop processing with `CommandId.STOP` before closing.
* - If `IEffect.close()` is called in this state, the effect instance should stop processing,
* transition to **IDLE**, and then close.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
PROCESSING,
@@ -123,6 +127,7 @@
* - If not implemented, the effect instance may transition directly from **PROCESSING** to
* **IDLE** without this intermediate state.
* - Any `CommandId.STOP` commands received during **DRAINING** should be ignored.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
DRAINING,
}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
index 2a8194e..8590296 100644
--- a/audio/aidl/android/hardware/audio/effect/state.gv
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// To render: "dot -Tpng state.gv -o state.png"
+// To render: "dot -Tpng state.gv -o state.png"
digraph effect_state_machine {
rankdir=LR; // Left to Right layout
@@ -29,40 +29,30 @@
I [shape=point, fillcolor=black, width=0.2];
// Final state node
- F [shape=doublecircle, fillcolor=white, width=0.2];
+ F [shape=doublecircle, label="Destroyed"];
// Define other nodes with colors
- INIT [shape=ellipse, fillcolor=lightgreen];
- IDLE [shape=ellipse, fillcolor=lightblue];
- PROCESSING [shape=ellipse, fillcolor=lightyellow];
- DRAINING [shape=ellipse, fillcolor=lightgrey];
+ INIT [shape=ellipse, fillcolor=lightgreen, label="INIT"];
+ IDLE [shape=ellipse, fillcolor=lightblue, label="IDLE"];
+ PROCESSING [shape=ellipse, fillcolor=lightyellow, label="PROCESSING"];
+ DRAINING [shape=ellipse, fillcolor=lightgrey, label="DRAINING"];
+ ANY_STATE [shape=ellipse, style=dashed, label="Any State", fillcolor=white];
- // Transitions
+ // Main transitions
I -> INIT [label="IFactory.createEffect", fontcolor="navy"];
-
- INIT -> F [label="IFactory.destroyEffect"];
-
INIT -> IDLE [label="IEffect.open()", fontcolor="lime"];
-
IDLE -> PROCESSING [label="IEffect.command(START)"];
-
- PROCESSING -> IDLE [label="IEffect.command(STOP)\nIEffect.command(RESET)"];
-
- PROCESSING -> DRAINING [label="IEffect.command(STOP)", fontcolor="orange"];
-
- DRAINING -> IDLE [label="Draining complete\n(IEffect.command(RESET)\nautomatic)"];
-
- DRAINING -> PROCESSING [label="IEffect.command(START)\n(Interrupt draining)"];
-
+ PROCESSING -> IDLE [label="IEffect.command(STOP) (if draining not required)\nIEffect.command(RESET)"];
+ PROCESSING -> DRAINING [label="IEffect.command(STOP) (if draining required)", fontcolor="orange"];
+ DRAINING -> IDLE [label="IEffect.command(RESET)\nDraining complete (automatic transition)"];
+ DRAINING -> PROCESSING [label="IEffect.command(START) (Interrupt draining)"];
IDLE -> INIT [label="IEffect.close()"];
- // Self-loops
- INIT -> INIT [label="IEffect.getState\nIEffect.getDescriptor"];
-
- IDLE -> IDLE [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.command(RESET)\nIEffect.reopen"];
-
- PROCESSING -> PROCESSING [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.reopen"];
-
- DRAINING -> DRAINING [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.reopen\nFading"];
-
+ // Global transitions
+ subgraph cluster_global_transitions {
+ label="Global Transitions (Any State)";
+ style=dashed;
+ ANY_STATE -> F [label="IFactory.destroyEffect", style="bold"];
+ ANY_STATE -> ANY_STATE [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.getState\nIEffect.reopen", fontsize=10];
+ }
}
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index 7857f53..97f7286 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -22,7 +22,10 @@
#include "effect-impl/EffectTypes.h"
#include "include/effect-impl/EffectTypes.h"
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
using aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
using aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
@@ -31,13 +34,45 @@
using ::android::hardware::EventFlag;
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
- State state;
- ndk::ScopedAStatus status = instanceSp->getState(&state);
- if (!status.isOk() || State::INIT != state) {
+ if (!instanceSp) {
+ LOG(ERROR) << __func__ << " nullptr";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+
+ Descriptor desc;
+ ndk::ScopedAStatus status = instanceSp->getDescriptor(&desc);
+ if (!status.isOk()) {
LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " failed to get descriptor, status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+
+ State state;
+ status = instanceSp->getState(&state);
+ if (!status.isOk()) {
+ LOG(ERROR) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
<< " in state: " << toString(state) << ", status: " << status.getDescription();
return EX_ILLEGAL_STATE;
}
+
+ int effectVersion = 0;
+ if (!instanceSp->getInterfaceVersion(&effectVersion).isOk()) {
+ LOG(WARNING) << __func__ << " " << desc.common.name << " failed to get interface version";
+ }
+
+ if (effectVersion < kDestroyAnyStateSupportedVersion) {
+ if (State::INIT != state) {
+ LOG(ERROR) << __func__ << " " << desc.common.name << " can not destroy instance "
+ << instanceSp.get() << " in state: " << toString(state);
+ return EX_ILLEGAL_STATE;
+ }
+ } else {
+ instanceSp->command(CommandId::RESET);
+ instanceSp->close();
+ }
+
+ LOG(DEBUG) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
+ << " destroyed";
return EX_NONE;
}
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 5a8b0a3..d945b17 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -179,8 +179,13 @@
const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
AudioHalProductStrategy aidlProductStrategy;
- aidlProductStrategy.id =
- VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
+ if (xsdcProductStrategy.hasId()) {
+ aidlProductStrategy.id =
+ VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
+ } else {
+ aidlProductStrategy.id =
+ VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
+ }
aidlProductStrategy.name = xsdcProductStrategy.getName();
if (xsdcProductStrategy.hasAttributesGroup()) {
diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
index c16e366..cfd99eb 100644
--- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -105,7 +105,8 @@
<xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="id" type="xs:int" use="required"/>
+ <!-- Only needs to be specified for vendor strategies. -->
+ <xs:attribute name="id" type="xs:int" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index ea59771..cef0ea6 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -77,17 +77,15 @@
}
::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
- usleep(1000);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::flush() {
- usleep(1000);
- return ::android::OK;
+ // TODO(b/372951987): consider if this needs to be done from 'StreamInWorkerLogic::cycle'.
+ return mIsInput ? standby() : ::android::OK;
}
::android::status_t StreamRemoteSubmix::pause() {
- usleep(1000);
return ::android::OK;
}
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
index 325a012..445b1d3 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.cpp
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -134,10 +134,10 @@
// - the peer input is in standby AFTER having been active.
// We DO block if:
// - the input was never activated to avoid discarding first frames in the pipe in case capture
-// start was delayed
+// start was delayed
bool SubmixRoute::shouldBlockWrite() {
std::lock_guard guard(mLock);
- return (mStreamInOpen || (mStreamInStandby && (mReadCounterFrames != 0)));
+ return mStreamInOpen && (!mStreamInStandby || mReadCounterFrames == 0);
}
long SubmixRoute::updateReadCounterFrames(size_t frameCount) {
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index d714ef4..754a08f 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -47,6 +47,7 @@
using aidl::android::hardware::audio::effect::getRange;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::isRangeValid;
+using aidl::android::hardware::audio::effect::kDrainSupportedVersion;
using aidl::android::hardware::audio::effect::kEffectTypeUuidSpatializer;
using aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
using aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
@@ -197,8 +198,11 @@
ASSERT_TRUE(expectState(effect, State::PROCESSING));
break;
case CommandId::STOP:
- ASSERT_TRUE(expectState(effect, State::IDLE) ||
- expectState(effect, State::DRAINING));
+ // Enforce the state checking after kDrainSupportedVersion
+ if (getHalVersion(effect) >= kDrainSupportedVersion) {
+ ASSERT_TRUE(expectState(effect, State::IDLE) ||
+ expectState(effect, State::DRAINING));
+ }
break;
case CommandId::RESET:
ASSERT_TRUE(expectState(effect, State::IDLE));
@@ -590,6 +594,11 @@
}
}
+ static int getHalVersion(const std::shared_ptr<IEffect>& effect) {
+ int version = 0;
+ return (effect && effect->getInterfaceVersion(&version).isOk()) ? version : 0;
+ }
+
bool mIsSpatializer;
Descriptor mDescriptor;
size_t mInputFrameSize, mOutputFrameSize;
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 53b6757..c007f18 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -139,12 +139,12 @@
};
TEST_P(AECParamTest, SetAndGetEchoDelay) {
- EXPECT_NO_FATAL_FAILURE(addEchoDelayParam(mEchoDelay));
+ addEchoDelayParam(mEchoDelay);
SetAndGetParameters();
}
TEST_P(AECParamTest, SetAndGetMobileMode) {
- EXPECT_NO_FATAL_FAILURE(addMobileModeParam(mMobileMode));
+ addMobileModeParam(mMobileMode);
SetAndGetParameters();
}
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index f14afbc..72a2d5e 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -139,17 +139,17 @@
};
TEST_P(AGC1ParamTest, SetAndGetTargetPeakLevelParam) {
- EXPECT_NO_FATAL_FAILURE(addTargetPeakLevelParam(mTargetPeakLevel));
+ addTargetPeakLevelParam(mTargetPeakLevel);
SetAndGetParameters();
}
TEST_P(AGC1ParamTest, SetAndGetMaxCompressionGain) {
- EXPECT_NO_FATAL_FAILURE(addMaxCompressionGainParam(mMaxCompressionGain));
+ addMaxCompressionGainParam(mMaxCompressionGain);
SetAndGetParameters();
}
TEST_P(AGC1ParamTest, SetAndGetEnableLimiter) {
- EXPECT_NO_FATAL_FAILURE(addEnableLimiterParam(mEnableLimiter));
+ addEnableLimiterParam(mEnableLimiter);
SetAndGetParameters();
}
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 048d540..ccac8c5 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -145,17 +145,17 @@
};
TEST_P(AGC2ParamTest, SetAndGetDigitalGainParam) {
- EXPECT_NO_FATAL_FAILURE(addDigitalGainParam(mGain));
+ addDigitalGainParam(mGain);
SetAndGetParameters();
}
TEST_P(AGC2ParamTest, SetAndGetSaturationMargin) {
- EXPECT_NO_FATAL_FAILURE(addSaturationMarginParam(mMargin));
+ addSaturationMarginParam(mMargin);
SetAndGetParameters();
}
TEST_P(AGC2ParamTest, SetAndGetLevelEstimator) {
- EXPECT_NO_FATAL_FAILURE(addLevelEstimatorParam(mLevelEstimator));
+ addLevelEstimatorParam(mLevelEstimator);
SetAndGetParameters();
}
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 93c2a61..750e54d 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -938,6 +938,8 @@
LOG(DEBUG) << __func__;
return "";
}
+ const std::vector<int8_t>& getData() const { return mData; }
+ void fillData(int8_t filler) { std::fill(mData.begin(), mData.end(), filler); }
std::optional<StreamDescriptor::Command> maybeGetNextCommand(int* actualSize = nullptr) {
TransitionTrigger trigger = mDriver->getNextTrigger(mData.size(), actualSize);
if (StreamEventReceiver::Event* expEvent =
@@ -1007,6 +1009,8 @@
StreamReaderLogic(const StreamContext& context, StreamLogicDriver* driver,
StreamEventReceiver* eventReceiver)
: StreamCommonLogic(context, driver, eventReceiver) {}
+ // Should only be called after the worker has joined.
+ const std::vector<int8_t>& getData() const { return StreamCommonLogic::getData(); }
protected:
Status cycle() override {
@@ -1072,6 +1076,7 @@
if (const size_t readCount =
!isMmapped() ? getDataMQ()->availableToRead() : reply.fmqByteCount;
readCount > 0) {
+ fillData(-1);
if (isMmapped() ? readDataFromMmap(readCount) : readDataFromMQ(readCount)) {
goto checkAcceptedReply;
}
@@ -1093,6 +1098,8 @@
StreamWriterLogic(const StreamContext& context, StreamLogicDriver* driver,
StreamEventReceiver* eventReceiver)
: StreamCommonLogic(context, driver, eventReceiver) {}
+ // Should only be called after the worker has joined.
+ const std::vector<int8_t>& getData() const { return StreamCommonLogic::getData(); }
protected:
Status cycle() override {
@@ -1109,6 +1116,14 @@
return Status::ABORT;
}
if (actualSize != 0) {
+ if (command.getTag() == StreamDescriptor::Command::burst) {
+ fillData(mBurstIteration);
+ if (mBurstIteration < std::numeric_limits<int8_t>::max()) {
+ mBurstIteration++;
+ } else {
+ mBurstIteration = 0;
+ }
+ }
if (isMmapped() ? !writeDataToMmap() : !writeDataToMQ()) {
return Status::ABORT;
}
@@ -1167,6 +1182,9 @@
LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
return Status::ABORT;
}
+
+ private:
+ int8_t mBurstIteration = 1;
};
using StreamWriter = StreamWorker<StreamWriterLogic>;
@@ -2859,10 +2877,12 @@
ASSERT_NO_FATAL_FAILURE(mStream->SetUpStream(module, getMinimumStreamBufferSizeFrames()));
}
- void SetUpStreamForDevicePort(IModule* module, ModuleConfig* moduleConfig,
- const AudioPort& devicePort, bool connectedOnly = false) {
- ASSERT_NO_FATAL_FAILURE(
- SetUpPortConfigForDevicePort(module, moduleConfig, devicePort, connectedOnly));
+ void SetUpStreamForDevicePort(
+ IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+ bool connectedOnly = false,
+ const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
+ ASSERT_NO_FATAL_FAILURE(SetUpPortConfigForDevicePort(module, moduleConfig, devicePort,
+ connectedOnly, connectionAddress));
if (!mSkipTestReason.empty()) return;
ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
}
@@ -2898,6 +2918,23 @@
if (!mSkipTestReason.empty()) return;
ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
}
+ void SetUpStreamForNewMixPortConfig(IModule* module, ModuleConfig*,
+ const AudioPortConfig& existingMixPortConfig,
+ const AudioPortConfig& existingDevicePortConfig) {
+ auto mixPortConfig = existingMixPortConfig;
+ mixPortConfig.id = 0;
+ mMixPortConfig = std::make_unique<WithAudioPortConfig>(mixPortConfig);
+ ASSERT_NO_FATAL_FAILURE(mMixPortConfig->SetUp(module));
+ mDevicePortConfig = std::make_unique<WithAudioPortConfig>(existingDevicePortConfig);
+ ASSERT_NO_FATAL_FAILURE(mDevicePortConfig->SetUp(module));
+ mDevice = existingDevicePortConfig.ext.get<AudioPortExt::device>().device;
+ mPatch = std::make_unique<WithAudioPatch>(mIsInput, mMixPortConfig->get(),
+ mDevicePortConfig->get());
+ ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(module));
+ mStream = std::make_unique<WithStream<Stream>>(mMixPortConfig->get());
+ ASSERT_NO_FATAL_FAILURE(mStream->SetUpPortConfig(module));
+ ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
+ }
void SetUpPatchForMixPortConfig(IModule* module, ModuleConfig* moduleConfig,
const AudioPortConfig& mixPortConfig) {
constexpr bool connectedOnly = true;
@@ -2929,6 +2966,7 @@
}
const AudioDevice& getDevice() const { return mDevice; }
+ const AudioPortConfig& getDevicePortConfig() const { return mDevicePortConfig->get(); }
int32_t getMinimumStreamBufferSizeFrames() const {
return mPatch->getMinimumStreamBufferSizeFrames();
}
@@ -2944,7 +2982,8 @@
private:
void SetUpDevicePort(IModule* module, ModuleConfig* moduleConfig,
const std::set<int32_t>& devicePortIds, bool connectedOnly,
- std::optional<AudioPort>* connectedDevicePort) {
+ std::optional<AudioPort>* connectedDevicePort,
+ const std::optional<AudioDeviceAddress>& connectionAddress) {
const auto attachedDevicePorts = moduleConfig->getAttachedDevicePorts();
if (auto it = findAny<AudioPort>(attachedDevicePorts, devicePortIds);
it != attachedDevicePorts.end()) {
@@ -2961,7 +3000,12 @@
const auto externalDevicePorts = moduleConfig->getExternalDevicePorts();
if (auto it = findAny<AudioPort>(externalDevicePorts, devicePortIds);
it != externalDevicePorts.end()) {
- AudioPort portWithData = GenerateUniqueDeviceAddress(*it);
+ AudioPort portWithData = *it;
+ if (connectionAddress.has_value()) {
+ portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
+ *connectionAddress;
+ }
+ portWithData = GenerateUniqueDeviceAddress(portWithData);
mPortConnected = std::make_unique<WithDevicePortConnectedState>(portWithData);
ASSERT_NO_FATAL_FAILURE(mPortConnected->SetUp(module, moduleConfig));
*connectedDevicePort = mPortConnected->get();
@@ -2980,9 +3024,9 @@
LOG(DEBUG) << __func__ << ": " << mSkipTestReason;
return;
};
- ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(module, moduleConfig,
- extractIds<AudioPort>(devicePorts), connectedOnly,
- connectedDevicePort));
+ ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(
+ module, moduleConfig, extractIds<AudioPort>(devicePorts), connectedOnly,
+ connectedDevicePort, std::nullopt /*connectionAddress*/));
if (!connectedDevicePort->has_value()) {
mSkipTestReason = std::string("Unable to find a device port pair for mix port id ")
.append(std::to_string(mixPort.id));
@@ -2990,11 +3034,14 @@
return;
}
}
- void SetUpPortConfigForDevicePort(IModule* module, ModuleConfig* moduleConfig,
- const AudioPort& devicePort, bool connectedOnly) {
+ void SetUpPortConfigForDevicePort(
+ IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+ bool connectedOnly,
+ const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
std::optional<AudioPort> connectedDevicePort;
ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(module, moduleConfig, {devicePort.id},
- connectedOnly, &connectedDevicePort));
+ connectedOnly, &connectedDevicePort,
+ connectionAddress));
if (!connectedDevicePort.has_value()) {
mSkipTestReason = std::string("Device port id ")
.append(std::to_string(devicePort.id))
@@ -3135,7 +3182,8 @@
};
// Defined later together with state transition sequences.
-std::shared_ptr<StateSequence> makeBurstCommands(bool isSync);
+std::shared_ptr<StateSequence> makeBurstCommands(bool isSync, size_t burstCount = 10,
+ bool standbyInputWhenDone = false);
// Certain types of ports can not be used without special preconditions.
static bool skipStreamIoTestForMixPortConfig(const AudioPortConfig& portConfig) {
@@ -3160,10 +3208,11 @@
public:
explicit StreamFixtureWithWorker(bool isSync) : mIsSync(isSync) {}
- void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort) {
+ void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+ const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
mStream = std::make_unique<StreamFixture<Stream>>();
- ASSERT_NO_FATAL_FAILURE(
- mStream->SetUpStreamForDevicePort(module, moduleConfig, devicePort));
+ ASSERT_NO_FATAL_FAILURE(mStream->SetUpStreamForDevicePort(
+ module, moduleConfig, devicePort, false /*connectedOnly*/, connectionAddress));
MaybeSetSkipTestReason();
}
@@ -3175,26 +3224,42 @@
MaybeSetSkipTestReason();
}
- void SendBurstCommands(bool validatePosition = true) {
- ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands());
+ void SetUp(IModule* module, ModuleConfig* moduleConfig,
+ const AudioPortConfig& existingMixPortConfig,
+ const AudioPortConfig& existingDevicePortConfig) {
+ mStream = std::make_unique<StreamFixture<Stream>>();
+ ASSERT_NO_FATAL_FAILURE(mStream->SetUpStreamForNewMixPortConfig(
+ module, moduleConfig, existingMixPortConfig, existingDevicePortConfig));
+ MaybeSetSkipTestReason();
+ }
+
+ void SendBurstCommands(bool validatePosition = true, size_t burstCount = 10,
+ bool standbyInputWhenDone = false) {
+ ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
ASSERT_NO_FATAL_FAILURE(JoinWorkerAfterBurstCommands(validatePosition));
}
- void StartWorkerToSendBurstCommands() {
+ void StartWorkerToSendBurstCommands(size_t burstCount = 10, bool standbyInputWhenDone = false) {
+ if (!IOTraits<Stream>::is_input) {
+ ASSERT_FALSE(standbyInputWhenDone) << "Only supported for input";
+ }
const StreamContext* context = mStream->getStreamContext();
mWorkerDriver = std::make_unique<StreamLogicDefaultDriver>(
- makeBurstCommands(mIsSync), context->getFrameSizeBytes(), context->isMmapped());
+ makeBurstCommands(mIsSync, burstCount, standbyInputWhenDone),
+ context->getFrameSizeBytes(), context->isMmapped());
mWorker = std::make_unique<typename IOTraits<Stream>::Worker>(
*context, mWorkerDriver.get(), mStream->getStreamEventReceiver());
LOG(DEBUG) << __func__ << ": starting " << IOTraits<Stream>::directionStr << " worker...";
ASSERT_TRUE(mWorker->start());
}
- void JoinWorkerAfterBurstCommands(bool validatePosition = true) {
- // Must call 'prepareToClose' before attempting to join because the stream may be stuck.
- std::shared_ptr<IStreamCommon> common;
- ASSERT_IS_OK(mStream->getStream()->getStreamCommon(&common));
- ASSERT_IS_OK(common->prepareToClose());
+ void JoinWorkerAfterBurstCommands(bool validatePosition = true,
+ bool callPrepareToClose = true) {
+ if (callPrepareToClose) {
+ std::shared_ptr<IStreamCommon> common;
+ ASSERT_IS_OK(mStream->getStream()->getStreamCommon(&common));
+ ASSERT_IS_OK(common->prepareToClose());
+ }
LOG(DEBUG) << __func__ << ": joining " << IOTraits<Stream>::directionStr << " worker...";
mWorker->join();
EXPECT_FALSE(mWorker->hasError()) << mWorker->getError();
@@ -3205,6 +3270,7 @@
EXPECT_FALSE(mWorkerDriver->hasObservableRetrogradePosition());
EXPECT_FALSE(mWorkerDriver->hasHardwareRetrogradePosition());
}
+ mLastData = mWorker->getData();
mWorker.reset();
mWorkerDriver.reset();
}
@@ -3212,6 +3278,9 @@
void TeardownPatch() { mStream->TeardownPatch(); }
const AudioDevice& getDevice() const { return mStream->getDevice(); }
+ const AudioPortConfig& getDevicePortConfig() const { return mStream->getDevicePortConfig(); }
+ const std::vector<int8_t>& getLastData() const { return mLastData; }
+ const AudioPortConfig& getPortConfig() const { return mStream->getPortConfig(); }
Stream* getStream() const { return mStream->getStream(); }
std::string skipTestReason() const {
return !mSkipTestReason.empty() ? mSkipTestReason : mStream->skipTestReason();
@@ -3229,6 +3298,7 @@
std::unique_ptr<StreamFixture<Stream>> mStream;
std::unique_ptr<StreamLogicDefaultDriver> mWorkerDriver;
std::unique_ptr<typename IOTraits<Stream>::Worker> mWorker;
+ std::vector<int8_t> mLastData;
};
template <typename Stream>
@@ -4576,15 +4646,20 @@
// TODO: Add async test cases for input once it is implemented.
-std::shared_ptr<StateSequence> makeBurstCommands(bool isSync) {
+std::shared_ptr<StateSequence> makeBurstCommands(bool isSync, size_t burstCount,
+ bool standbyInputWhenDone) {
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
- StateDag::Node last = d->makeFinalNode(State::ACTIVE);
+ StateDag::Node active = d->makeFinalNode(State::ACTIVE);
+ StateDag::Node paused = d->makeNodes({std::make_pair(State::ACTIVE, kPauseCommand),
+ std::make_pair(State::PAUSED, kFlushCommand)},
+ State::STANDBY);
+ StateDag::Node& last = standbyInputWhenDone ? paused : active;
if (isSync) {
StateDag::Node idle = d->makeNode(
State::IDLE, kBurstCommand,
// Use several bursts to ensure that the driver starts reporting the position.
- d->makeNodes(State::ACTIVE, kBurstCommand, 10, last));
+ d->makeNodes(State::ACTIVE, kBurstCommand, burstCount, last));
d->makeNode(State::STANDBY, kStartCommand, idle);
} else {
StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
@@ -4949,49 +5024,69 @@
public:
WithRemoteSubmix() : mStream(true /*isSync*/) {}
explicit WithRemoteSubmix(AudioDeviceAddress address)
- : mStream(true /*isSync*/), mAddress(address) {}
+ : mStream(true /*isSync*/), mAddress(address) {
+ LOG(DEBUG) << __func__ << ": Creating " << IOTraits<Stream>::directionStr
+ << " stream for: " << mAddress.value_or(AudioDeviceAddress{}).toString();
+ }
WithRemoteSubmix(const WithRemoteSubmix&) = delete;
WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
+ ~WithRemoteSubmix() {
+ LOG(DEBUG) << __func__ << ": Deleting " << IOTraits<Stream>::directionStr
+ << " stream for: " << mAddress.value_or(AudioDeviceAddress{}).toString();
+ }
- static std::optional<AudioPort> getRemoteSubmixAudioPort(
- ModuleConfig* moduleConfig,
- const std::optional<AudioDeviceAddress>& address = std::nullopt) {
+ static std::optional<AudioPort> getRemoteSubmixAudioPort(ModuleConfig* moduleConfig) {
auto ports =
moduleConfig->getRemoteSubmixPorts(IOTraits<Stream>::is_input, true /*singlePort*/);
if (ports.empty()) return {};
- AudioPort port = ports.front();
- if (address) {
- port.ext.template get<AudioPortExt::Tag::device>().device.address = address.value();
- }
- return port;
+ return ports.front();
}
void SetUp(IModule* module, ModuleConfig* moduleConfig) {
- auto devicePort = getRemoteSubmixAudioPort(moduleConfig, mAddress);
+ auto devicePort = getRemoteSubmixAudioPort(moduleConfig);
ASSERT_TRUE(devicePort.has_value()) << "Device port for remote submix device not found";
- ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, *devicePort));
+ ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, *devicePort, mAddress));
mAddress = mStream.getDevice().address;
}
-
- void StartWorkerToSendBurstCommands() {
- ASSERT_NO_FATAL_FAILURE(mStream.StartWorkerToSendBurstCommands());
+ void SetUp(IModule* module, ModuleConfig* moduleConfig,
+ const AudioPortConfig& existingMixPortConfig,
+ const AudioPortConfig& existingDevicePortConfig) {
+ ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, existingMixPortConfig,
+ existingDevicePortConfig));
+ mAddress = mStream.getDevice().address;
+ }
+ void StartWorkerToSendBurstCommands(size_t burstCount = 10, bool standbyInputWhenDone = false) {
+ ASSERT_NO_FATAL_FAILURE(
+ mStream.StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
}
- void JoinWorkerAfterBurstCommands() {
- ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands());
+ void JoinWorkerAfterBurstCommands(bool callPrepareToCloseBeforeJoin) {
+ ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands(
+ true /*validatePositionIncrease*/, callPrepareToCloseBeforeJoin));
}
- void SendBurstCommands() {
- ASSERT_NO_FATAL_FAILURE(mStream.StartWorkerToSendBurstCommands());
- ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands());
+ void JoinWorkerAfterBurstCommands(bool validatePositionIncrease,
+ bool callPrepareToCloseBeforeJoin) {
+ ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands(validatePositionIncrease,
+ callPrepareToCloseBeforeJoin));
+ }
+
+ void SendBurstCommands(bool callPrepareToCloseBeforeJoin, size_t burstCount = 10,
+ bool standbyInputWhenDone = false) {
+ ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
+ // When 'burstCount == 0', there is no "previous" frame count, thus the check for
+ // the position increase fails.
+ ASSERT_NO_FATAL_FAILURE(JoinWorkerAfterBurstCommands(
+ burstCount > 0 /*validatePositionIncrease*/, callPrepareToCloseBeforeJoin));
}
std::optional<AudioDeviceAddress> getAudioDeviceAddress() const { return mAddress; }
+ const AudioPortConfig& getDevicePortConfig() const { return mStream.getDevicePortConfig(); }
+ int8_t getLastBurstIteration() const { return mStream.getLastData()[0]; }
+ const AudioPortConfig& getPortConfig() const { return mStream.getPortConfig(); }
std::string skipTestReason() const { return mStream.skipTestReason(); }
private:
- void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort) {}
-
StreamFixtureWithWorker<Stream> mStream;
std::optional<AudioDeviceAddress> mAddress;
};
@@ -5007,77 +5102,130 @@
}
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
}
+
+ void TearDown() override {
+ streamIn.reset();
+ streamOut.reset();
+ }
+
+ void CreateOutputStream() {
+ streamOut = std::make_unique<WithRemoteSubmix<IStreamOut>>();
+ ASSERT_NO_FATAL_FAILURE(streamOut->SetUp(module.get(), moduleConfig.get()));
+ // Note: any issue with connection attempts is considered as a problem.
+ ASSERT_EQ("", streamOut->skipTestReason());
+ ASSERT_TRUE(streamOut->getAudioDeviceAddress().has_value());
+ }
+
+ void CreateInputStream(const std::optional<AudioDeviceAddress>& address = std::nullopt) {
+ if (address.has_value()) {
+ streamIn = std::make_unique<WithRemoteSubmix<IStreamIn>>(address.value());
+ } else {
+ ASSERT_TRUE(streamOut->getAudioDeviceAddress().has_value());
+ streamIn = std::make_unique<WithRemoteSubmix<IStreamIn>>(
+ streamOut->getAudioDeviceAddress().value());
+ }
+ ASSERT_NO_FATAL_FAILURE(streamIn->SetUp(module.get(), moduleConfig.get()));
+ ASSERT_EQ("", streamIn->skipTestReason());
+ auto inAddress = streamIn->getAudioDeviceAddress();
+ ASSERT_TRUE(inAddress.has_value());
+ if (address.has_value()) {
+ if (address.value() != AudioDeviceAddress{}) {
+ ASSERT_EQ(address.value(), inAddress.value());
+ }
+ } else {
+ ASSERT_EQ(streamOut->getAudioDeviceAddress().value(), inAddress.value());
+ }
+ }
+
+ std::unique_ptr<WithRemoteSubmix<IStreamOut>> streamOut;
+ std::unique_ptr<WithRemoteSubmix<IStreamIn>> streamIn;
};
TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenNoInput) {
- WithRemoteSubmix<IStreamOut> streamOut;
- ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
- // Note: here and in other tests any issue with connection attempts is considered as a problem.
- ASSERT_EQ("", streamOut.skipTestReason());
- ASSERT_NO_FATAL_FAILURE(streamOut.SendBurstCommands());
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(streamOut->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
}
-TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputStuck) {
- WithRemoteSubmix<IStreamOut> streamOut;
- ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
- ASSERT_EQ("", streamOut.skipTestReason());
- auto address = streamOut.getAudioDeviceAddress();
- ASSERT_TRUE(address.has_value());
+TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputInStandby) {
+ if (int32_t version; module->getInterfaceVersion(&version).isOk() && version < 3) {
+ GTEST_SKIP() << "Default remote submix implementation <V3 could not pass this test";
+ }
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+ ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+ // Send just 1 burst command. This triggers the condition "input is in standby after
+ // being active." The output must flush the fifo before writing to avoid being blocked.
+ ASSERT_NO_FATAL_FAILURE(
+ streamIn->StartWorkerToSendBurstCommands(1, true /*stanbyInputWhenDone*/));
+ // The output must be able to close without shutting down the pipe first (due to a call
+ // to 'prepareToClose').
+ ASSERT_NO_FATAL_FAILURE(
+ streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+ ASSERT_NO_FATAL_FAILURE(
+ streamIn->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+}
- WithRemoteSubmix<IStreamIn> streamIn(address.value());
- ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
- ASSERT_EQ("", streamIn.skipTestReason());
+TEST_P(AudioModuleRemoteSubmix, BlockedOutputUnblocksOnClose) {
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+ ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+ // Send just 3 burst command, but do not enter standby. This is a stalled input.
+ ASSERT_NO_FATAL_FAILURE(streamIn->StartWorkerToSendBurstCommands(3));
+ ASSERT_NO_FATAL_FAILURE(
+ streamOut->JoinWorkerAfterBurstCommands(true /*callPrepareToCloseBeforeJoin*/));
+ ASSERT_NO_FATAL_FAILURE(
+ streamIn->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+}
- ASSERT_NO_FATAL_FAILURE(streamOut.SendBurstCommands());
+TEST_P(AudioModuleRemoteSubmix, OutputBlocksUntilInputStarts) {
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+ ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+ // Read the head of the pipe and check that it starts with the first output burst, that is,
+ // the contents of the very first write has not been superseded due to pipe overflow.
+ // The burstCount is '0' because the very first burst is used to exit from the 'IDLE' state,
+ // see 'makeBurstCommands'.
+ ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/, 0,
+ true /*standbyInputWhenDone*/));
+ EXPECT_EQ(1, streamIn->getLastBurstIteration());
+ ASSERT_NO_FATAL_FAILURE(
+ streamOut->JoinWorkerAfterBurstCommands(true /*callPrepareToCloseBeforeJoin*/));
}
TEST_P(AudioModuleRemoteSubmix, OutputAndInput) {
- WithRemoteSubmix<IStreamOut> streamOut;
- ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
- ASSERT_EQ("", streamOut.skipTestReason());
- auto address = streamOut.getAudioDeviceAddress();
- ASSERT_TRUE(address.has_value());
-
- WithRemoteSubmix<IStreamIn> streamIn(address.value());
- ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
- ASSERT_EQ("", streamIn.skipTestReason());
-
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(CreateInputStream());
// Start writing into the output stream.
- ASSERT_NO_FATAL_FAILURE(streamOut.StartWorkerToSendBurstCommands());
+ ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
// Simultaneously, read from the input stream.
- ASSERT_NO_FATAL_FAILURE(streamIn.SendBurstCommands());
- ASSERT_NO_FATAL_FAILURE(streamOut.JoinWorkerAfterBurstCommands());
+ ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+ ASSERT_NO_FATAL_FAILURE(
+ streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
}
TEST_P(AudioModuleRemoteSubmix, OpenInputMultipleTimes) {
- WithRemoteSubmix<IStreamOut> streamOut;
- ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
- ASSERT_EQ("", streamOut.skipTestReason());
- auto address = streamOut.getAudioDeviceAddress();
- ASSERT_TRUE(address.has_value());
-
- const size_t streamInCount = 3;
- std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(streamInCount);
- for (size_t i = 0; i < streamInCount; i++) {
- streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>(address.value());
- ASSERT_NO_FATAL_FAILURE(streamIns[i]->SetUp(module.get(), moduleConfig.get()));
+ ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+ ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+ ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+ ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/, 1,
+ true /*standbyInputWhenDone*/));
+ // For the new stream, only create a new mix port config and a new patch.
+ const size_t extraStreamInCount = 2;
+ std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(extraStreamInCount);
+ for (size_t i = 0; i < extraStreamInCount; i++) {
+ streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>();
+ ASSERT_NO_FATAL_FAILURE(streamIns[i]->SetUp(module.get(), moduleConfig.get(),
+ streamIn->getPortConfig(),
+ streamIn->getDevicePortConfig()));
ASSERT_EQ("", streamIns[i]->skipTestReason());
+ const auto inAddress = streamIns[i]->getAudioDeviceAddress();
+ ASSERT_TRUE(inAddress.has_value());
+ ASSERT_EQ(streamOut->getAudioDeviceAddress().value(), inAddress.value());
+ ASSERT_NO_FATAL_FAILURE(streamIns[i]->SendBurstCommands(
+ false /*callPrepareToCloseBeforeJoin*/, 1, true /*standbyInputWhenDone*/));
}
- // Start writing into the output stream.
- ASSERT_NO_FATAL_FAILURE(streamOut.StartWorkerToSendBurstCommands());
- // Simultaneously, read from input streams.
- for (size_t i = 0; i < streamInCount; i++) {
- ASSERT_NO_FATAL_FAILURE(streamIns[i]->StartWorkerToSendBurstCommands());
- }
- for (size_t i = 0; i < streamInCount; i++) {
- ASSERT_NO_FATAL_FAILURE(streamIns[i]->JoinWorkerAfterBurstCommands());
- }
- ASSERT_NO_FATAL_FAILURE(streamOut.JoinWorkerAfterBurstCommands());
- // Clean up input streams in the reverse order because the device connection is owned
- // by the first one.
- for (size_t i = streamInCount; i != 0; --i) {
- streamIns[i - 1].reset();
- }
+ ASSERT_NO_FATAL_FAILURE(
+ streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
}
INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index d23bdc9..5b78981 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -42,6 +42,7 @@
using aidl::android::hardware::audio::effect::Flags;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -316,28 +317,39 @@
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
TEST_P(AudioEffectTest, DestroyOpenEffects) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
-
- // cleanup
- ASSERT_NO_FATAL_FAILURE(close(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ if (mVersion < kDestroyAnyStateSupportedVersion) {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
}
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
TEST_P(AudioEffectTest, DestroyProcessingEffects) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(mEffect));
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
- // cleanup
- ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ if (mVersion < kDestroyAnyStateSupportedVersion) {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
}
TEST_P(AudioEffectTest, NormalSequenceStates) {
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 9c23e94..09b6621 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -545,7 +545,7 @@
};
TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mCfg));
+ addEngineConfig(mCfg);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -597,7 +597,7 @@
};
TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
- EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
+ addInputGain(mInputGain);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -656,7 +656,7 @@
mInputGain.push_back(DynamicsProcessing::InputGain(i, gainDb));
}
std::vector<float> output(mInput.size());
- EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
+ addInputGain(mInputGain);
EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
if (!isAllParamsValid()) {
continue;
@@ -723,8 +723,8 @@
};
TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
- EXPECT_NO_FATAL_FAILURE(addLimiterConfig(mLimiterConfigList));
+ addEngineConfig(mEngineConfigPreset);
+ addLimiterConfig(mLimiterConfigList);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -787,8 +787,8 @@
}
void setLimiterParamsAndProcess(std::vector<float>& input, std::vector<float>& output) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
- EXPECT_NO_FATAL_FAILURE(addLimiterConfig(mLimiterConfigList));
+ addEngineConfig(mEngineConfigPreset);
+ addLimiterConfig(mLimiterConfigList);
EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(input, output));
}
@@ -942,20 +942,20 @@
};
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
- EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg));
+ addEngineConfig(mEngineConfigPreset);
+ addPreEqChannelConfig(mCfg);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
- EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg));
+ addEngineConfig(mEngineConfigPreset);
+ addPostEqChannelConfig(mCfg);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
- EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg));
+ addEngineConfig(mEngineConfigPreset);
+ addMbcChannelConfig(mCfg);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -1023,27 +1023,27 @@
TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ addEngineConfig(mEngineConfigPreset);
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
for (int i = 0; i < mChannelCount; i++) {
cfgs[i].channel = i;
cfgs[i].enable = true;
}
- EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(cfgs));
- EXPECT_NO_FATAL_FAILURE(addPreEqBandConfigs(mCfgs));
+ addPreEqChannelConfig(cfgs);
+ addPreEqBandConfigs(mCfgs);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ addEngineConfig(mEngineConfigPreset);
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
for (int i = 0; i < mChannelCount; i++) {
cfgs[i].channel = i;
cfgs[i].enable = true;
}
- EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(cfgs));
- EXPECT_NO_FATAL_FAILURE(addPostEqBandConfigs(mCfgs));
+ addPostEqChannelConfig(cfgs);
+ addPostEqBandConfigs(mCfgs);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -1190,14 +1190,14 @@
TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ addEngineConfig(mEngineConfigPreset);
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
for (int i = 0; i < mChannelCount; i++) {
cfgs[i].channel = i;
cfgs[i].enable = true;
}
- EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(cfgs));
- EXPECT_NO_FATAL_FAILURE(addMbcBandConfigs(mCfgs));
+ addMbcChannelConfig(cfgs);
+ addMbcBandConfigs(mCfgs);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index a50e1b4..c5a9bad 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -140,12 +140,12 @@
};
TEST_P(NSParamTest, SetAndGetLevel) {
- EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
+ addLevelParam(mLevel);
SetAndGetParameters();
}
TEST_P(NSParamTest, SetAndGetType) {
- EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
+ addLevelParam(mLevel);
SetAndGetParameters();
}
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index a88a1cc..f019e2a 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -194,22 +194,22 @@
};
TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
- ASSERT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
+ addCaptureSizeParam(mCaptureSize);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
}
TEST_P(VisualizerParamTest, SetAndGetScalingMode) {
- ASSERT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
+ addScalingModeParam(mScalingMode);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
}
TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) {
- ASSERT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
+ addMeasurementModeParam(mMeasurementMode);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
}
TEST_P(VisualizerParamTest, SetAndGetLatency) {
- ASSERT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ addLatencyParam(mLatency);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
}
@@ -217,10 +217,10 @@
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
bool allParamsValid = true;
- ASSERT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
- ASSERT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
- ASSERT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
- ASSERT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ addCaptureSizeParam(mCaptureSize);
+ addScalingModeParam(mScalingMode);
+ addMeasurementModeParam(mMeasurementMode);
+ addLatencyParam(mLatency);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters(&allParamsValid));
Parameter getParam;
@@ -282,9 +282,9 @@
for (float maxAudioSampleValue : testMaxAudioSampleValueList) {
bool allParamsValid = true;
- ASSERT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
- ASSERT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
- ASSERT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ addCaptureSizeParam(mCaptureSize);
+ addScalingModeParam(mScalingMode);
+ addLatencyParam(mLatency);
ASSERT_NO_FATAL_FAILURE(SetAndGetParameters(&allParamsValid));
ASSERT_NO_FATAL_FAILURE(generateSineWave(std::vector<int>{1000}, mInputBuffer,
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index 02f66a3..d9c4f58 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -23,6 +23,6 @@
gen_java_constants: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
}
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 02e593a..2b86049 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -105,7 +105,7 @@
<xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="id" type="xs:int" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
diff --git a/automotive/can/aidl/default/CanController.cpp b/automotive/can/aidl/default/CanController.cpp
index 1435a02..40332d5 100644
--- a/automotive/can/aidl/default/CanController.cpp
+++ b/automotive/can/aidl/default/CanController.cpp
@@ -20,10 +20,10 @@
#include "CanBusSlcan.h"
#include "CanBusVirtual.h"
-#include <android-base/format.h>
#include <android-base/logging.h>
#include <filesystem>
+#include <format>
#include <fstream>
#include <regex>
@@ -235,7 +235,7 @@
std::string* ifaceName) {
*ifaceName = {};
if (mBusesByName.find(busName) == mBusesByName.end()) {
- return resultToStatus(Result::BAD_BUS_NAME, fmt::format("{} doesn't exist", busName));
+ return resultToStatus(Result::BAD_BUS_NAME, std::format("{} doesn't exist", busName));
}
*ifaceName = std::string(mBusesByName[busName]->getIfaceName());
return ok();
@@ -245,11 +245,11 @@
if (!isValidName(config.name)) {
LOG(ERROR) << "Bus name " << config.name << " is invalid";
return resultToStatus(Result::BAD_BUS_NAME,
- fmt::format("{} is not a valid bus name", config.name));
+ std::format("{} is not a valid bus name", config.name));
} else if (mBusesByName.find(config.name) != mBusesByName.end()) {
LOG(ERROR) << "A bus named " << config.name << " already exists!";
return resultToStatus(Result::INVALID_STATE,
- fmt::format("A bus named {} already exists", config.name));
+ std::format("A bus named {} already exists", config.name));
}
if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::virtualif) {
@@ -310,7 +310,7 @@
if (result != Result::OK) {
// the bus failed to come up, don't leave a broken entry in the map.
mBusesByName.erase(config.name);
- return resultToStatus(result, fmt::format("CanBus::up failed for {}", config.name));
+ return resultToStatus(result, std::format("CanBus::up failed for {}", config.name));
}
*ifaceName = mBusesByName[config.name]->getIfaceName();
@@ -321,11 +321,11 @@
if (mBusesByName.find(busName) == mBusesByName.end()) {
return resultToStatus(
Result::UNKNOWN_ERROR,
- fmt::format("Couldn't bring down {}, because it doesn't exist", busName));
+ std::format("Couldn't bring down {}, because it doesn't exist", busName));
}
Result result = mBusesByName[busName]->down();
if (result != Result::OK) {
- return resultToStatus(result, fmt::format("Couldn't bring down {}!", busName));
+ return resultToStatus(result, std::format("Couldn't bring down {}!", busName));
}
mBusesByName.erase(busName);
return ok();
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
index 86fc70a..6c83339 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
@@ -16,10 +16,10 @@
#define LOG_TAG "DefaultVehicleHalServer"
+#include <format>
#include <fstream>
#include <regex>
-#include <android-base/format.h>
#include <android-base/logging.h>
#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
@@ -237,7 +237,7 @@
auto values = mServerSidePropStore.readAllValues();
size_t i = 0;
for (const auto& value : values) {
- result.buffer += fmt::format("[{}]: {}\n", i, toString(value));
+ result.buffer += std::format("[{}]: {}\n", i, toString(value));
i++;
}
return result;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
index e9ebcc6..c735b05 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
@@ -15,6 +15,8 @@
*/
#define LOG_TAG "FakeUserHal"
+#include <format>
+
#include <cutils/log.h>
#include <utils/SystemClock.h>
@@ -312,34 +314,34 @@
}
std::string FakeUserHal::showDumpHelp() {
- return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+ return std::format("{}: dumps state used for user management\n", kUserHalDumpOption);
}
std::string FakeUserHal::dump(std::string indent) {
std::string info;
if (mInitialUserResponseFromCmd != nullptr) {
- info += fmt::format("{}InitialUserInfo response: {}\n", indent.c_str(),
+ info += std::format("{}InitialUserInfo response: {}\n", indent.c_str(),
toString(*mInitialUserResponseFromCmd).c_str());
} else {
- info += fmt::format("{}No InitialUserInfo response\n", indent.c_str());
+ info += std::format("{}No InitialUserInfo response\n", indent.c_str());
}
if (mSwitchUserResponseFromCmd != nullptr) {
- info += fmt::format("{}SwitchUser response: {}\n", indent.c_str(),
+ info += std::format("{}SwitchUser response: {}\n", indent.c_str(),
toString(*mSwitchUserResponseFromCmd).c_str());
} else {
- info += fmt::format("{}No SwitchUser response\n", indent.c_str());
+ info += std::format("{}No SwitchUser response\n", indent.c_str());
}
if (mCreateUserResponseFromCmd != nullptr) {
- info += fmt::format("{}CreateUser response: {}\n", indent.c_str(),
+ info += std::format("{}CreateUser response: {}\n", indent.c_str(),
toString(*mCreateUserResponseFromCmd).c_str());
} else {
- info += fmt::format("{}No CreateUser response\n", indent.c_str());
+ info += std::format("{}No CreateUser response\n", indent.c_str());
}
if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- info += fmt::format("{}SetUserIdentificationAssociation response: {}\n", indent.c_str(),
+ info += std::format("{}SetUserIdentificationAssociation response: {}\n", indent.c_str(),
toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
} else {
- info += fmt::format("{}No SetUserIdentificationAssociation response\n", indent.c_str());
+ info += std::format("{}No SetUserIdentificationAssociation response\n", indent.c_str());
}
return info;
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
index 122aee8..33cef54 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
@@ -17,7 +17,6 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
#define android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
-#include <android-base/format.h>
#include <android-base/result.h>
#include <android/hardware/automotive/vehicle/2.0/types.h>
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
index fcbe8fd..1bf5ce1 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
@@ -17,7 +17,6 @@
#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
-#include <android-base/format.h>
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
index 878c2e7..309dd5f 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
@@ -19,6 +19,8 @@
#include "UserHalHelper.h"
+#include <format>
+
#include <VehicleUtils.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -336,7 +338,7 @@
}
std::string FakeUserHal::showDumpHelp() const {
- return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+ return std::format("{}: dumps state used for user management\n", kUserHalDumpOption);
}
std::string FakeUserHal::dump() const {
@@ -344,23 +346,23 @@
std::string info;
if (mInitialUserResponseFromCmd != nullptr) {
- info += fmt::format("InitialUserInfo response: {}\n",
+ info += std::format("InitialUserInfo response: {}\n",
mInitialUserResponseFromCmd->toString());
} else {
info += "No InitialUserInfo response\n";
}
if (mSwitchUserResponseFromCmd != nullptr) {
- info += fmt::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString());
+ info += std::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString());
} else {
info += "No SwitchUser response\n";
}
if (mCreateUserResponseFromCmd != nullptr) {
- info += fmt::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString());
+ info += std::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString());
} else {
info += "No CreateUser response\n";
}
if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- info += fmt::format("SetUserIdentificationAssociation response: {}\n",
+ info += std::format("SetUserIdentificationAssociation response: {}\n",
mSetUserIdentificationAssociationResponseFromCmd->toString());
} else {
info += "No SetUserIdentificationAssociation response\n";
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
index 2efda5b..6fe40a6 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <format>
#include <vector>
#include <JsonConfigLoader.h>
@@ -21,7 +22,6 @@
#include <VehicleHalTypes.h>
#include <android-base/file.h>
-#include <android-base/format.h>
#include <android/hardware/automotive/vehicle/SubscribeOptions.pb.h>
#include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
#include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
@@ -106,13 +106,13 @@
INSTANTIATE_TEST_SUITE_P(DefaultConfigs, PropConfigConversionTest,
::testing::ValuesIn(prepareTestConfigs()),
[](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropConfig>& info) {
- return ::fmt::format("property_{:d}", info.param.prop);
+ return ::std::format("property_{:d}", info.param.prop);
});
INSTANTIATE_TEST_SUITE_P(TestValues, PropValueConversionTest,
::testing::ValuesIn(prepareTestValues()),
[](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropValue>& info) {
- return ::fmt::format("property_{:d}", info.param.prop);
+ return ::std::format("property_{:d}", info.param.prop);
});
TEST_F(PropValueConversionTest, testConvertSubscribeOption) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 90a7c46..2bb4ba8 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -17,9 +17,10 @@
#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
+#include <format>
+
#include <VehicleHalTypes.h>
-#include <android-base/format.h>
#include <android-base/result.h>
#include <math/HashCombine.h>
#include <utils/Log.h>
@@ -289,7 +290,7 @@
}
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
toInt(status),
- fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
+ std::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
}
template <class T, class E>
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
index 734c739..cc690d7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
@@ -57,7 +57,7 @@
private:
// Test timeout is 0.1s.
- static const int64_t TEST_TIMEOUT = 100000000;
+ static constexpr int64_t TEST_TIMEOUT = 100000000;
std::unique_ptr<PendingRequestPool> mPool;
};
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
index c4632d4..0561145 100644
--- a/biometrics/face/aidl/default/apex/Android.bp
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -19,7 +19,7 @@
apex {
name: "com.android.hardware.biometrics.face.virtual",
manifest: "manifest.json",
- file_contexts: "file_contexts",
+ file_contexts: ":com.android.biometrics.virtual.face-file_contexts",
key: "com.android.hardware.key",
certificate: ":com.android.hardware.certificate",
updatable: false,
diff --git a/biometrics/face/aidl/default/apex/file_contexts b/biometrics/face/aidl/default/apex/file_contexts
deleted file mode 100644
index 4f935c1..0000000
--- a/biometrics/face/aidl/default/apex/file_contexts
+++ /dev/null
@@ -1,3 +0,0 @@
-(/.*)? u:object_r:vendor_file:s0
-/etc(/.*)? u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:hal_face_default_exec:s0
\ No newline at end of file
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index bd1ca69..3ffc203 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -23,6 +23,6 @@
gen_java: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
}
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
index f8a05f1..9c65b62 100644
--- a/bluetooth/1.1/Android.bp
+++ b/bluetooth/1.1/Android.bp
@@ -23,6 +23,6 @@
gen_java: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
}
diff --git a/bluetooth/OWNERS b/bluetooth/OWNERS
index f401b8c..df250c8 100644
--- a/bluetooth/OWNERS
+++ b/bluetooth/OWNERS
@@ -1,5 +1,5 @@
# Bug component: 27441
+asoulier@google.com
henrichataing@google.com
-mylesgw@google.com
siyuanh@google.com
diff --git a/bluetooth/aidl/Android.bp b/bluetooth/aidl/Android.bp
index 721be73..0daecf7 100644
--- a/bluetooth/aidl/Android.bp
+++ b/bluetooth/aidl/Android.bp
@@ -32,7 +32,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "33",
},
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index 725ec11..61f9a35 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -26,6 +26,6 @@
gen_java: false,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
}
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
index 4ca0bef..4d01a00 100644
--- a/bluetooth/audio/2.1/Android.bp
+++ b/bluetooth/audio/2.1/Android.bp
@@ -25,7 +25,7 @@
],
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
gen_java: false,
}
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index dbff368..6d4edb1 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -48,7 +48,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "31",
},
diff --git a/bluetooth/ranging/aidl/Android.bp b/bluetooth/ranging/aidl/Android.bp
index 4096669..b5ae205 100644
--- a/bluetooth/ranging/aidl/Android.bp
+++ b/bluetooth/ranging/aidl/Android.bp
@@ -31,7 +31,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "33",
},
diff --git a/bluetooth/socket/aidl/Android.bp b/bluetooth/socket/aidl/Android.bp
index 77679f8..7c03677 100644
--- a/bluetooth/socket/aidl/Android.bp
+++ b/bluetooth/socket/aidl/Android.bp
@@ -37,7 +37,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "33",
},
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..2fd2dad 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -57,7 +57,7 @@
name: "android.hardware.boot-service.default_recovery",
defaults: ["android.hardware.boot-service_common"],
init_rc: ["android.hardware.boot-service.default_recovery.rc"],
- vintf_fragments: ["android.hardware.boot-service.default.xml"],
+ vintf_fragment_modules: ["android.hardware.boot-service.default.xml.recovery"],
recovery: true,
shared_libs: [
@@ -77,11 +77,16 @@
installable: false,
}
-prebuilt_etc {
+vintf_fragment {
+ name: "android.hardware.boot-service.default.xml.recovery",
+ src: "android.hardware.boot-service.default.xml",
+ recovery: true,
+}
+
+vintf_fragment {
name: "android.hardware.boot-service.default.xml",
src: "android.hardware.boot-service.default.xml",
- sub_dir: "vintf",
- installable: false,
+ vendor: true,
}
apex {
@@ -98,6 +103,8 @@
],
prebuilts: [
"android.hardware.boot-service.default.rc",
+ ],
+ vintf_fragment_modules: [
"android.hardware.boot-service.default.xml",
],
}
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 825c931..19f4839 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -147,6 +147,6 @@
stem: "compatibility_matrix.202504.xml",
srcs: ["compatibility_matrix.202504.xml"],
kernel_configs: [
- "kernel_config_w_6.12",
+ "kernel_config_b_6.12",
],
}
diff --git a/compatibility_matrices/bump.py b/compatibility_matrices/bump.py
index ee2fa88..bcb0fa6 100755
--- a/compatibility_matrices/bump.py
+++ b/compatibility_matrices/bump.py
@@ -181,14 +181,14 @@
help="VINTF level of the next version (e.g. 202504)")
parser.add_argument("current_letter",
type=str,
- help="Letter of the API level of the current version (e.g. v)")
+ help="Letter of the API level of the current version (e.g. b)")
parser.add_argument("next_letter",
type=str,
- help="Letter of the API level of the next version (e.g. w)")
+ help="Letter of the API level of the next version (e.g. c)")
parser.add_argument("platform_version",
type=str,
nargs="?",
- help="Android release version number number (e.g. 15)")
+ help="Android release version number number (e.g. 16)")
cmdline_args = parser.parse_args()
Bump(cmdline_args).run()
diff --git a/contexthub/aidl/Android.bp b/contexthub/aidl/Android.bp
index 674f8af..b56537a 100644
--- a/contexthub/aidl/Android.bp
+++ b/contexthub/aidl/Android.bp
@@ -35,7 +35,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "33",
apps_enabled: true,
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index c7c6453..87c3892 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -25,7 +25,7 @@
gen_java: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
"com.android.media",
"com.android.media.swcodec",
],
diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp
index e9f75c1..54f68c6 100644
--- a/graphics/bufferqueue/2.0/Android.bp
+++ b/graphics/bufferqueue/2.0/Android.bp
@@ -27,7 +27,7 @@
gen_java: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
"com.android.media",
"com.android.media.swcodec",
],
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
index b876bf3..1683c22 100644
--- a/graphics/common/1.0/Android.bp
+++ b/graphics/common/1.0/Android.bp
@@ -20,7 +20,7 @@
gen_java_constants: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
"com.android.media.swcodec",
"test_com.android.media.swcodec",
],
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index ff6c9b7..81df887 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -23,7 +23,7 @@
gen_java_constants: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
"com.android.media.swcodec",
"test_com.android.media.swcodec",
],
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
index b4663e5..e1f4fe0 100644
--- a/graphics/common/1.2/Android.bp
+++ b/graphics/common/1.2/Android.bp
@@ -24,7 +24,7 @@
gen_java_constants: true,
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
"com.android.media.swcodec",
"test_com.android.media.swcodec",
],
diff --git a/macsec/aidl/default/MacsecPskPlugin.cpp b/macsec/aidl/default/MacsecPskPlugin.cpp
index 82d2545..8cb5283 100644
--- a/macsec/aidl/default/MacsecPskPlugin.cpp
+++ b/macsec/aidl/default/MacsecPskPlugin.cpp
@@ -18,7 +18,6 @@
#include <openssl/cipher.h>
#include <openssl/mem.h>
-#include <android-base/format.h>
#include <android-base/logging.h>
namespace aidl::android::hardware::macsec {
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
index f97405e..8852f6c 100644
--- a/nfc/aidl/vts/functional/Android.bp
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -58,12 +58,12 @@
"CondVar.cpp",
],
include_dirs: [
- "system/nfc/src/gki/common",
- "system/nfc/src/gki/ulinux",
- "system/nfc/src/include",
- "system/nfc/src/nfa/include",
- "system/nfc/src/nfc/include",
- "system/nfc/utils/include",
+ "packages/modules/Nfc/libnfc-nci/src/gki/common",
+ "packages/modules/Nfc/libnfc-nci/src/gki/ulinux",
+ "packages/modules/Nfc/libnfc-nci/src/include",
+ "packages/modules/Nfc/libnfc-nci/src/nfa/include",
+ "packages/modules/Nfc/libnfc-nci/src/nfc/include",
+ "packages/modules/Nfc/libnfc-nci/utils/include",
],
shared_libs: [
"liblog",
diff --git a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
index ff2522c..e93de95 100644
--- a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
+++ b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
@@ -119,6 +119,7 @@
case NCI_MSG_PROP_ANDROID: {
uint8_t android_sub_opcode = p_param[3];
switch (android_sub_opcode) {
+ case NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH:
case NCI_ANDROID_PASSIVE_OBSERVE: {
sVSCmdStatus = p_param[4];
LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
@@ -157,7 +158,7 @@
static_cast<uint8_t>(enable ? NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE
: NCI_ANDROID_PASSIVE_OBSERVE_PARAM_DISABLE)};
- status = NFA_SendRawVsCommand(sizeof(cmd), cmd, nfaVSCallback);
+ status = NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, sizeof(cmd), cmd, nfaVSCallback);
if (status == NFA_STATUS_OK) {
if (!sNfaVsCommand.wait(1000)) {
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index e49a50d..09cf9aa 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -25,7 +25,7 @@
],
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
gen_java: true,
}
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 01c09d8..53ef145 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -227,7 +227,7 @@
java: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index 2945dab..e6d2fdf 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -45,6 +45,9 @@
void deleteAllKeys();
void destroyAttestationIds();
android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken);
+ /**
+ * @deprecated Method has never been used due to design limitations
+ */
void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken);
void earlyBootEnded();
byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index b57dd8a..cafec70 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -826,6 +826,7 @@
*
* @param passwordOnly N/A due to the deprecation
* @param timestampToken N/A due to the deprecation
+ * @deprecated Method has never been used due to design limitations
*/
void deviceLocked(in boolean passwordOnly, in @nullable TimeStampToken timestampToken);
@@ -964,10 +965,11 @@
* IKeyMintDevice must ignore KeyParameters with tags not included in the following list:
*
* o Tag::MODULE_HASH: holds a hash that must be included in attestations in the moduleHash
- * field of the software enforced authorization list. If Tag::MODULE_HASH is included in more
- * than one setAdditionalAttestationInfo call, the implementation should compare the initial
- * KeyParamValue with the more recent one. If they differ, the implementation should fail with
- * ErrorCode::MODULE_HASH_ALREADY_SET. If they are the same, no action needs to be taken.
+ * field of the software enforced authorization list.
+ *
+ * @return error ErrorCode::MODULE_HASH_ALREADY_SET if this is not the first time
+ * setAdditionalAttestationInfo is called with Tag::MODULE_HASH, and the associated
+ * KeyParamValue of the current call doesn't match the KeyParamValue of the first call.
*/
void setAdditionalAttestationInfo(in KeyParameter[] info);
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index e56c193..7ea5f5d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -904,6 +904,9 @@
* Tag::MODULE_HASH specifies the SHA-256 hash of the DER-encoded module information (see
* KeyCreationResult.aidl for the ASN.1 schema).
*
+ * KeyStore clients can retrieve the unhashed DER-encoded module information from Android
+ * via KeyStoreManager.getSupplementaryAttestationInfo.
+ *
* This tag is never provided or returned from KeyMint in the key characteristics. It exists
* only to define the tag for use in the attestation record.
*
diff --git a/security/keymint/aidl/default/hal/lib.rs b/security/keymint/aidl/default/hal/lib.rs
index fad807f..196cf17 100644
--- a/security/keymint/aidl/default/hal/lib.rs
+++ b/security/keymint/aidl/default/hal/lib.rs
@@ -20,6 +20,19 @@
use kmr_hal::env::get_property;
use log::error;
+/// Retrieve the most significant attestation property for `name`.
+fn attestation_property(name: &str) -> Vec<u8> {
+ let prop_val = get_property(&format!("ro.product.vendor.{}", name)).unwrap_or_default();
+ if !prop_val.is_empty() {
+ prop_val
+ } else {
+ get_property(&format!("ro.product.{}", name))
+ .unwrap_or_else(|prop_name| format!("{} unavailable", prop_name))
+ }
+ .as_bytes()
+ .to_vec()
+}
+
/// Populate attestation ID information based on properties (where available).
/// Retrieving the serial number requires SELinux permission.
pub fn attestation_id_info() -> kmr_wire::AttestationIdInfo {
@@ -30,12 +43,12 @@
.to_vec()
};
kmr_wire::AttestationIdInfo {
- brand: prop("ro.product.brand"),
- device: prop("ro.product.device"),
- product: prop("ro.product.name"),
+ brand: attestation_property("brand"),
+ device: attestation_property("device"),
+ product: attestation_property("name"),
serial: prop("ro.serialno"),
- manufacturer: prop("ro.product.manufacturer"),
- model: prop("ro.product.model"),
+ manufacturer: attestation_property("manufacturer"),
+ model: attestation_property("model"),
// Currently modem_simulator always returns one fixed value. See `handleGetIMEI` in
// device/google/cuttlefish/host/commands/modem_simulator/misc_service.cpp for more details.
// TODO(b/263188546): Use device-specific IMEI values when available.
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index eaeec32..dcf8674 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <format>
#include <iomanip>
#include <iterator>
#include <memory>
@@ -535,7 +536,7 @@
switch (rpcHardwareInfo.versionNumber) {
case 3:
if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
- error += fmt::format(
+ error += std::format(
"Err: Incorrect number of device info entries. Expected {} but got "
"{}\n",
kNumTeeDeviceInfoEntries, parsed->size());
@@ -544,7 +545,7 @@
// may omit `os_version`
if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries &&
parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
- error += fmt::format(
+ error += std::format(
"Err: Incorrect number of device info entries. Expected {} or {} but got "
"{}\n",
kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
@@ -870,7 +871,7 @@
}
auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName));
+ true /*allowAnyMode*/, deviceSuffix(instanceName));
if (!csr.ok()) {
return csr.error().message();
}
@@ -904,7 +905,7 @@
}
auto csr1 = hwtrust::Csr::validate(encodedCsr1, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName1));
+ true /*allowAnyMode*/, deviceSuffix(instanceName1));
if (!csr1.ok()) {
return csr1.error().message();
}
@@ -921,7 +922,7 @@
}
auto csr2 = hwtrust::Csr::validate(encodedCsr2, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName2));
+ true /*allowAnyMode*/, deviceSuffix(instanceName2));
if (!csr2.ok()) {
return csr2.error().message();
}
@@ -952,7 +953,7 @@
}
auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(DEFAULT_INSTANCE_NAME));
+ true /*allowAnyMode*/, deviceSuffix(DEFAULT_INSTANCE_NAME));
if (!csr.ok()) {
return csr.error().message();
}
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 810cc38..66f7539 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -853,7 +853,7 @@
* is not "green" if and only if the mode on at least one certificate in the DICE chain
* is non-normal.
*/
-TEST_P(CertificateRequestV2Test, unlockedBootloaderStatesImpliesNonnormalDiceChain) {
+TEST_P(CertificateRequestV2Test, DISABLED_unlockedBootloaderStatesImpliesNonnormalDiceChain) {
auto challenge = randomBytes(MAX_CHALLENGE_SIZE);
bytevec csr;
auto status =
diff --git a/security/secretkeeper/aidl/vts/dice_sample.rs b/security/secretkeeper/aidl/vts/dice_sample.rs
index 4ef396a..d6379e5 100644
--- a/security/secretkeeper/aidl/vts/dice_sample.rs
+++ b/security/secretkeeper/aidl/vts/dice_sample.rs
@@ -283,7 +283,7 @@
SUBCOMPONENT_AUTHORITY_HASH => hex::decode("ed255ae9ea98826f3f3a966849f0aaaf356d140c766a869048016e0ba10141af039fec5c53658ddebdad9c2339587c5ef5487bde89237ca79802238d91aebba8").unwrap(),
},
{
- SUBCOMPONENT_NAME => "apex:com.android.btservices",
+ SUBCOMPONENT_NAME => "apex:com.android.bt",
SUBCOMPONENT_SECURITY_VERSION => 990090000,
SUBCOMPONENT_CODE_HASH => hex::decode("d7aa86dfdf92e662d2210cd2b3ad4e4522c917e9e287268363aa90e20f9ae16c").unwrap(),
SUBCOMPONENT_AUTHORITY_HASH => hex::decode("a0d577d4a56cfad09aaa7abcd2355cd78872df85672f2faf9ac2fdf15c06147394e704c7473f28bed737803581a3d097275cc26d8095a4a896ee76167f9ee40e").unwrap(),
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index b31a06c..99eb761 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -64,7 +64,7 @@
int keySizeBytes;
}
union DerivedKeyPolicy {
- android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKey;
+ android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKeyPolicy;
byte[] opaqueKey;
}
parcelable DerivedKeyParameters {
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 7c87dd3..3adb2f9 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -34,5 +34,5 @@
package android.hardware.security.see.hwcrypto;
@VintfStability
interface IHwCryptoOperations {
- android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+ android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations);
}
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index 97a4c37..93d6cbc 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -107,10 +107,12 @@
* If used we will derive a clear key and pass it back as an array of bytes on
* <code>HwCryptoKeyMaterial::explicitKey</code>.
*/
- ClearKeyPolicy clearKey;
+ ClearKeyPolicy clearKeyPolicy;
/*
* Policy for the newly derived opaque key. Defines how the key can be used and its type.
+ * Its definition can be found in <code>KeyPolicy.cddl</code>, which is basically a CBOR
+ * serialization of the file <code>KeyPolicy.aidl</code>.
*/
byte[] opaqueKey;
}
@@ -154,11 +156,14 @@
* Key to be used to derive the new key using HKDF.
*
* @return:
- * A DiceCurrentBoundKeyResult containint the versioned key tied the current client version
+ * A DiceCurrentBoundKeyResult containing the versioned key tied the current client version
* on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid DeviceKeyId is requested.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(
in DiceBoundDerivationKey derivationKey);
@@ -184,7 +189,11 @@
* success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid DeviceKeyId is requested or if dicePolicyForKeyVersion
+ * is not a valid encrypted DICE policy.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DiceBoundKeyResult deriveDicePolicyBoundKey(
in DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
@@ -197,10 +206,15 @@
* file for more information.
*
* @return:
- * A HwCryptoKeyMaterial containing the derived key on success.
+ * A <code>DerivedKey</code> containing the derived key on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid key policy is provided or if the key policy conflicts
+ * with the requested key.
+ * - SERIALIZATION_ERROR if the provided key policy is not a valid CBOR key policy.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DerivedKey deriveKey(in DerivedKeyParameters parameters);
@@ -233,7 +247,11 @@
* IOpaqueKey on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid Key policy is provided or if the key policy conflicts
+ * with provided key material.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
*/
IOpaqueKey importClearKey(in ExplicitKeyMaterial keyMaterial, in KeyPolicy newKeyPolicy);
@@ -248,7 +266,9 @@
* passing the receiver DICE policy to insure that only that receiver can import the key.
*
* @return:
- * byte[] on success, which is the caller encrypted DICE policy.
+ * byte[] on success, which is the caller encrypted DICE policy. The DICE policy follows
+ * the structure defined on DicePolicy.cddl, located under
+ * hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
*/
byte[] getCurrentDicePolicy();
@@ -266,10 +286,14 @@
* DICE policy used to seal the exported key.
*
* @return:
- * An IOpaqueKey that can be directly be used on the local HWCrypto service on success.
+ * An IOpaqueKey that can be directly used on the local HWCrypto service on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid encrypted sealing DICE policy is provided.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
+ * - UNAUTHORIZED if the sealingDicePolicy do not match the caller.
*/
IOpaqueKey keyTokenImport(in OpaqueKeyToken requestedKey, in byte[] sealingDicePolicy);
@@ -287,8 +311,9 @@
* An IOpaqueKey corresponding to the requested key slot on success.
*
* @throws:
- * ServiceSpecificException <code>UNAUTHORIZED</code> if the caller cannot access the
- * requested key, another specific error based on <code>HalErrorCode</code> otherwise.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - UNAUTHORIZED if the caller cannot access the requested key.
*/
IOpaqueKey getKeyslotData(KeySlot slotId);
}
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 9df6d67..dbe4d80 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -31,19 +31,21 @@
*
* @param operations:
* Parameter containing 1 or more set of commands to execute. Additionally, each set can
- * also contain a context on which the commands will be executed.
- *
- * @param additionalErrorInfo:
- * Structure containing additional info when errors are encountered. Only valid if the
- * function failed its execution.
+ * also contain a context on which the commands will be executed. The parameter has type
+ * inout because it can contain buffers used to write the output of the operation.
*
* @return:
* CryptoOperationResult[] on success, which can contain a context to continue executing
* each of the provided operations sets.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - INVALID_KEY if the provided key is not compatible with the operation requested.
+ * - BAD_STATE if the provided <code>CryptoOperationSet</code> contains operations that
+ * cannot be carried out in the current server state.
+ * - UNSUPPORTED if the requested operation is not supported by the server.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
*/
- CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations,
- out CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+ CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations);
}
diff --git a/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
index 9a8d0d7..b5762aa 100644
--- a/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
@@ -103,7 +103,8 @@
/**
* Renames an existing file.
*
- * The file must not already be opened. (If it is, use `IFile::rename`.)
+ * Will return `ILLEGAL_STATE` if the file is already opened. In that case, use `IFile::rename`
+ * instead.
*
* @currentPath:
* path to the file, relative to filesystem root
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 158e4f1..59d9593 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -214,9 +214,7 @@
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
- if (!isPassthroughFilter(filterConf)) {
- ASSERT_TRUE(filterDataOutputTest());
- }
+ ASSERT_TRUE(filterDataOutputTest());
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.releaseShareAvHandle(filterId));
@@ -1383,6 +1381,10 @@
auto live_configs = generateLiveConfigurations();
for (auto& configuration : live_configs) {
live = configuration;
+ // shared memory handle is not used by a passthrough filter at all
+ if (isPassthroughFilter(filterMap[live.videoFilterId])) {
+ continue;
+ }
mediaFilterUsingSharedMemoryTest(filterMap[live.videoFilterId],
frontendMap[live.frontendId]);
}
diff --git a/virtualization/OWNERS b/virtualization/OWNERS
new file mode 100644
index 0000000..316145b
--- /dev/null
+++ b/virtualization/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/Virtualization:/OWNERS
diff --git a/virtualization/capabilities_service/README.md b/virtualization/capabilities_service/README.md
new file mode 100644
index 0000000..7dc141e
--- /dev/null
+++ b/virtualization/capabilities_service/README.md
@@ -0,0 +1,9 @@
+The IVmCapabilitiesService HAL is used in a flow to grant a pVM a capability to
+issue vendor-specific SMCs. For more information see: TODO(ioffe): link the docs
+
+Here is a brief overview of the subdirectories structure:
+
+* default/ - a reference implementation of the HAL that partners can integrate
+ in their products.
+* noop/ - a no-op implementation is used in cuttlefish for mixed build testing.
+* vts/ - VTS tests for this HAL.
diff --git a/virtualization/capabilities_service/noop/Android.bp b/virtualization/capabilities_service/noop/Android.bp
new file mode 100644
index 0000000..37dc1a7
--- /dev/null
+++ b/virtualization/capabilities_service/noop/Android.bp
@@ -0,0 +1,34 @@
+package {
+ default_team: "trendy_team_virtualization",
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary {
+ name: "android.hardware.virtualization.capabilities.capabilities_service-noop",
+ relative_install_path: "hw",
+ vendor: true,
+ installable: true,
+ prefer_rlib: true,
+ rustlibs: [
+ "android.hardware.virtualization.capabilities.capabilities_service-V1-rust",
+ "libanyhow",
+ "libandroid_logger",
+ "libbinder_rs",
+ "liblog_rust",
+ ],
+ srcs: [
+ "src/main.rs",
+ ],
+ init_rc: [
+ "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc",
+ ],
+ vintf_fragment_modules: [
+ "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+ ],
+}
+
+vintf_fragment {
+ name: "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+ src: "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+ vendor: true,
+}
diff --git a/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc
new file mode 100644
index 0000000..58c554a
--- /dev/null
+++ b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc
@@ -0,0 +1,6 @@
+service vendor.vm_capabilities_service /vendor/bin/hw/android.hardware.virtualization.capabilities.capabilities_service-noop
+ interface aidl android.hardware.virtualization.capabilities.IVmCapabilitiesService/noop
+ class hal
+ disabled
+ user nobody
+ group nobody
diff --git a/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml
new file mode 100644
index 0000000..8ecb9e5
--- /dev/null
+++ b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.virtualization.capabilities</name>
+ <version>1</version>
+ <interface>
+ <name>IVmCapabilitiesService</name>
+ <instance>noop</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/virtualization/capabilities_service/noop/src/aidl.rs b/virtualization/capabilities_service/noop/src/aidl.rs
new file mode 100644
index 0000000..8d85e49
--- /dev/null
+++ b/virtualization/capabilities_service/noop/src/aidl.rs
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+//! No-op implementation of the IVmCapabilitiesService AIDL interface.
+
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::IVmCapabilitiesService;
+use binder::{Interface, ParcelFileDescriptor};
+use log::info;
+
+/// No-op implementation of IVmCapabilitiesService
+pub struct NoOpVmCapabilitiesService {}
+
+impl NoOpVmCapabilitiesService {
+ pub fn init() -> NoOpVmCapabilitiesService {
+ let service = NoOpVmCapabilitiesService {};
+ service
+ }
+}
+
+impl Interface for NoOpVmCapabilitiesService {}
+
+impl IVmCapabilitiesService for NoOpVmCapabilitiesService {
+
+ fn grantAccessToVendorTeeServices(&self,
+ vm_fd: &ParcelFileDescriptor, tee_services: &[String]) -> binder::Result<()> {
+ info!("received {vm_fd:?} {tee_services:?}");
+ Ok(())
+ }
+}
diff --git a/virtualization/capabilities_service/noop/src/main.rs b/virtualization/capabilities_service/noop/src/main.rs
new file mode 100644
index 0000000..9440996
--- /dev/null
+++ b/virtualization/capabilities_service/noop/src/main.rs
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+//! No-op implementation of the IVmCapabilitiesService.
+
+mod aidl;
+
+use crate::aidl::NoOpVmCapabilitiesService;
+use anyhow::{bail, Context, Result};
+use log::{error, info, LevelFilter};
+use binder::{register_lazy_service, BinderFeatures, ProcessState};
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::BnVmCapabilitiesService;
+
+const SERVICE_NAME: &str = "android.hardware.virtualization.capabilities.IVmCapabilitiesService/noop";
+
+fn try_main() -> Result<()> {
+ // Initialize Android logging.
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("NoOpIVmCapabilitiesService")
+ .with_max_level(LevelFilter::Info)
+ .with_log_buffer(android_logger::LogId::System),
+ );
+
+ ProcessState::start_thread_pool();
+ let service_impl = NoOpVmCapabilitiesService::init();
+ let service = BnVmCapabilitiesService::new_binder(service_impl, BinderFeatures::default());
+ register_lazy_service(SERVICE_NAME, service.as_binder())
+ .with_context(|| format!("failed to register {SERVICE_NAME}"))?;
+ info!("Registered Binder service, joining threadpool.");
+ ProcessState::join_thread_pool();
+ bail!("thread pool unexpectedly ended");
+}
+
+fn main() {
+ if let Err(e) = try_main() {
+ error!("failed with {e:?}");
+ std::process::exit(1);
+ }
+}
diff --git a/virtualization/capabilities_service/vts/Android.bp b/virtualization/capabilities_service/vts/Android.bp
new file mode 100644
index 0000000..1aa21c9
--- /dev/null
+++ b/virtualization/capabilities_service/vts/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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_virtualization",
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_test {
+ name: "VtsVmCapabilitiesServiceTest",
+ srcs: ["tests.rs"],
+ defaults: [
+ "rdroidtest.defaults",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ test_config: "AndroidTest.xml",
+ rustlibs: [
+ "android.hardware.virtualization.capabilities.capabilities_service-V1-rust",
+ "libbinder_rs",
+ ],
+ require_root: true,
+}
diff --git a/virtualization/capabilities_service/vts/AndroidTest.xml b/virtualization/capabilities_service/vts/AndroidTest.xml
new file mode 100644
index 0000000..2c3dadb
--- /dev/null
+++ b/virtualization/capabilities_service/vts/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?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="Config for VmCapabilitiesService VTS tests.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="VtsVmCapabilitiesServiceTest"
+ value="/data/local/tmp/VtsVmCapabilitiesServiceTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+ <option name="test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsVmCapabilitiesServiceTest" />
+ </test>
+</configuration>
diff --git a/virtualization/capabilities_service/vts/tests.rs b/virtualization/capabilities_service/vts/tests.rs
new file mode 100644
index 0000000..9f0b7fd
--- /dev/null
+++ b/virtualization/capabilities_service/vts/tests.rs
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::IVmCapabilitiesService;
+use rdroidtest::rdroidtest;
+use std::fs::File;
+
+const VM_CAPABILITIES_SERVICE: &str =
+ "android.hardware.virtualization.capabilities.IVmCapabilitiesService";
+
+/// Returns all available instances of VmCapabilitiesService.
+/// Note: it actually returns a pair of (<instance_name>, <instance_name)). This is a requirement
+/// of the rdroidtest framework for parameterized tests. See
+/// platform_testing/libraries/rdroidtest/README.md for more information.
+fn get_instances() -> Vec<(String, String)> {
+ binder::get_declared_instances(VM_CAPABILITIES_SERVICE)
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| (v.clone(), v))
+ .collect()
+}
+
+fn connect(instance: &str) -> binder::Strong<dyn IVmCapabilitiesService> {
+ let name = format!("{VM_CAPABILITIES_SERVICE}/{instance}");
+ binder::wait_for_interface(&name).unwrap()
+}
+
+/// A very basic test that simply connects to the service and send bogus data.
+#[rdroidtest(get_instances())]
+fn connect_to_service(instance: String) {
+ let service = connect(&instance);
+ let dev_null = File::open("/dev/null").expect("failed to open /dev/null");
+ let fd = binder::ParcelFileDescriptor::new(dev_null);
+ // In this test we don't care what service returns.
+ let _ = service.grantAccessToVendorTeeServices(&fd, &[]);
+}
+
+rdroidtest::test_main!();