Merge "Enable the rust backend for android.hardware.bluetooth.socket" 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/Visualizer.aidl b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
index 0b37546..fe8fe97 100644
--- a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
@@ -20,10 +20,12 @@
/**
* Visualizer specific definitions. Visualizer enables application to retrieve part of the currently
- * playing audio for visualization purpose
+ * playing audio for visualization purpose. The output is identical to the input, while
+ * visualization data is generated separately based on scalingMode and captureSamples parameter
+ * values.
*
* All parameter settings must be inside the range of Capability.Range.visualizer definition if the
- * definition for the corresponding parameter tag exist. See more detals about Range in Range.aidl.
+ * definition for the corresponding parameter tag exist. See more details about Range in Range.aidl.
*
*/
@VintfStability
@@ -50,14 +52,24 @@
enum ScalingMode {
/**
* Defines a capture mode where amplification is applied based on the content of the
- * captured data. This is the default Visualizer mode, and is suitable for music
- * visualization.
+ * captured data in order to normalize it to the unsigned 8 bit sample range. This is the
+ * default Visualizer mode, and is suitable for music visualization.
+ *
+ * For example,
+ * Input Range:[-0.5, 0.5] -> Visualization Data Range:[0, 255]
+ * Input Range:[-1,1] -> Visualization Data Range:[0, 255]
+ *
*/
NORMALIZED = 0,
/**
- * Defines a capture mode where the playback volume will affect (scale) the range of the
- * captured data. A low playback volume will lead to low sample and fft values, and
- * vice-versa.
+ * Defines a capture mode where no additional scaling is done on the input audio data thus
+ * the visualization data remains as close as possible to the input. The visualization
+ * directly reflects the actual loudness and waveform shape, rather than fitting everything
+ * into a normalized visual range.
+ *
+ * For example,
+ * Input Range:[-0.5, 0.5] -> Visualization Data Range:[64, 192]
+ * Input Range:[-1,1] -> Visualization Data Range:[0, 255]
*/
AS_PLAYED,
}
@@ -93,7 +105,10 @@
Measurement measurement;
/**
- * Get only parameter to get the latest captured samples of PCM samples (8 bits per sample).
+ * Get only parameter to get the latest captured samples of PCM samples (8 bits per sample). It
+ * represents the visualization data. The capture is intended for passing to applications, and
+ * it contains the same audio data as the input, but with intentionally lower sample resolution,
+ * and optionally normalized, depending on the scalingMode.
*/
byte[] captureSampleBuffer;
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/common/tests/utils_tests.cpp b/audio/aidl/common/tests/utils_tests.cpp
index 1b8b8df..1522d7e 100644
--- a/audio/aidl/common/tests/utils_tests.cpp
+++ b/audio/aidl/common/tests/utils_tests.cpp
@@ -86,7 +86,7 @@
std::make_pair(6UL, AudioChannelLayout::LAYOUT_5POINT1),
std::make_pair(8UL, AudioChannelLayout::LAYOUT_7POINT1),
std::make_pair(16UL, AudioChannelLayout::LAYOUT_9POINT1POINT6),
- std::make_pair(13UL, AudioChannelLayout::LAYOUT_13POINT_360RA),
+ std::make_pair(13UL, AudioChannelLayout::LAYOUT_13POINT0),
std::make_pair(24UL, AudioChannelLayout::LAYOUT_22POINT2),
std::make_pair(3UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_A),
std::make_pair(4UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_AB)};
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/Module.cpp b/audio/aidl/default/Module.cpp
index e96cf81..f9fa799 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -184,8 +184,12 @@
const int32_t nominalLatencyMs = getNominalLatencyMs(*portConfigIt);
// Since this is a private method, it is assumed that
// validity of the portConfigId has already been checked.
- const int32_t minimumStreamBufferSizeFrames =
- calculateBufferSizeFrames(nominalLatencyMs, portConfigIt->sampleRate.value().value);
+ int32_t minimumStreamBufferSizeFrames = 0;
+ if (!calculateBufferSizeFrames(
+ portConfigIt->format.value(), nominalLatencyMs,
+ portConfigIt->sampleRate.value().value, &minimumStreamBufferSizeFrames).isOk()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
if (in_bufferSizeFrames < minimumStreamBufferSizeFrames) {
LOG(ERROR) << __func__ << ": " << mType << ": insufficient buffer size "
<< in_bufferSizeFrames << ", must be at least " << minimumStreamBufferSizeFrames;
@@ -378,6 +382,18 @@
return kLatencyMs;
}
+ndk::ScopedAStatus Module::calculateBufferSizeFrames(
+ const ::aidl::android::media::audio::common::AudioFormatDescription &format,
+ int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames) {
+ if (format.type == AudioFormatType::PCM) {
+ *bufferSizeFrames = calculateBufferSizeFramesForPcm(latencyMs, sampleRateHz);
+ return ndk::ScopedAStatus::ok();
+ }
+ LOG(ERROR) << __func__ << ": " << mType << ": format " << format.toString()
+ << " is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
ndk::ScopedAStatus Module::createMmapBuffer(
const ::aidl::android::hardware::audio::core::StreamContext& context __unused,
::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) {
@@ -1123,8 +1139,14 @@
*_aidl_return = in_requested;
auto maxSampleRateIt = std::max_element(sampleRates.begin(), sampleRates.end());
const int32_t latencyMs = getNominalLatencyMs(*(maxSampleRateIt->second));
- _aidl_return->minimumStreamBufferSizeFrames =
- calculateBufferSizeFrames(latencyMs, maxSampleRateIt->first);
+ if (!calculateBufferSizeFrames(
+ maxSampleRateIt->second->format.value(), latencyMs, maxSampleRateIt->first,
+ &_aidl_return->minimumStreamBufferSizeFrames).isOk()) {
+ if (patchesBackup.has_value()) {
+ mPatches = std::move(*patchesBackup);
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
_aidl_return->latenciesMs.clear();
_aidl_return->latenciesMs.insert(_aidl_return->latenciesMs.end(),
_aidl_return->sinkPortConfigIds.size(), latencyMs);
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index e57c108..3814fe6 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -50,7 +50,7 @@
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_NONE;
- enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT_360RA;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT0;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_22POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index 108a6a3..cfe0a6e 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -463,7 +463,7 @@
<xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT4"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT6"/>
- <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT_360RA"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT0"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_22POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_A"/>
<xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
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/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index d03598a..cbc13d1 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -207,12 +207,15 @@
virtual std::unique_ptr<Configuration> initializeConfig();
virtual int32_t getNominalLatencyMs(
const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+ virtual ndk::ScopedAStatus calculateBufferSizeFrames(
+ const ::aidl::android::media::audio::common::AudioFormatDescription &format,
+ int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames);
virtual ndk::ScopedAStatus createMmapBuffer(
const ::aidl::android::hardware::audio::core::StreamContext& context,
::aidl::android::hardware::audio::core::StreamDescriptor* desc);
// Utility and helper functions accessible to subclasses.
- static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
+ static int32_t calculateBufferSizeFramesForPcm(int32_t latencyMs, int32_t sampleRateHz) {
const int32_t rawSizeFrames =
aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
sampleRateHz);
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 eedac3d..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;
@@ -84,7 +85,9 @@
}
static constexpr float kMaxAudioSampleValue = 1;
+static constexpr int kNPointFFT = 16384;
static constexpr int kSamplingFrequency = 44100;
+static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
class EffectHelper {
public:
@@ -195,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));
@@ -255,13 +261,14 @@
EXPECT_TRUE(efState & kEventFlagDataMqUpdate);
}
- Parameter::Common createParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000,
- int oSampleRate = 48000, long iFrameCount = 0x100,
- long oFrameCount = 0x100) {
- AudioChannelLayout inputLayout = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO);
- AudioChannelLayout outputLayout = inputLayout;
-
+ Parameter::Common createParamCommon(
+ int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
+ long iFrameCount = 0x100, long oFrameCount = 0x100,
+ AudioChannelLayout inputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout),
+ AudioChannelLayout outputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ kDefaultChannelLayout)) {
// query supported input layout and use it as the default parameter in common
if (mIsSpatializer && isRangeValid<Range::spatializer>(Spatializer::supportedChannelLayout,
mDescriptor.capability)) {
@@ -271,18 +278,10 @@
layoutRange &&
0 != (layouts = layoutRange->min.get<Spatializer::supportedChannelLayout>())
.size()) {
- inputLayout = layouts[0];
+ inputChannelLayout = layouts[0];
}
}
- return createParamCommon(session, ioHandle, iSampleRate, oSampleRate, iFrameCount,
- oFrameCount, inputLayout, outputLayout);
- }
-
- static Parameter::Common createParamCommon(int session, int ioHandle, int iSampleRate,
- int oSampleRate, long iFrameCount, long oFrameCount,
- AudioChannelLayout inputChannelLayout,
- AudioChannelLayout outputChannelLayout) {
Parameter::Common common;
common.session = session;
common.ioHandle = ioHandle;
@@ -459,43 +458,120 @@
// Generate multitone input between -amplitude to +amplitude using testFrequencies
// All test frequencies are considered having the same amplitude
+ // The function supports only mono and stereo channel layout
void generateSineWave(const std::vector<int>& testFrequencies, std::vector<float>& input,
const float amplitude = 1.0,
- const int samplingFrequency = kSamplingFrequency) {
- for (size_t i = 0; i < input.size(); i++) {
+ const int samplingFrequency = kSamplingFrequency,
+ int channelLayout = AudioChannelLayout::LAYOUT_STEREO) {
+ bool isStereo = (channelLayout == AudioChannelLayout::LAYOUT_STEREO);
+ if (isStereo) {
+ ASSERT_EQ(input.size() % 2, 0u)
+ << "In case of stereo input, the input size value must be even";
+ }
+ for (size_t i = 0; i < input.size(); i += (isStereo ? 2 : 1)) {
input[i] = 0;
for (size_t j = 0; j < testFrequencies.size(); j++) {
- input[i] += sin(2 * M_PI * testFrequencies[j] * i / samplingFrequency);
+ input[i] += sin(2 * M_PI * testFrequencies[j] * (i / (isStereo ? 2 : 1)) /
+ samplingFrequency);
}
input[i] *= amplitude / testFrequencies.size();
+
+ if (isStereo) {
+ input[i + 1] = input[i];
+ }
}
}
// Generate single tone input between -amplitude to +amplitude using testFrequency
+ // The function supports only mono and stereo channel layout
void generateSineWave(const int testFrequency, std::vector<float>& input,
const float amplitude = 1.0,
- const int samplingFrequency = kSamplingFrequency) {
- generateSineWave(std::vector<int>{testFrequency}, input, amplitude, samplingFrequency);
+ const int samplingFrequency = kSamplingFrequency,
+ int channelLayout = AudioChannelLayout::LAYOUT_STEREO) {
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(std::vector<int>{testFrequency}, input, amplitude,
+ samplingFrequency, channelLayout));
+ }
+
+ // PFFFT only supports transforms for inputs of length N of the form N = (2^a)*(3^b)*(5^c) where
+ // a >= 5, b >=0, c >= 0.
+ constexpr bool isFftInputSizeValid(size_t n) {
+ if (n == 0 || n & 0b11111) {
+ return false;
+ }
+ for (const int factor : {2, 3, 5}) {
+ while (n % factor == 0) {
+ n /= factor;
+ }
+ }
+ return n == 1;
}
// Use FFT transform to convert the buffer to frequency domain
// Compute its magnitude at binOffsets
- std::vector<float> calculateMagnitude(const std::vector<float>& buffer,
- const std::vector<int>& binOffsets, const int nPointFFT) {
+ void calculateMagnitudeMono(std::vector<float>& bufferMag, // Output parameter
+ const std::vector<float>& buffer, // Input parameter
+ const std::vector<int>& binOffsets, // Input parameter
+ const int nPointFFT = kNPointFFT) { // Input parameter
+ ASSERT_TRUE(isFftInputSizeValid(nPointFFT))
+ << "PFFFT only supports transforms for inputs of length N of the form N = (2 ^ a) "
+ "* (3 ^ b) * (5 ^ c) where a >= 5, b >= 0, c >= 0. ";
+ ASSERT_GE((int)buffer.size(), nPointFFT)
+ << "The input(buffer) size must be greater than or equal to nPointFFT";
+ bufferMag.resize(binOffsets.size());
std::vector<float> fftInput(nPointFFT);
PFFFT_Setup* inputHandle = pffft_new_setup(nPointFFT, PFFFT_REAL);
pffft_transform_ordered(inputHandle, buffer.data(), fftInput.data(), nullptr,
PFFFT_FORWARD);
pffft_destroy_setup(inputHandle);
- std::vector<float> bufferMag(binOffsets.size());
for (size_t i = 0; i < binOffsets.size(); i++) {
size_t k = binOffsets[i];
bufferMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
(fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
}
+ }
- return bufferMag;
+ // Use FFT transform to convert the buffer to frequency domain
+ // Compute its magnitude at binOffsets
+ void calculateMagnitudeStereo(
+ std::pair<std::vector<float>, std::vector<float>>& bufferMag, // Output parameter
+ const std::vector<float>& buffer, // Input parameter
+ const std::vector<int>& binOffsets, // Input parameter
+ const int nPointFFT = kNPointFFT) { // Input parameter
+ std::vector<float> leftChannelBuffer(buffer.size() / 2),
+ rightChannelBuffer(buffer.size() / 2);
+ for (size_t i = 0; i < buffer.size(); i += 2) {
+ leftChannelBuffer[i / 2] = buffer[i];
+ rightChannelBuffer[i / 2] = buffer[i + 1];
+ }
+ std::vector<float> leftMagnitude(binOffsets.size());
+ std::vector<float> rightMagnitude(binOffsets.size());
+
+ ASSERT_NO_FATAL_FAILURE(
+ calculateMagnitudeMono(leftMagnitude, leftChannelBuffer, binOffsets, nPointFFT));
+ ASSERT_NO_FATAL_FAILURE(
+ calculateMagnitudeMono(rightMagnitude, rightChannelBuffer, binOffsets, nPointFFT));
+
+ bufferMag = {leftMagnitude, rightMagnitude};
+ }
+
+ // Computes magnitude for mono and stereo inputs and verifies equal magnitude for left and right
+ // channel in case of stereo inputs
+ void calculateAndVerifyMagnitude(std::vector<float>& mag, // Output parameter
+ const int channelLayout, // Input parameter
+ const std::vector<float>& buffer, // Input parameter
+ const std::vector<int>& binOffsets, // Input parameter
+ const int nPointFFT = kNPointFFT) { // Input parameter
+ if (channelLayout == AudioChannelLayout::LAYOUT_STEREO) {
+ std::pair<std::vector<float>, std::vector<float>> magStereo;
+ ASSERT_NO_FATAL_FAILURE(
+ calculateMagnitudeStereo(magStereo, buffer, binOffsets, nPointFFT));
+ ASSERT_EQ(magStereo.first, magStereo.second);
+
+ mag = magStereo.first;
+ } else {
+ ASSERT_NO_FATAL_FAILURE(calculateMagnitudeMono(mag, buffer, binOffsets, nPointFFT));
+ }
}
void updateFrameSize(const Parameter::Common& common) {
@@ -518,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/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 5a24be7..c3c1e9e 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -48,7 +48,7 @@
class BassBoostEffectHelper : public EffectHelper {
public:
- void SetUpBassBoost(int32_t layout = AudioChannelLayout::LAYOUT_STEREO) {
+ void SetUpBassBoost(int32_t layout = kDefaultChannelLayout) {
ASSERT_NE(nullptr, mFactory);
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
setFrameCounts(layout);
@@ -113,7 +113,7 @@
}
}
- static constexpr int kDurationMilliSec = 720;
+ static constexpr int kDurationMilliSec = 1440;
static constexpr int kInputSize = kSamplingFrequency * kDurationMilliSec / 1000;
long mInputFrameCount, mOutputFrameCount;
std::shared_ptr<IFactory> mFactory;
@@ -187,25 +187,6 @@
}
}
- // Use FFT transform to convert the buffer to frequency domain
- // Compute its magnitude at binOffsets
- std::vector<float> calculateMagnitude(const std::vector<float>& buffer,
- const std::vector<int>& binOffsets) {
- std::vector<float> fftInput(kNPointFFT);
- PFFFT_Setup* inputHandle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
- pffft_transform_ordered(inputHandle, buffer.data(), fftInput.data(), nullptr,
- PFFFT_FORWARD);
- pffft_destroy_setup(inputHandle);
- std::vector<float> bufferMag(binOffsets.size());
- for (size_t i = 0; i < binOffsets.size(); i++) {
- size_t k = binOffsets[i];
- bufferMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
- (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
- }
-
- return bufferMag;
- }
-
// Calculate gain difference between low frequency and high frequency magnitude
float calculateGainDiff(const std::vector<float>& inputMag,
const std::vector<float>& outputMag) {
@@ -218,7 +199,6 @@
return gains[0] - gains[1];
}
- static constexpr int kNPointFFT = 16384;
static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
std::set<int> mStrengthValues;
int32_t mChannelLayout;
@@ -240,9 +220,11 @@
roundToFreqCenteredToFftBin(testFrequencies, binOffsets);
// Generate multitone input
- generateSineWave(testFrequencies, input);
+ ASSERT_NO_FATAL_FAILURE(
+ generateSineWave(testFrequencies, input, 1.0, kSamplingFrequency, mChannelLayout));
- inputMag = calculateMagnitude(input, binOffsets);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(inputMag, mChannelLayout, input, binOffsets));
if (isStrengthValid(0)) {
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(0, EX_NONE));
@@ -254,7 +236,10 @@
processAndWriteToOutput(input, baseOutput, mEffect, &mOpenEffectReturn));
std::vector<float> baseMag(testFrequencies.size());
- baseMag = calculateMagnitude(baseOutput, binOffsets);
+
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(baseMag, mChannelLayout, baseOutput, binOffsets));
+
float baseDiff = calculateGainDiff(inputMag, baseMag);
for (int strength : mStrengthValues) {
@@ -271,7 +256,9 @@
ASSERT_NO_FATAL_FAILURE(
processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn));
- outputMag = calculateMagnitude(output, binOffsets);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, binOffsets));
+
float diff = calculateGainDiff(inputMag, outputMag);
ASSERT_GT(diff, prevGain);
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index bf22839..5c5be3a 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -52,7 +52,7 @@
AudioChannelLayout::LAYOUT_5POINT1POINT4, AudioChannelLayout::LAYOUT_6POINT1,
AudioChannelLayout::LAYOUT_7POINT1, AudioChannelLayout::LAYOUT_7POINT1POINT2,
AudioChannelLayout::LAYOUT_7POINT1POINT4, AudioChannelLayout::LAYOUT_9POINT1POINT4,
- AudioChannelLayout::LAYOUT_9POINT1POINT6, AudioChannelLayout::LAYOUT_13POINT_360RA,
+ AudioChannelLayout::LAYOUT_9POINT1POINT6, AudioChannelLayout::LAYOUT_13POINT0,
AudioChannelLayout::LAYOUT_22POINT2};
static const std::vector<int32_t> kChannels = {
@@ -86,7 +86,7 @@
class DownmixEffectHelper : public EffectHelper {
public:
- void SetUpDownmix(int32_t inputBufferLayout = AudioChannelLayout::LAYOUT_STEREO) {
+ void SetUpDownmix(int32_t inputBufferLayout = kDefaultChannelLayout) {
ASSERT_NE(nullptr, mFactory);
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 3b1f3d9..09b6621 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -46,8 +46,8 @@
class DynamicsProcessingTestHelper : public EffectHelper {
public:
DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair,
- int32_t channelLayOut = AudioChannelLayout::LAYOUT_STEREO)
- : mChannelLayout(channelLayOut),
+ int32_t channelLayout = kDefaultChannelLayout)
+ : mChannelLayout(channelLayout),
mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout))) {
std::tie(mFactory, mDescriptor) = pair;
@@ -162,11 +162,12 @@
static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
private:
- const int32_t mChannelLayout;
std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
protected:
+ const int32_t mChannelLayout;
const int mChannelCount;
+
void CleanUp() {
mTags.clear();
mPreEqChannelEnable.clear();
@@ -397,6 +398,8 @@
return true;
}
+// This function calculates power for both and mono and stereo data as the total power for
+// interleaved multichannel data can be calculated by treating it as a continuous mono input.
float DynamicsProcessingTestHelper::calculateDb(const std::vector<float>& input,
size_t startSamplePos = 0) {
return audio_utils_compute_power_mono(input.data() + startSamplePos, AUDIO_FORMAT_PCM_FLOAT,
@@ -542,7 +545,7 @@
};
TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
- EXPECT_NO_FATAL_FAILURE(addEngineConfig(mCfg));
+ addEngineConfig(mCfg);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -594,7 +597,7 @@
};
TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
- EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
+ addInputGain(mInputGain);
ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
}
@@ -623,13 +626,14 @@
DynamicsProcessingInputGainDataTest()
: DynamicsProcessingTestHelper((GetParam()), AudioChannelLayout::LAYOUT_MONO) {
mInput.resize(kFrameCount * mChannelCount);
- generateSineWave(kInputFrequency /*Input Frequency*/, mInput);
- mInputDb = calculateDb(mInput);
}
void SetUp() override {
SetUpDynamicsProcessingEffect();
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency /*Input Frequency*/, mInput, 1.0,
+ kSamplingFrequency, mChannelLayout));
+ mInputDb = calculateDb(mInput);
}
void TearDown() override { TearDownDynamicsProcessingEffect(); }
@@ -652,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;
@@ -719,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());
}
@@ -758,13 +762,14 @@
: DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
mBufferSize = kFrameCount * mChannelCount;
mInput.resize(mBufferSize);
- generateSineWave(1000 /*Input Frequency*/, mInput);
- mInputDb = calculateDb(mInput);
}
void SetUp() override {
SetUpDynamicsProcessingEffect();
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, mInput, 1.0,
+ kSamplingFrequency, mChannelLayout));
+ mInputDb = calculateDb(mInput);
}
void TearDown() override { TearDownDynamicsProcessingEffect(); }
@@ -782,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));
}
@@ -937,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());
}
@@ -1018,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());
}
@@ -1185,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/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index a29920e..0222923 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -43,13 +43,13 @@
static const std::vector<TagVectorPair> kParamsIncreasingVector = {
{EnvironmentalReverb::roomLevelMb, {-3500, -2800, -2100, -1400, -700, 0}},
{EnvironmentalReverb::roomHfLevelMb, {-4000, -3200, -2400, -1600, -800, 0}},
- {EnvironmentalReverb::decayTimeMs, {800, 1600, 2400, 3200, 4000}},
- {EnvironmentalReverb::decayHfRatioPm, {100, 600, 1100, 1600, 2000}},
+ {EnvironmentalReverb::decayTimeMs, {400, 800, 1200, 1600, 2000}},
+ {EnvironmentalReverb::decayHfRatioPm, {1000, 900, 800, 700}},
{EnvironmentalReverb::levelMb, {-3500, -2800, -2100, -1400, -700, 0}},
};
static const TagVectorPair kDiffusionParam = {EnvironmentalReverb::diffusionPm,
- {200, 400, 600, 800, 1000}};
+ {100, 300, 500, 700, 900}};
static const TagVectorPair kDensityParam = {EnvironmentalReverb::densityPm,
{0, 200, 400, 600, 800, 1000}};
@@ -139,6 +139,7 @@
return valueTag;
}
+
/**
* Tests do the following:
* - Testing parameter range supported by the effect. Range is verified with IEffect.getDescriptor()
@@ -281,11 +282,11 @@
static constexpr int kDurationMilliSec = 500;
static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
- static constexpr int kInputFrequency = 1000;
+ static constexpr int kInputFrequency = 2000;
+ static constexpr int mChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
- int mStereoChannelCount =
- getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO));
+ int mStereoChannelCount = getChannelCount(
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
int mFrameCount = kBufferSize / mStereoChannelCount;
std::shared_ptr<IFactory> mFactory;
@@ -344,10 +345,11 @@
: EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
mInput.resize(kBufferSize);
- generateSineWave(kInputFrequency, mInput);
}
void SetUp() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(
+ generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
SetUpReverb();
}
void TearDown() override {
@@ -434,7 +436,8 @@
TEST_P(EnvironmentalReverbMinimumParamTest, MinimumValueTest) {
std::vector<float> input(kBufferSize);
- generateSineWave(kInputFrequency, input);
+ ASSERT_NO_FATAL_FAILURE(
+ generateSineWave(kInputFrequency, input, 1.0, kSamplingFrequency, mChannelLayout));
std::vector<float> output(kBufferSize);
setParameterAndProcess(input, output, mValue, mTag);
float energy = computeOutputEnergy(input, output);
@@ -470,10 +473,11 @@
: EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
mInput.resize(kBufferSize);
- generateSineWave(kInputFrequency, mInput);
}
void SetUp() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(
+ generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
SetUpReverb();
}
void TearDown() override {
@@ -546,14 +550,15 @@
mParamValues = std::get<PARAM_DENSITY_VALUE>(GetParam());
mIsInputMute = (std::get<IS_INPUT_MUTE>(GetParam()));
mInput.resize(kBufferSize);
- if (mIsInputMute) {
- std::fill(mInput.begin(), mInput.end(), 0);
- } else {
- generateSineWave(kInputFrequency, mInput);
- }
}
void SetUp() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ if (mIsInputMute) {
+ std::fill(mInput.begin(), mInput.end(), 0);
+ } else {
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, 1.0,
+ kSamplingFrequency, mChannelLayout));
+ }
SetUpReverb();
}
void TearDown() override {
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 4c868a9..ace0597 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -153,9 +153,8 @@
public:
LoudnessEnhancerDataTest() {
std::tie(mFactory, mDescriptor) = GetParam();
- size_t channelCount =
- getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO));
+ size_t channelCount = getChannelCount(
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
mBufferSizeInFrames = kFrameCount * channelCount;
mInputBuffer.resize(mBufferSizeInFrames);
generateInputBuffer(mInputBuffer, 0, true, channelCount, kMaxAudioSampleValue);
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/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 3ce9e53..f127c81 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -133,11 +133,11 @@
PresetReverbProcessTest() {
std::tie(mFactory, mDescriptor) = GetParam();
mInput.resize(kBufferSize);
- generateSineWave(1000 /*Input Frequency*/, mInput);
}
void SetUp() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, mInput));
ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb());
}
void TearDown() override {
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index 3021370..c9c7172 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -94,7 +94,6 @@
}
}
- static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
static constexpr int kDurationMilliSec = 720;
static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
int kChannelCount = getChannelCount(
@@ -159,14 +158,6 @@
ASSERT_NO_FATAL_FAILURE(TearDownVirtualizer());
}
- void generateInput(std::vector<float>& buffer) {
- if (mZeroInput) {
- std::fill(buffer.begin(), buffer.end(), 0);
- } else {
- generateSineWave(1000 /*Input Frequency*/, buffer);
- }
- }
-
static constexpr float kAbsError = 0.00001;
bool mZeroInput;
};
@@ -176,7 +167,11 @@
std::vector<float> output(kBufferSize);
std::vector<int> strengths = {250, 500, 750, 1000};
- generateInput(input);
+ if (mZeroInput) {
+ std::fill(input.begin(), input.end(), 0);
+ } else {
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, input));
+ }
const float inputRmse =
audio_utils_compute_energy_mono(input.data(), AUDIO_FORMAT_PCM_FLOAT, input.size());
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index a942521..f019e2a 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -68,9 +68,14 @@
ASSERT_NE(nullptr, mFactory);
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ AudioChannelLayout inputLayout = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_MONO);
+ AudioChannelLayout outputLayout = inputLayout;
+
Parameter::Common common = createParamCommon(
- 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
- kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ 0 /* session */, 1 /* ioHandle */, mBufferSizeInFrames /* iSampleRate */,
+ mBufferSizeInFrames /* oSampleRate */, kInputFrameCount /* iFrameCount */,
+ kOutputFrameCount /* oFrameCount */, inputLayout, outputLayout);
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &mOpenEffectReturn, EX_NONE));
ASSERT_NE(nullptr, mEffect);
mVersion = EffectFactoryHelper::getHalVersion(mFactory);
@@ -189,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());
}
@@ -212,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;
@@ -261,7 +266,8 @@
constexpr float kPowerToleranceDb = 0.5;
- generateSineWave(std::vector<int>{1000}, mInputBuffer, 1.0, mBufferSizeInFrames);
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(1000, mInputBuffer, 1.0, mBufferSizeInFrames,
+ AudioChannelLayout::LAYOUT_MONO));
const float expectedPowerNormalized = audio_utils_compute_power_mono(
mInputBuffer.data(), AUDIO_FORMAT_PCM_FLOAT, mInputBuffer.size());
@@ -276,13 +282,14 @@
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));
- generateSineWave(std::vector<int>{1000}, mInputBuffer, maxAudioSampleValue,
- mBufferSizeInFrames);
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(std::vector<int>{1000}, mInputBuffer,
+ maxAudioSampleValue, mBufferSizeInFrames,
+ AudioChannelLayout::LAYOUT_MONO));
// The stop and reset calls to the effect are made towards the end in order to fetch the
// captureSampleBuffer values
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index b58c1c6..0b68b02 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -66,7 +66,7 @@
void initFrameCount() {
int channelCount = getChannelCount(
- AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
mInputFrameCount = kBufferSize / channelCount;
mOutputFrameCount = kBufferSize / channelCount;
}
@@ -93,10 +93,10 @@
}
}
- static constexpr int kDurationMilliSec = 720;
+ static constexpr int kDurationMilliSec = 1440;
static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
static constexpr int kMinLevel = -96;
- static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
+ static constexpr int mChannelLayout = kDefaultChannelLayout;
long mInputFrameCount, mOutputFrameCount;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
@@ -162,8 +162,6 @@
mInputMag.resize(mTestFrequencies.size());
mBinOffsets.resize(mTestFrequencies.size());
roundToFreqCenteredToFftBin(mTestFrequencies, mBinOffsets, kBinWidth);
- generateSineWave(mTestFrequencies, mInput);
- mInputMag = calculateMagnitude(mInput, mBinOffsets, kNPointFFT);
}
std::vector<int> calculatePercentageDiff(const std::vector<float>& outputMag) {
@@ -183,6 +181,11 @@
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
// Skips test fixture if api_level <= 34 (__ANDROID_API_U__).
if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP();
+ ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput, 1.0, kSamplingFrequency,
+ mChannelLayout));
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(mInputMag, mChannelLayout, mInput, mBinOffsets));
+
ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl());
}
void TearDown() override {
@@ -194,7 +197,6 @@
const int kVsrApiLevel;
static constexpr int kMaxAudioSample = 1;
static constexpr int kTransitionDuration = 300;
- static constexpr int kNPointFFT = 16384;
static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
static constexpr size_t offset = kSamplingFrequency * kTransitionDuration / 1000;
static constexpr float kBaseLevel = 0;
@@ -218,7 +220,9 @@
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(Volume::levelDb, kBaseLevel, EX_NONE));
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
- outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
for (size_t i = 0; i < diffs.size(); i++) {
@@ -231,7 +235,10 @@
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
std::vector<float> subOutputMute(output.begin() + offset, output.end());
- outputMag = calculateMagnitude(subOutputMute, mBinOffsets, kNPointFFT);
+
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, subOutputMute, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
for (size_t i = 0; i < diffs.size(); i++) {
@@ -239,7 +246,9 @@
}
// Verifying Fade out
- outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
for (size_t i = 0; i < diffs.size(); i++) {
@@ -253,7 +262,9 @@
std::vector<float> subOutputUnmute(output.begin() + offset, output.end());
- outputMag = calculateMagnitude(subOutputUnmute, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, subOutputUnmute, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
for (size_t i = 0; i < diffs.size(); i++) {
@@ -261,7 +272,9 @@
}
// Verifying Fade in
- outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
for (size_t i = 0; i < diffs.size(); i++) {
@@ -283,7 +296,9 @@
ASSERT_NO_FATAL_FAILURE(
processAndWriteToOutput(mInput, baseOutput, mEffect, &mOpenEffectReturn));
- outputMag = calculateMagnitude(baseOutput, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, baseOutput, mBinOffsets));
+
baseDiffs = calculatePercentageDiff(outputMag);
for (int level : decreasingLevels) {
@@ -298,7 +313,9 @@
ASSERT_NO_FATAL_FAILURE(
processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
- outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+ ASSERT_NO_FATAL_FAILURE(
+ calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
diffs = calculatePercentageDiff(outputMag);
// Decrease in volume level results in greater magnitude difference
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/can/aidl/default/service.cpp b/automotive/can/aidl/default/service.cpp
index eb45167..ef04cfd 100644
--- a/automotive/can/aidl/default/service.cpp
+++ b/automotive/can/aidl/default/service.cpp
@@ -20,12 +20,11 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
-namespace android::hardware::automotive::can {
-
using namespace std::string_literals;
+using namespace android;
using ::aidl::android::hardware::automotive::can::CanController;
-extern "C" int main() {
+int main() {
base::SetDefaultTag("CanController");
base::SetMinimumLogSeverity(base::VERBOSE);
@@ -40,4 +39,3 @@
LOG(FATAL) << "CanController exited unexpectedly!";
return EXIT_FAILURE;
}
-} // namespace android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
index 94e77b4..87a4497 100644
--- a/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
+++ b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
@@ -98,7 +98,11 @@
return true;
}
-extern "C" int main(int argc, char* argv[]) {
+} // namespace android::hardware::automotive::can
+
+int main(int argc, char* argv[]) {
+ using namespace android::hardware::automotive::can;
+
std::string configFilepath = static_cast<std::string>(kDefaultConfigPath);
// allow for CLI specification of a config file.
@@ -114,5 +118,3 @@
}
return 0;
}
-
-} // namespace android::hardware::automotive::can
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/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 18fc4b2..3f1f5f6 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -489,11 +489,11 @@
std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
int req_allocation_bitmask,
std::vector<AseDirectionConfiguration>& valid_direction_configurations,
- bool is_exact) {
+ bool isExact) {
// Prefer the same allocation_bitmask
int channel_count = getCountFromBitmask(req_allocation_bitmask);
- if (is_exact) {
+ if (isExact) {
for (auto& cfg : valid_direction_configurations) {
int cfg_bitmask =
getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
@@ -747,12 +747,19 @@
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
matched_ase_configuration_settings,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
- bool isMatchContext, bool isExact) {
+ bool isMatchContext, bool isExact, bool isMatchFlags) {
LOG(INFO) << __func__ << ": Trying to match for the requirement "
<< requirement.toString() << ", match context = " << isMatchContext
- << ", match exact = " << isExact;
+ << ", match exact = " << isExact
+ << ", match flags = " << isMatchFlags;
+ // Don't have to match with flag if requirements don't have flags.
+ auto requirement_flags_bitmask = 0;
+ if (isMatchFlags) {
+ if (!requirement.flags.has_value()) return std::nullopt;
+ requirement_flags_bitmask = requirement.flags.value().bitmask;
+ }
for (auto& setting : matched_ase_configuration_settings) {
- // Try to match context in metadata.
+ // Try to match context.
if (isMatchContext) {
if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
requirement.audioContext.bitmask)
@@ -761,6 +768,16 @@
<< getSettingOutputString(setting);
}
+ // Try to match configuration flags
+ if (isMatchFlags) {
+ if (!setting.flags.has_value()) continue;
+ if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
+ requirement_flags_bitmask)
+ continue;
+ LOG(DEBUG) << __func__ << ": Setting with matched flags: "
+ << getSettingOutputString(setting);
+ }
+
auto filtered_ase_configuration_setting =
getRequirementMatchedAseConfigurationSettings(setting, requirement,
isExact);
@@ -853,21 +870,25 @@
// If we cannot match, return an empty result.
// Matching priority list:
+ // Matched configuration flags, i.e. for asymmetric requirement.
// Preferred context - exact match with allocation
// Preferred context - loose match with allocation
// Any context - exact match with allocation
// Any context - loose match with allocation
bool found = false;
- for (bool match_context : {true, false}) {
- for (bool match_exact : {true, false}) {
- auto matched_setting =
- matchWithRequirement(matched_ase_configuration_settings,
- requirement, match_context, match_exact);
- if (matched_setting.has_value()) {
- result.push_back(matched_setting.value());
- found = true;
- break;
+ for (bool match_flag : {true, false}) {
+ for (bool match_context : {true, false}) {
+ for (bool match_exact : {true, false}) {
+ auto matched_setting = matchWithRequirement(
+ matched_ase_configuration_settings, requirement, match_context,
+ match_exact, match_flag);
+ if (matched_setting.has_value()) {
+ result.push_back(matched_setting.value());
+ found = true;
+ break;
+ }
}
+ if (found) break;
}
if (found) break;
}
@@ -881,7 +902,11 @@
}
}
- LOG(INFO) << __func__ << ": Found matches for all requirements!";
+ LOG(INFO) << __func__
+ << ": Found matches for all requirements, chosen settings:";
+ for (auto& setting : result) {
+ LOG(INFO) << __func__ << ": " << getSettingOutputString(setting);
+ }
*_aidl_return = result;
return ndk::ScopedAStatus::ok();
};
@@ -913,7 +938,13 @@
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
- bool is_exact) {
+ bool isExact, bool isMatchFlags) {
+ auto requirement_flags_bitmask = 0;
+ if (isMatchFlags) {
+ if (!qosRequirement.flags.has_value()) return std::nullopt;
+ requirement_flags_bitmask = qosRequirement.flags.value().bitmask;
+ }
+
std::optional<AseQosDirectionRequirement> direction_qos_requirement =
std::nullopt;
@@ -929,9 +960,18 @@
if ((setting.audioContext.bitmask & qosRequirement.audioContext.bitmask) !=
qosRequirement.audioContext.bitmask)
continue;
+ LOG(DEBUG) << __func__ << ": Setting with matched context: "
+ << getSettingOutputString(setting);
// Match configuration flags
- // Currently configuration flags are not populated, ignore.
+ if (isMatchFlags) {
+ if (!setting.flags.has_value()) continue;
+ if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
+ requirement_flags_bitmask)
+ continue;
+ LOG(DEBUG) << __func__ << ": Setting with matched flags: "
+ << getSettingOutputString(setting);
+ }
// Get a list of all matched AseDirectionConfiguration
// for the input direction
@@ -980,7 +1020,7 @@
direction_qos_requirement.value().aseConfiguration);
// Get the best matching config based on channel allocation
auto req_valid_configs = getValidConfigurationsFromAllocation(
- qos_allocation_bitmask, temp, is_exact);
+ qos_allocation_bitmask, temp, isExact);
if (req_valid_configs.empty()) {
LOG(WARNING) << __func__
<< ": Cannot find matching allocation for bitmask "
@@ -1010,29 +1050,38 @@
if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
if (!isValidQosRequirement(in_qosRequirement.sinkAseQosRequirement.value()))
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- {
- // Try exact match first
- result.sinkQosConfiguration =
- getDirectionQosConfiguration(kLeAudioDirectionSink, in_qosRequirement,
- ase_configuration_settings, true);
- if (!result.sinkQosConfiguration.has_value()) {
- result.sinkQosConfiguration = getDirectionQosConfiguration(
+ bool found = false;
+ for (bool match_flag : {true, false}) {
+ for (bool match_exact : {true, false}) {
+ auto setting = getDirectionQosConfiguration(
kLeAudioDirectionSink, in_qosRequirement,
- ase_configuration_settings, false);
+ ase_configuration_settings, match_exact, match_flag);
+ if (setting.has_value()) {
+ found = true;
+ result.sinkQosConfiguration = setting;
+ break;
+ }
}
+ if (found) break;
}
}
if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
if (!isValidQosRequirement(
in_qosRequirement.sourceAseQosRequirement.value()))
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- result.sourceQosConfiguration =
- getDirectionQosConfiguration(kLeAudioDirectionSource, in_qosRequirement,
- ase_configuration_settings, true);
- if (!result.sourceQosConfiguration.has_value()) {
- result.sourceQosConfiguration = getDirectionQosConfiguration(
- kLeAudioDirectionSource, in_qosRequirement,
- ase_configuration_settings, false);
+ bool found = false;
+ for (bool match_flag : {true, false}) {
+ for (bool match_exact : {true, false}) {
+ auto setting = getDirectionQosConfiguration(
+ kLeAudioDirectionSource, in_qosRequirement,
+ ase_configuration_settings, match_exact, match_flag);
+ if (setting.has_value()) {
+ found = true;
+ result.sourceQosConfiguration = setting;
+ break;
+ }
+ }
+ if (found) break;
}
}
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 3a82b73..8c4f543 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -164,7 +164,7 @@
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
- bool is_exact);
+ bool isExact, bool isMatchedFlag);
bool isSubgroupConfigurationMatchedContext(
AudioContext requirement_context,
IBluetoothAudioProvider::BroadcastQuality quality,
@@ -175,7 +175,7 @@
matched_ase_configuration_settings,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
requirements,
- bool isMatchContext, bool isExact);
+ bool isMatchContext, bool isExact, bool isMatchFlags);
};
class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index d4968a8..6d1da63 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -90,15 +90,15 @@
cc_test {
name: "BluetoothLeAudioCodecsProviderTest",
- srcs: [
- "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
- "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
- ],
defaults: [
"latest_android_hardware_audio_common_ndk_static",
"latest_android_hardware_bluetooth_audio_ndk_static",
"latest_android_media_audio_common_types_ndk_static",
],
+ srcs: [
+ "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
+ "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
+ ],
header_libs: [
"libxsdc-utils",
],
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
index 07e4997..3e18de2 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -47,6 +47,8 @@
#include <aidl/android/hardware/bluetooth/audio/Phy.h>
#include <android-base/logging.h>
+#include <optional>
+
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
@@ -561,6 +563,17 @@
if (ase_cnt == 2) directionAseConfiguration.push_back(config);
}
+// Comparing if 2 AseDirectionConfiguration is equal.
+// Configuration are copied in, so we can remove some fields for comparison
+// without affecting the result.
+bool isAseConfigurationEqual(AseDirectionConfiguration cfg_a,
+ AseDirectionConfiguration cfg_b) {
+ // Remove unneeded fields when comparing.
+ cfg_a.aseConfiguration.metadata = std::nullopt;
+ cfg_b.aseConfiguration.metadata = std::nullopt;
+ return cfg_a == cfg_b;
+}
+
void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
const le_audio::AudioSetConfiguration* flat_cfg,
std::vector<const le_audio::CodecConfiguration*>* codec_cfgs,
@@ -569,7 +582,7 @@
std::vector<std::optional<AseDirectionConfiguration>>&
sourceAseConfiguration,
std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration,
- ConfigurationFlags& /*configurationFlags*/) {
+ ConfigurationFlags& configurationFlags) {
if (flat_cfg == nullptr) {
LOG(ERROR) << "flat_cfg cannot be null";
return;
@@ -636,6 +649,32 @@
sourceAseConfiguration, location);
}
}
+
+ // After putting all subconfig, check if it's an asymmetric configuration
+ // and populate information for ConfigurationFlags
+ if (!sinkAseConfiguration.empty() && !sourceAseConfiguration.empty()) {
+ if (sinkAseConfiguration.size() == sourceAseConfiguration.size()) {
+ for (int i = 0; i < sinkAseConfiguration.size(); ++i) {
+ if (sinkAseConfiguration[i].has_value() !=
+ sourceAseConfiguration[i].has_value()) {
+ // Different configuration: one is not empty and other is.
+ configurationFlags.bitmask |=
+ ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+ } else if (sinkAseConfiguration[i].has_value()) {
+ // Both is not empty, comparing inner fields:
+ if (!isAseConfigurationEqual(sinkAseConfiguration[i].value(),
+ sourceAseConfiguration[i].value())) {
+ configurationFlags.bitmask |=
+ ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+ }
+ }
+ }
+ } else {
+ // Different number of ASE, is a different configuration.
+ configurationFlags.bitmask |=
+ ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+ }
+ }
} else {
if (codec_cfg == nullptr) {
LOG(ERROR) << "No codec config matching key " << codec_config_key.c_str()
@@ -645,8 +684,6 @@
<< "' has no valid subconfigurations.";
}
}
-
- // TODO: Populate information for ConfigurationFlags
}
bool AudioSetConfigurationProviderJson::LoadConfigurationsFromFiles(
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 59c43a4..a96df52 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -14,10 +14,13 @@
* limitations under the License.
*/
+#include <optional>
#include <set>
#include "aidl/android/hardware/bluetooth/audio/ChannelMode.h"
#include "aidl/android/hardware/bluetooth/audio/CodecId.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h"
#include "aidl_android_hardware_bluetooth_audio_setting_enums.h"
#define LOG_TAG "BTAudioCodecsProviderAidl"
@@ -52,6 +55,26 @@
return le_audio_offload_setting;
}
+void add_flag(CodecInfo& codec_info, int32_t bitmask) {
+ auto& transport =
+ codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ if (!transport.flags.has_value()) transport.flags = ConfigurationFlags();
+ transport.flags->bitmask |= bitmask;
+}
+
+// Compare 2 codec info to see if they are equal.
+// Currently only compare bitdepth, frameDurationUs and samplingFrequencyHz
+bool is_equal(CodecInfo& codec_info_a, CodecInfo& codec_info_b) {
+ auto& transport_a =
+ codec_info_a.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ auto& transport_b =
+ codec_info_b.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ return codec_info_a.name == codec_info_b.name &&
+ transport_a.bitdepth == transport_b.bitdepth &&
+ transport_a.frameDurationUs == transport_b.frameDurationUs &&
+ transport_a.samplingFrequencyHz == transport_b.samplingFrequencyHz;
+}
+
std::unordered_map<SessionType, std::vector<CodecInfo>>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
const std::optional<setting::LeAudioOffloadSetting>&
@@ -111,6 +134,9 @@
codec_info.transport =
CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
+ // Add low latency support by default
+ add_flag(codec_info, ConfigurationFlags::LOW_LATENCY);
+
// Mapping codec configuration information
auto& transport =
codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
@@ -152,6 +178,25 @@
}
}
+ // Goes through a list of scenarios and detect asymmetrical config using
+ // codecConfiguration name.
+ for (auto& s : supported_scenarios_) {
+ if (s.hasEncode() && s.hasDecode() &&
+ config_codec_info_map_.count(s.getEncode()) &&
+ config_codec_info_map_.count(s.getDecode())) {
+ // Check if it's actually using the different codec
+ auto& encode_codec_info = config_codec_info_map_[s.getEncode()];
+ auto& decode_codec_info = config_codec_info_map_[s.getDecode()];
+ if (!is_equal(encode_codec_info, decode_codec_info)) {
+ // Change both x and y to become asymmetrical
+ add_flag(encode_codec_info,
+ ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS);
+ add_flag(decode_codec_info,
+ ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS);
+ }
+ }
+ }
+
// Goes through every scenario, deduplicate configuration, skip the invalid
// config references (e.g. the "invalid" entries in the xml file).
std::set<std::string> encoding_config, decoding_config, broadcast_config;
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
index c47f7d5..6338e11 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
@@ -20,10 +20,16 @@
#include <tuple>
#include "BluetoothLeAudioCodecsProvider.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h"
+#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
using aidl::android::hardware::bluetooth::audio::BluetoothLeAudioCodecsProvider;
+using aidl::android::hardware::bluetooth::audio::CodecInfo;
+using aidl::android::hardware::bluetooth::audio::ConfigurationFlags;
using aidl::android::hardware::bluetooth::audio::
LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::SessionType;
using aidl::android::hardware::bluetooth::audio::setting::AudioLocation;
using aidl::android::hardware::bluetooth::audio::setting::CodecConfiguration;
using aidl::android::hardware::bluetooth::audio::setting::
@@ -51,15 +57,30 @@
static const Scenario kValidBroadcastScenario(
std::nullopt, std::nullopt, std::make_optional("BcastStereo_16_2"));
+static const Scenario kValidAsymmetricScenario(
+ std::make_optional("OneChanStereo_32_1"),
+ std::make_optional("OneChanStereo_16_1"), std::nullopt);
+
// Configuration
static const Configuration kValidConfigOneChanStereo_16_1(
std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
+
+static const Configuration kValidConfigOneChanStereo_32_1(
+ std::make_optional("OneChanStereo_32_1"), std::make_optional("LC3_32k_1"),
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
+
// CodecConfiguration
static const CodecConfiguration kValidCodecLC3_16k_1(
std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
std::nullopt, std::make_optional(16000), std::make_optional(7500),
std::make_optional(30), std::nullopt);
+
+static const CodecConfiguration kValidCodecLC3_32k_1(
+ std::make_optional("LC3_32k_1"), std::make_optional(CodecType::LC3),
+ std::nullopt, std::make_optional(32000), std::make_optional(7500),
+ std::make_optional(30), std::nullopt);
+
// StrategyConfiguration
static const StrategyConfiguration kValidStrategyStereoOneCis(
std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
@@ -181,6 +202,17 @@
kValidStrategyStereoOneCisBoth, kValidStrategyStereoTwoCisBoth,
kValidStrategyMonoOneCisBoth, kValidStrategyBroadcastStereoBoth})};
+// Define some valid asymmetric scenario list
+static const std::vector<ScenarioList> kValidAsymmetricScenarioList = {
+ ScenarioList(std::vector<Scenario>{kValidAsymmetricScenario})};
+static const std::vector<ConfigurationList> kValidAsymmetricConfigurationList =
+ {ConfigurationList(std::vector<Configuration>{
+ kValidConfigOneChanStereo_16_1, kValidConfigOneChanStereo_32_1})};
+static const std::vector<CodecConfigurationList>
+ kValidAsymmetricCodecConfigurationList = {
+ CodecConfigurationList(std::vector<CodecConfiguration>{
+ kValidCodecLC3_16k_1, kValidCodecLC3_32k_1})};
+
class BluetoothLeAudioCodecsProviderTest
: public ::testing::TestWithParam<OffloadSetting> {
public:
@@ -227,6 +259,19 @@
return le_audio_codec_capabilities;
}
+ std::unordered_map<SessionType, std::vector<CodecInfo>>
+ RunCodecInfoTestCase() {
+ auto& [scenario_lists, configuration_lists, codec_configuration_lists,
+ strategy_configuration_lists] = GetParam();
+ LeAudioOffloadSetting le_audio_offload_setting(
+ scenario_lists, configuration_lists, codec_configuration_lists,
+ strategy_configuration_lists);
+ auto le_audio_codec_capabilities =
+ BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
+ std::make_optional(le_audio_offload_setting));
+ return le_audio_codec_capabilities;
+ }
+
private:
static inline OffloadSetting CreateTestCase(
const ScenarioList& scenario_list,
@@ -392,6 +437,39 @@
ASSERT_TRUE(!le_audio_codec_capabilities.empty());
}
+class ComposeLeAudioAymmetricCodecInfoTest
+ : public BluetoothLeAudioCodecsProviderTest {
+ public:
+};
+
+TEST_P(ComposeLeAudioAymmetricCodecInfoTest, AsymmetricCodecInfoNotEmpty) {
+ Initialize();
+ auto le_audio_codec_info_map = RunCodecInfoTestCase();
+ ASSERT_TRUE(!le_audio_codec_info_map.empty());
+ // Check true asymmetric codec info
+ ASSERT_TRUE(!le_audio_codec_info_map
+ [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH]
+ .empty());
+ ASSERT_TRUE(!le_audio_codec_info_map
+ [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH]
+ .empty());
+ auto required_flag = ConfigurationFlags();
+ required_flag.bitmask |= ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+
+ auto codec_info = le_audio_codec_info_map
+ [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH][0];
+ ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::Tag::leAudio);
+ auto& transport =
+ codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ ASSERT_EQ(transport.flags, std::make_optional(required_flag));
+
+ codec_info = le_audio_codec_info_map
+ [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH][0];
+ ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::Tag::leAudio);
+ transport = codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+ ASSERT_EQ(transport.flags, std::make_optional(required_flag));
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetScenariosTest);
INSTANTIATE_TEST_SUITE_P(
BluetoothLeAudioCodecsProviderTest, GetScenariosTest,
@@ -434,6 +512,15 @@
kValidScenarioList, kValidConfigurationList,
kValidCodecConfigurationList, kValidStrategyConfigurationList)));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ ComposeLeAudioAymmetricCodecInfoTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, ComposeLeAudioAymmetricCodecInfoTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ kValidAsymmetricScenarioList, kValidAsymmetricConfigurationList,
+ kValidAsymmetricCodecConfigurationList,
+ kValidStrategyConfigurationList)));
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
index 5f6d86e..109ca5c 100644
--- a/bluetooth/hci/h4_protocol.cc
+++ b/bluetooth/hci/h4_protocol.cc
@@ -45,29 +45,50 @@
}
size_t H4Protocol::Send(PacketType type, const uint8_t* data, size_t length) {
- /* For HCI communication over USB dongle, multiple write results in
- * response timeout as driver expect type + data at once to process
- * the command, so using "writev"(for atomicity) here.
- */
- struct iovec iov[2];
- ssize_t ret = 0;
- iov[0].iov_base = &type;
- iov[0].iov_len = sizeof(type);
- iov[1].iov_base = (void*)data;
- iov[1].iov_len = length;
- while (1) {
- ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2));
+ struct iovec iov_array[] = {{&type, sizeof(type)},
+ {const_cast<uint8_t*>(data), length}};
+ size_t iovcnt = sizeof(iov_array) / sizeof(iov_array[0]);
+ struct iovec* iov = iov_array;
+ size_t total_bytes = sizeof(type) + length;
+ size_t remaining_bytes = total_bytes;
+ size_t bytes_written = 0;
+
+ while (remaining_bytes > 0) {
+ ssize_t ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, iovcnt));
if (ret == -1) {
- LOG_ALWAYS_FATAL("%s error writing to UART (%s)", __func__,
- strerror(errno));
+ if (errno == EAGAIN) continue;
+ ALOGE("Error writing to UART (%s)", strerror(errno));
+ break;
} else if (ret == 0) {
// Nothing written :(
ALOGE("%s zero bytes written - something went wrong...", __func__);
break;
+ } else if (ret == remaining_bytes) {
+ // Everything written
+ bytes_written += ret;
+ break;
}
- break;
+
+ // Updating counters for partial writes
+ bytes_written += ret;
+ remaining_bytes -= ret;
+
+ ALOGW("%s: %zu/%zu bytes written - retrying remaining %zu bytes", __func__,
+ bytes_written, total_bytes, remaining_bytes);
+
+ // Remove fully written iovs from the list
+ while (ret >= iov->iov_len) {
+ ret -= iov->iov_len;
+ ++iov;
+ --iovcnt;
+ }
+ // Adjust the iov to point to the remaining data that needs to be written
+ if (ret > 0) {
+ iov->iov_base = static_cast<uint8_t*>(iov->iov_base) + ret;
+ iov->iov_len -= ret;
+ }
}
- return ret;
+ return total_bytes - remaining_bytes;
}
size_t H4Protocol::OnPacketReady(const std::vector<uint8_t>& packet) {
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 6cf9e52..2903c03 100644
--- a/bluetooth/socket/aidl/Android.bp
+++ b/bluetooth/socket/aidl/Android.bp
@@ -40,7 +40,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
+ "com.android.bt",
],
min_sdk_version: "33",
},
diff --git a/boot/aidl/client/BootControlClient.cpp b/boot/aidl/client/BootControlClient.cpp
index 5cca183..7aab5b4 100644
--- a/boot/aidl/client/BootControlClient.cpp
+++ b/boot/aidl/client/BootControlClient.cpp
@@ -80,6 +80,7 @@
explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
: module_(module),
boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
+ AIBinder_DeathRecipient_setOnUnlinked(boot_control_death_recipient, onCallbackUnlinked);
binder_status_t status =
AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
if (status != STATUS_OK) {
@@ -236,6 +237,11 @@
private:
std::shared_ptr<IBootControl> module_;
AIBinder_DeathRecipient* boot_control_death_recipient;
+ static void onCallbackUnlinked(void* /*client*/) {
+ // this is an empty function needed to suppress the "AIBinder_linkToDeath is being called
+ // with a non-null cookie and no onUnlink callback set. This might not be intended.
+ // AIBinder_DeathRecipient_setOnUnlinked should be called first." warning
+ }
static void onBootControlServiceDied(void* client) {
BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
self->onBootControlServiceDied();
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/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
index 93c8376..228e2af 100644
--- a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
+++ b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
@@ -84,20 +84,20 @@
for (int s = 0; s < 2; s++) {
const auto result = boot->setActiveBootSlot(s);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
}
{
// Restore original flags to avoid problems on reboot
auto result = boot->setActiveBootSlot(curSlot);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
if (!otherBootable) {
const auto result = boot->setSlotAsUnbootable(otherSlot);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
}
result = boot->markBootSuccessful();
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
}
{
int slots = 0;
@@ -116,19 +116,19 @@
boot->isSlotBootable(otherSlot, &otherBootable);
{
auto result = boot->setSlotAsUnbootable(otherSlot);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
boot->isSlotBootable(otherSlot, &otherBootable);
ASSERT_FALSE(otherBootable);
// Restore original flags to avoid problems on reboot
if (otherBootable) {
result = boot->setActiveBootSlot(otherSlot);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
}
result = boot->setActiveBootSlot(curSlot);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
result = boot->markBootSuccessful();
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
}
{
int32_t slots = 0;
@@ -143,7 +143,7 @@
for (int s = 0; s < 2; s++) {
bool bootable = false;
const auto res = boot->isSlotBootable(s, &bootable);
- ASSERT_TRUE(res.isOk()) << res.getMessage();
+ ASSERT_TRUE(res.isOk()) << res;
}
int32_t slots = 0;
boot->getNumberSlots(&slots);
@@ -184,7 +184,7 @@
{
const string emptySuffix = "";
const auto result = boot->getSuffix(numSlots, &suffixStr);
- ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result.isOk()) << result;
ASSERT_EQ(suffixStr, emptySuffix);
}
}
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..91f58d4 100755
--- a/compatibility_matrices/bump.py
+++ b/compatibility_matrices/bump.py
@@ -45,6 +45,7 @@
self.current_level = cmdline_args.current_level
self.current_letter = cmdline_args.current_letter
self.current_version = cmdline_args.platform_version
+ self.next_version = cmdline_args.next_platform_version
self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
self.device_module_name = "framework_compatibility_matrix.device.xml"
@@ -132,27 +133,27 @@
return
try:
check_call(["grep", "-h",
- f"{self.current_letter.upper()} = {self.current_level}",
- "system/libvintf/include/vintf/Level.h"])
+ f"{self.next_letter.upper()} = {self.next_level}",
+ f"{self.top}/system/libvintf/include/vintf/Level.h"])
except subprocess.CalledProcessError:
print("Adding new API level to libvintf")
- add_lines_above("system/libvintf/analyze_matrix/analyze_matrix.cpp",
+ add_lines_above(f"{self.top}/system/libvintf/analyze_matrix/analyze_matrix.cpp",
" case Level::UNSPECIFIED:",
textwrap.indent(textwrap.dedent(f"""\
- case Level::{self.current_letter.upper()}:
- return "Android {self.current_version} ({self.current_letter.upper()})";"""),
+ case Level::{self.next_letter.upper()}:
+ return "Android {self.next_version} ({self.next_letter.upper()})";"""),
" "*2))
- add_lines_above("system/libvintf/include/vintf/Level.h",
+ add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
" // To add new values:",
- f" {self.current_letter.upper()} = {self.current_level},")
- add_lines_above("system/libvintf/include/vintf/Level.h",
+ f" {self.next_letter.upper()} = {self.next_level},")
+ add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
" Level::UNSPECIFIED,",
- f" Level::{self.current_letter.upper()},")
- add_lines_above("system/libvintf/RuntimeInfo.cpp",
+ f" Level::{self.next_letter.upper()},")
+ add_lines_above(f"{self.top}/system/libvintf/RuntimeInfo.cpp",
" // Add more levels above this line.",
textwrap.indent(textwrap.dedent(f"""\
- case {self.current_version}: {{
- ret = Level::{self.current_letter.upper()};
+ case {self.next_version}: {{
+ ret = Level::{self.next_letter.upper()};
}} break;"""),
" "*3))
@@ -181,14 +182,18 @@
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="Current Android release version number (e.g. 16)")
+ parser.add_argument("next_platform_version",
+ type=str,
+ nargs="?",
+ help="Next Android release version number number (e.g. 17)")
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/health/aidl/default/LinkedCallback.h b/health/aidl/default/LinkedCallback.h
index 8c9c997..6b17be0 100644
--- a/health/aidl/default/LinkedCallback.h
+++ b/health/aidl/default/LinkedCallback.h
@@ -36,7 +36,7 @@
// cookie when it's unlinked.
static ::android::base::Result<LinkedCallback*> Make(
std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback);
- // On callback died, unreigster it from the service.
+ // On callback died, unregister it from the service.
void OnCallbackDied();
private:
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 4a57f44..fc5979a 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -229,13 +229,13 @@
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
hidl_vec<hidl_vec<uint8_t>> cert_chain;
- EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
- convert(AttestKey(
- AuthorizationSetBuilder()
+ ErrorCode result = convert(
+ AttestKey(AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
- &cert_chain)));
+ &cert_chain));
+ EXPECT_TRUE(result == ErrorCode::UNIMPLEMENTED || result == ErrorCode::INVALID_ARGUMENT);
CheckedDeleteKey();
ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
@@ -244,13 +244,13 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
- EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
- convert(AttestKey(
- AuthorizationSetBuilder()
+ result = convert(
+ AttestKey(AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
- &cert_chain)));
+ &cert_chain));
+ EXPECT_TRUE(result == ErrorCode::UNIMPLEMENTED || result == ErrorCode::INVALID_ARGUMENT);
CheckedDeleteKey();
}
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/macsec/aidl/default/service.cpp b/macsec/aidl/default/service.cpp
index faf3a09..9d5d3bf 100644
--- a/macsec/aidl/default/service.cpp
+++ b/macsec/aidl/default/service.cpp
@@ -20,12 +20,11 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
-namespace android::hardware::macsec {
-
using namespace std::string_literals;
+using namespace android;
using ::aidl::android::hardware::macsec::MacsecPskPlugin;
-extern "C" int main() {
+int main() {
base::SetDefaultTag("MacsecPskPlugin");
base::SetMinimumLogSeverity(base::VERBOSE);
@@ -40,4 +39,3 @@
LOG(FATAL) << "MacsecPskPlugin exited unexpectedly!";
return EXIT_FAILURE;
}
-} // namespace 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..a61f8ee 100644
--- a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
+++ b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
@@ -114,16 +114,26 @@
}
}
-void static nfaVSCallback(uint8_t event, uint16_t /* param_len */, uint8_t* p_param) {
+void static nfaVSCallback(uint8_t event, uint16_t param_len, uint8_t* p_param) {
switch (event & NCI_OID_MASK) {
case NCI_MSG_PROP_ANDROID: {
uint8_t android_sub_opcode = p_param[3];
switch (android_sub_opcode) {
case NCI_ANDROID_PASSIVE_OBSERVE: {
- sVSCmdStatus = p_param[4];
- LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
- SyncEventGuard guard(sNfaVsCommand);
- sNfaVsCommand.notifyOne();
+ if (param_len == 5) {
+ if ((p_param[0] & NCI_MT_MASK) == (NCI_MT_RSP << NCI_MT_SHIFT)) {
+ sVSCmdStatus = p_param[4];
+ LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
+ SyncEventGuard guard(sNfaVsCommand);
+ sNfaVsCommand.notifyOne();
+ } else {
+ LOG(WARNING) << StringPrintf(
+ "Observe Mode RSP has incorrect message type: %x", p_param[0]);
+ }
+ } else {
+ LOG(WARNING) << StringPrintf("Observe Mode RSP has incorrect length: %d",
+ param_len);
+ }
} break;
case NCI_ANDROID_POLLING_FRAME_NTF: {
// TODO
@@ -152,12 +162,11 @@
}
}
- uint8_t cmd[] = {(NCI_MT_CMD << NCI_MT_SHIFT) | NCI_GID_PROP, NCI_MSG_PROP_ANDROID,
- NCI_ANDROID_PASSIVE_OBSERVE_PARAM_SIZE, NCI_ANDROID_PASSIVE_OBSERVE,
+ uint8_t cmd[] = {NCI_ANDROID_PASSIVE_OBSERVE,
static_cast<uint8_t>(enable ? NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE
: NCI_ANDROID_PASSIVE_OBSERVE_PARAM_DISABLE)};
- status = NFA_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/Android.bp b/security/keymint/aidl/Android.bp
index a2e58ac..76aa604 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -99,3 +99,13 @@
"android.hardware.security.keymint-V4-rust",
],
}
+
+// java_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this java_defaults to avoid
+// managing dependency versions explicitly.
+java_defaults {
+ name: "keymint_use_latest_hal_aidl_java",
+ static_libs: [
+ "android.hardware.security.keymint-V4-java",
+ ],
+}
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..fc703e9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -87,12 +87,14 @@
* SHA-2 256.
* - Unpadded, RSAES-OAEP and RSAES-PKCS1-v1_5 padding modes for RSA encryption.
*
- * o ECDSA
+ * o ECDSA and ECDH
*
+ * - IKeyMintDevices must support elliptic curve signing (Purpose::SIGN, Purpose::ATTEST_KEY)
+ * and key agreement operations (Purpose::AGREE_KEY).
* - TRUSTED_ENVIRONMENT IKeyMintDevices must support NIST curves P-224, P-256, P-384 and
* P-521. STRONGBOX IKeyMintDevices must support NIST curve P-256.
- * - TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256, SHA-2
- * 384 and SHA-2 512 digest modes. STRONGBOX IKeyMintDevices must support SHA-2 256.
+ * - For signing, TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256,
+ * SHA-2 384 and SHA-2 512 digest modes. STRONGBOX IKeyMintDevices must support SHA-2 256.
* - TRUSTED_ENVRIONMENT IKeyMintDevices must support curve 25519 for Purpose::SIGN (Ed25519,
* as specified in RFC 8032), Purpose::ATTEST_KEY (Ed25519) or for KeyPurpose::AGREE_KEY
* (X25519, as specified in RFC 7748). However, a key must have exactly one of these
@@ -302,12 +304,12 @@
* PaddingMode::RSA_OAEP, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
* PaddingMode::RSA_PKCS1_1_5_SIGN for RSA keys.
*
- * == ECDSA Keys ==
+ * == ECDSA/ECDH Keys ==
*
- * Tag::EC_CURVE must be provided to generate an ECDSA key. If it is not provided, generateKey
- * must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE. TEE
- * IKeyMintDevice implementations must support all required curves. StrongBox implementations
- * must support P_256 and no other curves.
+ * Tag::EC_CURVE must be provided to generate an elliptic curve key. If it is not provided,
+ * generateKey must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE.
+ * TEE IKeyMintDevice implementations must support all required curves. StrongBox
+ * implementations must support P_256 and no other curves.
*
* Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER must be provided to specify the
* valid date range for the returned X.509 certificate holding the public key. If omitted,
@@ -318,10 +320,10 @@
* than one purpose should be rejected with ErrorCode::INCOMPATIBLE_PURPOSE.
* StrongBox implementation do not support CURVE_25519.
*
- * Tag::DIGEST specifies digest algorithms that may be used with the new key. TEE
- * IKeyMintDevice implementations must support all Digest values (see Digest.aidl) for ECDSA
- * keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice implementations must
- * support SHA_2_256.
+ * Tag::DIGEST specifies digest algorithms that may be used with the new key when used for
+ * signing. TEE IKeyMintDevice implementations must support all Digest values (see Digest.aidl)
+ * for ECDSA keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice
+ * implementations must support SHA_2_256.
*
* == AES Keys ==
*
@@ -826,6 +828,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 +967,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/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 743928e..2f34b9d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -2269,10 +2269,19 @@
get_unique_id(app_id, min_date - 1, &unique_id8);
EXPECT_NE(unique_id, unique_id8);
- // Marking RESET_SINCE_ID_ROTATION should give a different unique ID.
- vector<uint8_t> unique_id9;
- get_unique_id(app_id, cert_date, &unique_id9, /* reset_id = */ true);
- EXPECT_NE(unique_id, unique_id9);
+ // Some StrongBox implementations did not correctly handle RESET_SINCE_ID_ROTATION when
+ // combined with use of an ATTEST_KEY, but this was not previously tested. Tests under GSI
+ // were updated to implicitly use ATTEST_KEYS (because rkp-only status cannot be determined),
+ // uncovering the problem. Skip this test for older implementations in that situation
+ // (cf. b/385800086).
+ int vendor_api_level = get_vendor_api_level();
+ if (!(is_gsi_image() && SecLevel() == SecurityLevel::STRONGBOX &&
+ vendor_api_level < AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__))) {
+ // Marking RESET_SINCE_ID_ROTATION should give a different unique ID.
+ vector<uint8_t> unique_id9;
+ get_unique_id(app_id, cert_date, &unique_id9, /* reset_id = */ true);
+ EXPECT_NE(unique_id, unique_id9);
+ }
}
/*
@@ -2281,6 +2290,16 @@
* Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
*/
TEST_P(NewKeyGenerationTest, EcdsaAttestationTagNoApplicationId) {
+ int vendor_api_level = get_vendor_api_level();
+ if (is_gsi_image() && SecLevel() == SecurityLevel::STRONGBOX &&
+ vendor_api_level < AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+ // Some StrongBox implementations did not correctly handle missing APPLICATION_ID when
+ // combined with use of an ATTEST_KEY, but this was not previously tested. Tests under
+ // GSI were updated to implicitly use ATTEST_KEYS (because rkp-only status cannot be
+ // determined), uncovering the problem. Skip this test for older implementations in that
+ // situation (cf. b/385800086).
+ GTEST_SKIP() << "Skip test on StrongBox device with vendor-api-level < __ANDROID_API_V__";
+ }
auto challenge = "hello";
auto attest_app_id = "foo";
auto subject = "cert subj 2";
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index eaeec32..ecf69e8 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());
@@ -862,15 +863,15 @@
allowAnyMode);
}
-ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& encodedCsr,
- const std::string& instanceName) {
+ErrMsgOr<hwtrust::DiceChain> getDiceChain(const std::vector<uint8_t>& encodedCsr, bool isFactory,
+ bool allowAnyMode, std::string_view instanceName) {
auto diceChainKind = getDiceChainKind();
if (!diceChainKind) {
return diceChainKind.message();
}
- auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName));
+ auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, isFactory, allowAnyMode,
+ deviceSuffix(instanceName));
if (!csr.ok()) {
return csr.error().message();
}
@@ -880,6 +881,16 @@
return diceChain.error().message();
}
+ return std::move(*diceChain);
+}
+
+ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& encodedCsr,
+ const std::string& instanceName) {
+ auto diceChain =
+ getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName);
+ if (!diceChain) {
+ return diceChain.message();
+ }
return diceChain->IsProper();
}
@@ -898,20 +909,10 @@
std::string_view instanceName1,
const std::vector<uint8_t>& encodedCsr2,
std::string_view instanceName2) {
- auto diceChainKind = getDiceChainKind();
- if (!diceChainKind) {
- return diceChainKind.message();
- }
-
- auto csr1 = hwtrust::Csr::validate(encodedCsr1, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName1));
- if (!csr1.ok()) {
- return csr1.error().message();
- }
-
- auto diceChain1 = csr1->getDiceChain();
- if (!diceChain1.ok()) {
- return diceChain1.error().message();
+ auto diceChain1 =
+ getDiceChain(encodedCsr1, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName1);
+ if (!diceChain1) {
+ return diceChain1.message();
}
auto proper1 = diceChain1->IsProper();
@@ -920,15 +921,10 @@
hexlify(encodedCsr1);
}
- auto csr2 = hwtrust::Csr::validate(encodedCsr2, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName2));
- if (!csr2.ok()) {
- return csr2.error().message();
- }
-
- auto diceChain2 = csr2->getDiceChain();
- if (!diceChain2.ok()) {
- return diceChain2.error().message();
+ auto diceChain2 =
+ getDiceChain(encodedCsr2, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName2);
+ if (!diceChain2) {
+ return diceChain2.message();
}
auto proper2 = diceChain2->IsProper();
@@ -946,20 +942,10 @@
}
ErrMsgOr<bool> verifyComponentNameInKeyMintDiceChain(const std::vector<uint8_t>& encodedCsr) {
- auto diceChainKind = getDiceChainKind();
- if (!diceChainKind) {
- return diceChainKind.message();
- }
-
- auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(DEFAULT_INSTANCE_NAME));
- if (!csr.ok()) {
- return csr.error().message();
- }
-
- auto diceChain = csr->getDiceChain();
- if (!diceChain.ok()) {
- return diceChain.error().message();
+ auto diceChain = getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true,
+ DEFAULT_INSTANCE_NAME);
+ if (!diceChain) {
+ return diceChain.message();
}
auto satisfied = diceChain->componentNameContains(kKeyMintComponentName);
@@ -972,20 +958,10 @@
ErrMsgOr<bool> hasNonNormalModeInDiceChain(const std::vector<uint8_t>& encodedCsr,
std::string_view instanceName) {
- auto diceChainKind = getDiceChainKind();
- if (!diceChainKind) {
- return diceChainKind.message();
- }
-
- auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- true /*allowAnyMode*/, deviceSuffix(instanceName));
- if (!csr.ok()) {
- return csr.error().message();
- }
-
- auto diceChain = csr->getDiceChain();
- if (!diceChain.ok()) {
- return diceChain.error().message();
+ auto diceChain =
+ getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName);
+ if (!diceChain) {
+ return diceChain.message();
}
auto hasNonNormalModeInDiceChain = diceChain->hasNonNormalMode();
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 810cc38..7ef445e 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -344,6 +344,53 @@
ASSERT_TRUE(*result);
}
+/**
+ * Check that ro.boot.vbmeta.device_state is not "locked" or ro.boot.verifiedbootstate
+ * is not "green" if and only if the mode on at least one certificate in the DICE chain
+ * is non-normal.
+ */
+TEST(NonParameterizedTests, unlockedBootloaderStatesImpliesNonnormalRkpVmDiceChain) {
+ if (!AServiceManager_isDeclared(RKPVM_INSTANCE_NAME.c_str())) {
+ GTEST_SKIP() << "The RKP VM (" << RKPVM_INSTANCE_NAME << ") is not present on this device.";
+ }
+
+ auto rpc = getHandle<IRemotelyProvisionedComponent>(RKPVM_INSTANCE_NAME);
+ ASSERT_NE(rpc, nullptr) << "The RKP VM (" << RKPVM_INSTANCE_NAME << ") RPC is unavailable.";
+
+ RpcHardwareInfo hardwareInfo;
+ auto status = rpc->getHardwareInfo(&hardwareInfo);
+ if (!status.isOk()) {
+ GTEST_SKIP() << "The RKP VM is not supported on this system.";
+ }
+
+ auto challenge = randomBytes(MAX_CHALLENGE_SIZE);
+ bytevec csr;
+ auto rkpVmStatus = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
+ ASSERT_TRUE(rkpVmStatus.isOk()) << status.getDescription();
+
+ auto isProper = isCsrWithProperDiceChain(csr, RKPVM_INSTANCE_NAME);
+ ASSERT_TRUE(isProper) << isProper.message();
+ if (!*isProper) {
+ GTEST_SKIP() << "Skipping test: Only a proper DICE chain has a mode set.";
+ }
+
+ auto nonNormalMode = hasNonNormalModeInDiceChain(csr, RKPVM_INSTANCE_NAME);
+ ASSERT_TRUE(nonNormalMode) << nonNormalMode.message();
+
+ auto deviceState = ::android::base::GetProperty("ro.boot.vbmeta.device_state", "");
+ auto verifiedBootState = ::android::base::GetProperty("ro.boot.verifiedbootstate", "");
+
+ ASSERT_TRUE(!deviceState.empty());
+ ASSERT_TRUE(!verifiedBootState.empty());
+
+ ASSERT_EQ(deviceState != "locked" || verifiedBootState != "green", *nonNormalMode)
+ << "ro.boot.vbmeta.device_state = '" << deviceState
+ << "' and ro.boot.verifiedbootstate = '" << verifiedBootState << "', but the DICE "
+ << " chain has a " << (*nonNormalMode ? "non-normal" : "normal") << " DICE mode."
+ << " Locked devices must report normal, and unlocked devices must report "
+ << " non-normal.";
+}
+
using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
@@ -849,37 +896,6 @@
};
/**
- * Check that ro.boot.vbmeta.device_state is not "locked" or ro.boot.verifiedbootstate
- * 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) {
- auto challenge = randomBytes(MAX_CHALLENGE_SIZE);
- bytevec csr;
- auto status =
- provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
- ASSERT_TRUE(status.isOk()) << status.getDescription();
-
- auto isProper = isCsrWithProperDiceChain(csr, GetParam());
- ASSERT_TRUE(isProper) << isProper.message();
- if (!*isProper) {
- GTEST_SKIP() << "Skipping test: Only a proper DICE chain has a mode set.";
- }
-
- auto nonNormalMode = hasNonNormalModeInDiceChain(csr, GetParam());
- ASSERT_TRUE(nonNormalMode) << nonNormalMode.message();
-
- auto deviceState = ::android::base::GetProperty("ro.boot.vbmeta.device_state", "");
- auto verifiedBootState = ::android::base::GetProperty("ro.boot.verifiedbootstate", "");
-
- ASSERT_EQ(deviceState != "locked" || verifiedBootState != "green", *nonNormalMode)
- << "ro.boot.vbmeta.device_state = '" << deviceState
- << "' and ro.boot.verifiedbootstate = '" << verifiedBootState << "', but it is "
- << *nonNormalMode
- << " that the DICE chain has a certificate with a non-normal mode set.";
-}
-
-/**
* Generate an empty certificate request with all possible length of challenge, and decrypt and
* verify the structure and content.
*/
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 2b39bc6..59d9593 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -100,7 +100,9 @@
ASSERT_TRUE(mFilterTests.configFilter(filterReconf.settings, filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
- ASSERT_TRUE(mFilterTests.startIdTest(filterId));
+ if (!isPassthroughFilter(filterReconf)) {
+ ASSERT_TRUE(mFilterTests.startIdTest(filterId));
+ }
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@@ -152,7 +154,9 @@
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
- ASSERT_TRUE(filterDataOutputTest());
+ if (!isPassthroughFilter(filterConf)) {
+ ASSERT_TRUE(filterDataOutputTest());
+ }
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@@ -1377,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/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index be9b996..5fdc3dc 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -89,6 +89,28 @@
sectionFilterIds.clear();
}
+bool isPassthroughFilter(FilterConfig filterConfig) {
+ auto type = filterConfig.type;
+ if (type.mainType == DemuxFilterMainType::TS) {
+ auto subType = type.subType.get<DemuxFilterSubType::Tag::tsFilterType>();
+ if (subType == DemuxTsFilterType::AUDIO || subType == DemuxTsFilterType::VIDEO) {
+ auto tsFilterSettings = filterConfig.settings.get<DemuxFilterSettings::Tag::ts>();
+ auto avSettings = tsFilterSettings.filterSettings
+ .get<DemuxTsFilterSettingsFilterSettings::Tag::av>();
+ return avSettings.isPassthrough;
+ }
+ } else if (filterConfig.type.mainType != DemuxFilterMainType::MMTP) {
+ auto subType = type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>();
+ if (subType == DemuxMmtpFilterType::AUDIO || subType == DemuxMmtpFilterType::VIDEO) {
+ auto mmtpFilterSettings = filterConfig.settings.get<DemuxFilterSettings::Tag::mmtp>();
+ auto avSettings = mmtpFilterSettings.filterSettings
+ .get<DemuxMmtpFilterSettingsFilterSettings::Tag::av>();
+ return avSettings.isPassthrough;
+ }
+ }
+ return false;
+}
+
enum class Dataflow_Context { LNBRECORD, RECORD, DESCRAMBLING, LNBDESCRAMBLING };
class TunerLnbAidlTest : public testing::TestWithParam<std::string> {
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!();