Merge "Create a snapshot of the hardware_legacy"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 563ee62..691cf34 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -117,6 +117,8 @@
"android/hardware/audio/core/IStreamIn.aidl",
"android/hardware/audio/core/IStreamOut.aidl",
"android/hardware/audio/core/ITelephony.aidl",
+ "android/hardware/audio/core/MicrophoneDynamicInfo.aidl",
+ "android/hardware/audio/core/MicrophoneInfo.aidl",
"android/hardware/audio/core/MmapBufferDescriptor.aidl",
"android/hardware/audio/core/ModuleDebug.aidl",
"android/hardware/audio/core/StreamDescriptor.aidl",
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
new file mode 100644
index 0000000..6473d23
--- /dev/null
+++ b/audio/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalAudioCoreTargetTest"
+ }
+ ]
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index 7f960e0..0c7ca27 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -56,6 +56,7 @@
void setMasterVolume(float volume);
boolean getMicMute();
void setMicMute(boolean mute);
+ android.hardware.audio.core.MicrophoneInfo[] getMicrophones();
void updateAudioMode(android.hardware.audio.core.AudioMode mode);
void updateScreenRotation(android.hardware.audio.core.IModule.ScreenRotation rotation);
void updateScreenState(boolean isTurnedOn);
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
index d5ab3e8..e9c727f 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
@@ -35,5 +35,20 @@
@VintfStability
interface IStreamIn {
void close();
+ android.hardware.audio.core.MicrophoneDynamicInfo[] getActiveMicrophones();
+ android.hardware.audio.core.IStreamIn.MicrophoneDirection getMicrophoneDirection();
+ void setMicrophoneDirection(android.hardware.audio.core.IStreamIn.MicrophoneDirection direction);
+ float getMicrophoneFieldDimension();
+ void setMicrophoneFieldDimension(float zoom);
void updateMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+ const int MIC_FIELD_DIMENSION_WIDE_ANGLE = -1;
+ const int MIC_FIELD_DIMENSION_NO_ZOOM = 0;
+ const int MIC_FIELD_DIMENSION_MAX_ZOOM = 1;
+ @Backing(type="int") @VintfStability
+ enum MicrophoneDirection {
+ UNSPECIFIED = 0,
+ FRONT = 1,
+ BACK = 2,
+ EXTERNAL = 3,
+ }
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneDynamicInfo.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneDynamicInfo.aidl
new file mode 100644
index 0000000..50a5528
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneDynamicInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable MicrophoneDynamicInfo {
+ @utf8InCpp String id;
+ android.hardware.audio.core.MicrophoneDynamicInfo.ChannelMapping[] channelMapping;
+ @Backing(type="int") @VintfStability
+ enum ChannelMapping {
+ UNUSED = 0,
+ DIRECT = 1,
+ PROCESSED = 2,
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneInfo.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneInfo.aidl
new file mode 100644
index 0000000..68c7f88
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MicrophoneInfo.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable MicrophoneInfo {
+ @utf8InCpp String id;
+ android.media.audio.common.AudioDevice device;
+ android.hardware.audio.core.MicrophoneInfo.Location location = android.hardware.audio.core.MicrophoneInfo.Location.UNKNOWN;
+ int group = -1;
+ int indexInTheGroup = -1;
+ @nullable android.hardware.audio.core.MicrophoneInfo.Sensitivity sensitivity;
+ android.hardware.audio.core.MicrophoneInfo.Directionality directionality = android.hardware.audio.core.MicrophoneInfo.Directionality.UNKNOWN;
+ android.hardware.audio.core.MicrophoneInfo.FrequencyResponsePoint[] frequencyResponse;
+ @nullable android.hardware.audio.core.MicrophoneInfo.Coordinate position;
+ @nullable android.hardware.audio.core.MicrophoneInfo.Coordinate orientation;
+ const int GROUP_UNKNOWN = -1;
+ const int INDEX_IN_THE_GROUP_UNKNOWN = -1;
+ @Backing(type="int") @VintfStability
+ enum Location {
+ UNKNOWN = 0,
+ MAINBODY = 1,
+ MAINBODY_MOVABLE = 2,
+ PERIPHERAL = 3,
+ }
+ @VintfStability
+ parcelable Sensitivity {
+ float leveldBFS;
+ float maxSpldB;
+ float minSpldB;
+ }
+ @Backing(type="int") @VintfStability
+ enum Directionality {
+ UNKNOWN = 0,
+ OMNI = 1,
+ BI_DIRECTIONAL = 2,
+ CARDIOID = 3,
+ HYPER_CARDIOID = 4,
+ SUPER_CARDIOID = 5,
+ }
+ @VintfStability
+ parcelable FrequencyResponsePoint {
+ float frequencyHz;
+ float leveldB;
+ }
+ @VintfStability
+ parcelable Coordinate {
+ float x;
+ float y;
+ float z;
+ }
+}
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 974e7e8..786d5ee 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -25,6 +25,7 @@
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
import android.hardware.audio.core.ITelephony;
+import android.hardware.audio.core.MicrophoneInfo;
import android.hardware.audio.core.ModuleDebug;
import android.hardware.audio.core.StreamDescriptor;
import android.media.audio.common.AudioOffloadInfo;
@@ -605,6 +606,22 @@
void setMicMute(boolean mute);
/**
+ * Provide information describing built-in microphones of the HAL module.
+ *
+ * If there are no built-in microphones in the HAL module, it must return an
+ * empty vector. If there are microphones, but the HAL module does not
+ * possess the required information about them, EX_UNSUPPORTED_OPERATION
+ * must be thrown.
+ *
+ * If this method is supported by the HAL module, it must also support
+ * 'IStreamIn.getActiveMicrophones' method.
+ *
+ * @return The vector with information about each microphone.
+ * @throws EX_UNSUPPORTED_OPERATION If the information is unavailable.
+ */
+ MicrophoneInfo[] getMicrophones();
+
+ /**
* Notify the HAL module on the change of the current audio mode.
*
* The current audio mode is always controlled by the client. This is an
diff --git a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
index 0c3e3d1..0b6e02c 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
@@ -17,6 +17,7 @@
package android.hardware.audio.core;
import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.core.MicrophoneDynamicInfo;
/**
* This interface provides means for receiving audio data from input devices.
@@ -39,6 +40,92 @@
void close();
/**
+ * Provides information on the microphones that are active for this stream.
+ *
+ * The returned array contains dynamic information on the microphones which
+ * are active for this stream. Each entry in the returned array must have a
+ * corresponding entry (matched by the 'MicrophoneInfo.id' field value) in
+ * the list of all available microphones which is provided by the
+ * 'IModule.getMicrophones' method.
+ *
+ * This method must be supported by the HAL module if
+ * 'IModule.getMicrophones' is supported.
+ *
+ * @return The vector with dynamic information on the microphones.
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the information is unavailable.
+ */
+ MicrophoneDynamicInfo[] getActiveMicrophones();
+
+ @VintfStability
+ @Backing(type="int")
+ enum MicrophoneDirection {
+ /**
+ * Don't do any directionality processing of the activated microphone(s).
+ */
+ UNSPECIFIED = 0,
+ /**
+ * Optimize capture for audio coming from the screen-side of the device.
+ */
+ FRONT = 1,
+ /**
+ * Optimize capture for audio coming from the side of the device opposite the screen.
+ */
+ BACK = 2,
+ /**
+ * Optimize capture for audio coming from an off-device microphone.
+ */
+ EXTERNAL = 3,
+ }
+ /**
+ * Get the current logical microphone direction.
+ *
+ * @return The current logical microphone direction.
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the information is unavailable.
+ */
+ MicrophoneDirection getMicrophoneDirection();
+ /**
+ * Set the current logical microphone direction.
+ *
+ * The client sets this parameter in order to specify its preference for
+ * optimizing the direction of capture when multiple microphones are in use.
+ *
+ * @param direction The preferred capture direction.
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the operation is not supported.
+ */
+ void setMicrophoneDirection(MicrophoneDirection direction);
+
+ const int MIC_FIELD_DIMENSION_WIDE_ANGLE = -1;
+ const int MIC_FIELD_DIMENSION_NO_ZOOM = 0;
+ const int MIC_FIELD_DIMENSION_MAX_ZOOM = 1;
+ /**
+ * Get the "zoom factor" for the logical microphone.
+ *
+ * The returned value must be within the range of [-1.0, 1.0] (see
+ * MIC_FIELD_DIMENSION_* constants).
+ *
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the information is unavailable.
+ */
+ float getMicrophoneFieldDimension();
+ /**
+ * Set the "zoom factor" for the logical microphone.
+ *
+ * If multiple microphones are in use, the provided zoom factor must be
+ * treated as a preference for their combined field dimension. The zoom
+ * factor must be within the range of [-1.0, 1.0] (see MIC_FIELD_DIMENSION_*
+ * constants).
+ *
+ * @param zoom The preferred field dimension of the microphone capture.
+ * @throws EX_ILLEGAL_ARGUMENT If the dimension value is outside of the range.
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @throws EX_UNSUPPORTED_OPERATION If the operation is not supported.
+ */
+ void setMicrophoneFieldDimension(float zoom);
+
+ /**
* Update stream metadata.
*
* Updates the metadata initially provided at the stream creation.
diff --git a/audio/aidl/android/hardware/audio/core/MicrophoneDynamicInfo.aidl b/audio/aidl/android/hardware/audio/core/MicrophoneDynamicInfo.aidl
new file mode 100644
index 0000000..36cc51f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/MicrophoneDynamicInfo.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+/**
+ * Structure providing dynamic information on a microphone. This information
+ * changes between recording sessions.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable MicrophoneDynamicInfo {
+ /**
+ * Unique alphanumeric id for the microphone. It must match the id of one of
+ * the 'MicrophoneInfo' entries returned by 'IModule.getMicrophones'.
+ */
+ @utf8InCpp String id;
+
+ @VintfStability
+ @Backing(type="int")
+ enum ChannelMapping {
+ /** Channel not used. */
+ UNUSED = 0,
+ /** Channel is used and the signal is not processed. */
+ DIRECT = 1,
+ /** Channel is used and the signal has some processing. */
+ PROCESSED = 2,
+ }
+ /**
+ * The vector is indexes by zero-based channels of the microphone, thus the
+ * element '0' corresponds to the first channel, '1' is the second, etc. The
+ * vector must contain at least 1 element.
+ */
+ ChannelMapping[] channelMapping;
+}
diff --git a/audio/aidl/android/hardware/audio/core/MicrophoneInfo.aidl b/audio/aidl/android/hardware/audio/core/MicrophoneInfo.aidl
new file mode 100644
index 0000000..3b8c7f3
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/MicrophoneInfo.aidl
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+import android.media.audio.common.AudioDevice;
+
+/**
+ * Structure providing static information on a microphone. This information
+ * never changes during the lifetime of the IModule which owns the microphone.
+ * The information presented in this structure indicates the location and
+ * orientation of the microphone on the device as well as useful information
+ * like frequency response and sensitivity.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable MicrophoneInfo {
+ /**
+ * Unique alphanumeric id for the microphone. It must remain the same across
+ * device reboots. The client must never attempt to parse the value of this
+ * field.
+ */
+ @utf8InCpp String id;
+ /**
+ * Describes the location of the microphone in terms of managed audio devices.
+ */
+ AudioDevice device;
+
+ @VintfStability
+ @Backing(type="int")
+ enum Location {
+ /** Microphone location is unknown. */
+ UNKNOWN = 0,
+ /** The microphone is located on the main body of the device. */
+ MAINBODY = 1,
+ /** The microphone is located on a movable main body of the device. */
+ MAINBODY_MOVABLE = 2,
+ /** The microphone is located on a peripheral. */
+ PERIPHERAL = 3,
+ }
+ /** Location of the microphone in regard to the body of the device */
+ Location location = Location.UNKNOWN;
+
+ /**
+ * This value is used when the group of the microphone is unknown.
+ */
+ const int GROUP_UNKNOWN = -1;
+ /**
+ * An identifier to group related microphones together, for example,
+ * microphones of a microphone array should all belong to the same group.
+ * Note that microphones assigned to 'GROUP_UNKNOWN' do not form a group.
+ */
+ int group = GROUP_UNKNOWN;
+ /**
+ * This value is used when the index in the group of the microphone is
+ * unknown.
+ */
+ const int INDEX_IN_THE_GROUP_UNKNOWN = -1;
+ /**
+ * Index of this microphone within the group. The pair (group, index) must
+ * be unique within the same HAL module, except the pair
+ * (GROUP_UNKNOWN, INDEX_IN_THE_GROUP_UNKNOWN).
+ */
+ int indexInTheGroup = INDEX_IN_THE_GROUP_UNKNOWN;
+
+ @VintfStability
+ parcelable Sensitivity {
+ /** Level in dBFS produced by a 1000 Hz tone at 94 dB SPL. */
+ float leveldBFS;
+ /** Level in dB of the max SPL supported at 1000 Hz */
+ float maxSpldB;
+ /** Level in dB of the min SPL supported at 1000 Hz */
+ float minSpldB;
+ }
+ /**
+ * If provided, must describe acceptable sound pressure levels (SPL)
+ * for a 1 kHz sine wave, and the resulting level in dBFS.
+ */
+ @nullable Sensitivity sensitivity;
+
+ @VintfStability
+ @Backing(type="int")
+ enum Directionality {
+ UNKNOWN = 0,
+ OMNI = 1,
+ BI_DIRECTIONAL = 2,
+ CARDIOID = 3,
+ HYPER_CARDIOID = 4,
+ SUPER_CARDIOID = 5,
+ }
+ /**
+ * The standard polar pattern of the microphone.
+ */
+ Directionality directionality = Directionality.UNKNOWN;
+
+ /**
+ * A (frequency, level) pair. Used to represent frequency response.
+ */
+ @VintfStability
+ parcelable FrequencyResponsePoint {
+ float frequencyHz;
+ float leveldB;
+ }
+ /**
+ * Vector with ordered frequency responses (from low to high frequencies)
+ * with the frequency response of the microphone. Levels are in dB,
+ * relative to level at 1000 Hz.
+ */
+ FrequencyResponsePoint[] frequencyResponse;
+
+ /**
+ * A 3D point used to represent position or orientation of a microphone.
+ */
+ @VintfStability
+ parcelable Coordinate {
+ float x;
+ float y;
+ float z;
+ }
+ /**
+ * If provided, must specify distances of the microphone's capsule, in
+ * meters, from the bottom-left-back corner of the bounding box of device in
+ * its natural orientation (PORTRAIT for phones, LANDSCAPE for tablets, TVs,
+ * etc).
+ */
+ @nullable Coordinate position;
+ /**
+ * If provided, describes the normalized point which defines the main
+ * orientation of the microphone's capsule.
+ * Magnitude = sqrt(x^2 + y^2 + z^2) = 1.
+ */
+ @nullable Coordinate orientation;
+}
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index a3e5ff7..280814f 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -243,6 +243,13 @@
AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
+ MicrophoneInfo mic;
+ mic.id = "zero";
+ mic.device = zeroInDevice.ext.get<AudioPortExt::Tag::device>().device;
+ mic.group = 0;
+ mic.indexInTheGroup = 0;
+ c.microphones = std::vector<MicrophoneInfo>{mic};
+
AudioPort primaryInMix =
createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
primaryInMix.profiles.push_back(
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 9dbd61c..1e561d4 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -31,6 +31,7 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
@@ -136,7 +137,8 @@
StreamContext temp(
std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
- frameSize, std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
+ portConfigIt->format.value(), portConfigIt->channelMask.value(),
+ std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
asyncCallback, mDebug.streamTransientStateDelayMs);
if (temp.isValid()) {
*out_context = std::move(temp);
@@ -149,6 +151,39 @@
return ndk::ScopedAStatus::ok();
}
+std::vector<AudioDevice> Module::findConnectedDevices(int32_t portConfigId) {
+ std::vector<AudioDevice> result;
+ auto& ports = getConfig().ports;
+ auto portIds = portIdsFromPortConfigIds(findConnectedPortConfigIds(portConfigId));
+ for (auto it = portIds.begin(); it != portIds.end(); ++it) {
+ auto portIt = findById<AudioPort>(ports, *it);
+ if (portIt != ports.end() && portIt->ext.getTag() == AudioPortExt::Tag::device) {
+ result.push_back(portIt->ext.template get<AudioPortExt::Tag::device>().device);
+ }
+ }
+ return result;
+}
+
+std::set<int32_t> Module::findConnectedPortConfigIds(int32_t portConfigId) {
+ std::set<int32_t> result;
+ auto patchIdsRange = mPatches.equal_range(portConfigId);
+ auto& patches = getConfig().patches;
+ for (auto it = patchIdsRange.first; it != patchIdsRange.second; ++it) {
+ auto patchIt = findById<AudioPatch>(patches, it->second);
+ if (patchIt == patches.end()) {
+ LOG(FATAL) << __func__ << ": patch with id " << it->second << " taken from mPatches "
+ << "not found in the configuration";
+ }
+ if (std::find(patchIt->sourcePortConfigIds.begin(), patchIt->sourcePortConfigIds.end(),
+ portConfigId) != patchIt->sourcePortConfigIds.end()) {
+ result.insert(patchIt->sinkPortConfigIds.begin(), patchIt->sinkPortConfigIds.end());
+ } else {
+ result.insert(patchIt->sourcePortConfigIds.begin(), patchIt->sourcePortConfigIds.end());
+ }
+ }
+ return result;
+}
+
ndk::ScopedAStatus Module::findPortIdForNewStream(int32_t in_portConfigId, AudioPort** port) {
auto& configs = getConfig().portConfigs;
auto portConfigIt = findById<AudioPortConfig>(configs, in_portConfigId);
@@ -187,6 +222,19 @@
return ndk::ScopedAStatus::ok();
}
+template <typename C>
+std::set<int32_t> Module::portIdsFromPortConfigIds(C portConfigIds) {
+ std::set<int32_t> result;
+ auto& portConfigs = getConfig().portConfigs;
+ for (auto it = portConfigIds.begin(); it != portConfigIds.end(); ++it) {
+ auto portConfigIt = findById<AudioPortConfig>(portConfigs, *it);
+ if (portConfigIt != portConfigs.end()) {
+ result.insert(portConfigIt->portId);
+ }
+ }
+ return result;
+}
+
internal::Configuration& Module::getConfig() {
if (!mConfig) {
mConfig.reset(new internal::Configuration(internal::getNullPrimaryConfiguration()));
@@ -223,12 +271,16 @@
idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end());
std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) {
if (idsToConnect.count(portConfigId) == 0) {
- mStreams.setStreamIsConnected(portConfigId, false);
+ LOG(DEBUG) << "The stream on port config id " << portConfigId << " is not connected";
+ mStreams.setStreamIsConnected(portConfigId, {});
}
});
std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) {
if (idsToDisconnect.count(portConfigId) == 0) {
- mStreams.setStreamIsConnected(portConfigId, true);
+ const auto connectedDevices = findConnectedDevices(portConfigId);
+ LOG(DEBUG) << "The stream on port config id " << portConfigId
+ << " is connected to: " << ::android::internal::ToString(connectedDevices);
+ mStreams.setStreamIsConnected(portConfigId, connectedDevices);
}
});
}
@@ -468,14 +520,15 @@
return status;
}
context.fillDescriptor(&_aidl_return->desc);
- auto stream = ndk::SharedRefBase::make<StreamIn>(in_args.sinkMetadata, std::move(context));
+ auto stream = ndk::SharedRefBase::make<StreamIn>(in_args.sinkMetadata, std::move(context),
+ mConfig->microphones);
if (auto status = stream->init(); !status.isOk()) {
return status;
}
StreamWrapper streamWrapper(stream);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
- streamWrapper.setStreamIsConnected(true);
+ streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
}
mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
_aidl_return->stream = std::move(stream);
@@ -525,7 +578,7 @@
StreamWrapper streamWrapper(stream);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
- streamWrapper.setStreamIsConnected(true);
+ streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
}
mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
_aidl_return->stream = std::move(stream);
@@ -844,6 +897,12 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::getMicrophones(std::vector<MicrophoneInfo>* _aidl_return) {
+ *_aidl_return = mConfig->microphones;
+ LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Module::updateAudioMode(AudioMode in_mode) {
// No checks for supported audio modes here, it's an informative notification.
LOG(DEBUG) << __func__ << ": " << toString(in_mode);
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index d7c352f..be5887c 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -18,12 +18,17 @@
#include <android-base/logging.h>
#include <utils/SystemClock.h>
+#include <Utils.h>
+
#include "core-impl/Module.h"
#include "core-impl/Stream.h"
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioOffloadInfo;
+using android::hardware::audio::common::getChannelCount;
+using android::hardware::audio::common::getFrameSizeInBytes;
namespace aidl::android::hardware::audio::core {
@@ -35,13 +40,17 @@
desc->reply = mReplyMQ->dupeDesc();
}
if (mDataMQ) {
- desc->frameSizeBytes = mFrameSize;
- desc->bufferSizeFrames =
- mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / mFrameSize;
+ const size_t frameSize = getFrameSize();
+ desc->frameSizeBytes = frameSize;
+ desc->bufferSizeFrames = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / frameSize;
desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
}
}
+size_t StreamContext::getFrameSize() const {
+ return getFrameSizeInBytes(mFormat, mChannelLayout);
+}
+
bool StreamContext::isValid() const {
if (mCommandMQ && !mCommandMQ->isValid()) {
LOG(ERROR) << "command FMQ is invalid";
@@ -51,8 +60,8 @@
LOG(ERROR) << "reply FMQ is invalid";
return false;
}
- if (mFrameSize == 0) {
- LOG(ERROR) << "frame size is not set";
+ if (getFrameSize() == 0) {
+ LOG(ERROR) << "frame size is invalid";
return false;
}
if (mDataMQ && !mDataMQ->isValid()) {
@@ -530,11 +539,64 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
-StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext context)
- : StreamCommon<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)) {
+namespace {
+static std::map<AudioDevice, std::string> transformMicrophones(
+ const std::vector<MicrophoneInfo>& microphones) {
+ std::map<AudioDevice, std::string> result;
+ std::transform(microphones.begin(), microphones.end(), std::inserter(result, result.begin()),
+ [](const auto& mic) { return std::make_pair(mic.device, mic.id); });
+ return result;
+}
+} // namespace
+
+StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext context,
+ const std::vector<MicrophoneInfo>& microphones)
+ : StreamCommon<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)),
+ mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
+ndk::ScopedAStatus StreamIn::getActiveMicrophones(
+ std::vector<MicrophoneDynamicInfo>* _aidl_return) {
+ std::vector<MicrophoneDynamicInfo> result;
+ std::vector<MicrophoneDynamicInfo::ChannelMapping> channelMapping{
+ getChannelCount(mContext.getChannelLayout()),
+ MicrophoneDynamicInfo::ChannelMapping::DIRECT};
+ for (auto it = mConnectedDevices.begin(); it != mConnectedDevices.end(); ++it) {
+ if (auto micIt = mMicrophones.find(*it); micIt != mMicrophones.end()) {
+ MicrophoneDynamicInfo dynMic;
+ dynMic.id = micIt->second;
+ dynMic.channelMapping = channelMapping;
+ result.push_back(std::move(dynMic));
+ }
+ }
+ *_aidl_return = std::move(result);
+ LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamIn::getMicrophoneDirection(MicrophoneDirection* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamIn::setMicrophoneDirection(MicrophoneDirection in_direction) {
+ LOG(DEBUG) << __func__ << ": direction " << toString(in_direction);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamIn::getMicrophoneFieldDimension(float* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamIn::setMicrophoneFieldDimension(float in_zoom) {
+ LOG(DEBUG) << __func__ << ": zoom " << in_zoom;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext context,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamCommon<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h
index d5cd30b..95adcd7 100644
--- a/audio/aidl/default/include/core-impl/Configuration.h
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -21,12 +21,14 @@
#include <aidl/android/hardware/audio/core/AudioPatch.h>
#include <aidl/android/hardware/audio/core/AudioRoute.h>
+#include <aidl/android/hardware/audio/core/MicrophoneInfo.h>
#include <aidl/android/media/audio/common/AudioPort.h>
#include <aidl/android/media/audio/common/AudioPortConfig.h>
namespace aidl::android::hardware::audio::core::internal {
struct Configuration {
+ std::vector<MicrophoneInfo> microphones;
std::vector<::aidl::android::media::audio::common::AudioPort> ports;
std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index f7b85ed..3509327 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -77,6 +77,7 @@
ndk::ScopedAStatus setMasterVolume(float in_volume) override;
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
+ ndk::ScopedAStatus getMicrophones(std::vector<MicrophoneInfo>* _aidl_return) override;
ndk::ScopedAStatus updateAudioMode(
::aidl::android::hardware::audio::core::AudioMode in_mode) override;
ndk::ScopedAStatus updateScreenRotation(
@@ -88,9 +89,14 @@
int32_t in_portConfigId, int64_t in_bufferSizeFrames,
std::shared_ptr<IStreamCallback> asyncCallback,
::aidl::android::hardware::audio::core::StreamContext* out_context);
+ std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
+ int32_t portConfigId);
+ std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
internal::Configuration& getConfig();
+ template <typename C>
+ std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
void registerPatch(const AudioPatch& patch);
void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 3c96973..7a07eeb 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -30,7 +30,9 @@
#include <aidl/android/hardware/audio/core/BnStreamIn.h>
#include <aidl/android/hardware/audio/core/BnStreamOut.h>
#include <aidl/android/hardware/audio/core/IStreamCallback.h>
+#include <aidl/android/hardware/audio/core/MicrophoneInfo.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
#include <fmq/AidlMessageQueue.h>
#include <system/thread_defs.h>
@@ -61,12 +63,15 @@
StreamContext() = default;
StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
- size_t frameSize, std::unique_ptr<DataMQ> dataMQ,
- std::shared_ptr<IStreamCallback> asyncCallback, int transientStateDelayMs)
+ const ::aidl::android::media::audio::common::AudioFormatDescription& format,
+ const ::aidl::android::media::audio::common::AudioChannelLayout& channelLayout,
+ std::unique_ptr<DataMQ> dataMQ, std::shared_ptr<IStreamCallback> asyncCallback,
+ int transientStateDelayMs)
: mCommandMQ(std::move(commandMQ)),
mInternalCommandCookie(std::rand()),
mReplyMQ(std::move(replyMQ)),
- mFrameSize(frameSize),
+ mFormat(format),
+ mChannelLayout(channelLayout),
mDataMQ(std::move(dataMQ)),
mAsyncCallback(asyncCallback),
mTransientStateDelayMs(transientStateDelayMs) {}
@@ -74,7 +79,8 @@
: mCommandMQ(std::move(other.mCommandMQ)),
mInternalCommandCookie(other.mInternalCommandCookie),
mReplyMQ(std::move(other.mReplyMQ)),
- mFrameSize(other.mFrameSize),
+ mFormat(other.mFormat),
+ mChannelLayout(other.mChannelLayout),
mDataMQ(std::move(other.mDataMQ)),
mAsyncCallback(other.mAsyncCallback),
mTransientStateDelayMs(other.mTransientStateDelayMs) {}
@@ -82,7 +88,8 @@
mCommandMQ = std::move(other.mCommandMQ);
mInternalCommandCookie = other.mInternalCommandCookie;
mReplyMQ = std::move(other.mReplyMQ);
- mFrameSize = other.mFrameSize;
+ mFormat = std::move(other.mFormat);
+ mChannelLayout = std::move(other.mChannelLayout);
mDataMQ = std::move(other.mDataMQ);
mAsyncCallback = other.mAsyncCallback;
mTransientStateDelayMs = other.mTransientStateDelayMs;
@@ -91,9 +98,15 @@
void fillDescriptor(StreamDescriptor* desc);
std::shared_ptr<IStreamCallback> getAsyncCallback() const { return mAsyncCallback; }
+ ::aidl::android::media::audio::common::AudioChannelLayout getChannelLayout() const {
+ return mChannelLayout;
+ }
CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
DataMQ* getDataMQ() const { return mDataMQ.get(); }
- size_t getFrameSize() const { return mFrameSize; }
+ ::aidl::android::media::audio::common::AudioFormatDescription getFormat() const {
+ return mFormat;
+ }
+ size_t getFrameSize() const;
int getInternalCommandCookie() const { return mInternalCommandCookie; }
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
int getTransientStateDelayMs() const { return mTransientStateDelayMs; }
@@ -104,7 +117,8 @@
std::unique_ptr<CommandMQ> mCommandMQ;
int mInternalCommandCookie; // The value used to confirm that the command was posted internally
std::unique_ptr<ReplyMQ> mReplyMQ;
- size_t mFrameSize;
+ ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
+ ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
std::unique_ptr<DataMQ> mDataMQ;
std::shared_ptr<IStreamCallback> mAsyncCallback;
int mTransientStateDelayMs;
@@ -193,7 +207,11 @@
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
bool isClosed() const { return mWorker.isClosed(); }
- void setIsConnected(bool connected) { mWorker.setIsConnected(connected); }
+ void setIsConnected(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ mWorker.setIsConnected(!devices.empty());
+ mConnectedDevices = devices;
+ }
ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
protected:
@@ -205,6 +223,7 @@
Metadata mMetadata;
StreamContext mContext;
StreamWorker mWorker;
+ std::vector<::aidl::android::media::audio::common::AudioDevice> mConnectedDevices;
};
class StreamIn
@@ -214,6 +233,12 @@
return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
StreamInWorker>::close();
}
+ ndk::ScopedAStatus getActiveMicrophones(
+ std::vector<MicrophoneDynamicInfo>* _aidl_return) override;
+ ndk::ScopedAStatus getMicrophoneDirection(MicrophoneDirection* _aidl_return) override;
+ ndk::ScopedAStatus setMicrophoneDirection(MicrophoneDirection in_direction) override;
+ ndk::ScopedAStatus getMicrophoneFieldDimension(float* _aidl_return) override;
+ ndk::ScopedAStatus setMicrophoneFieldDimension(float in_zoom) override;
ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
in_sinkMetadata) override {
return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
@@ -222,7 +247,10 @@
public:
StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext context);
+ StreamContext context, const std::vector<MicrophoneInfo>& microphones);
+
+ private:
+ const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
class StreamOut : public StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
@@ -261,11 +289,12 @@
},
mStream);
}
- void setStreamIsConnected(bool connected) {
+ void setStreamIsConnected(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
std::visit(
[&](auto&& ws) {
auto s = ws.lock();
- if (s) s->setIsConnected(connected);
+ if (s) s->setIsConnected(devices);
},
mStream);
}
@@ -288,9 +317,11 @@
mStreams.insert(std::pair{portConfigId, sw});
mStreams.insert(std::pair{portId, std::move(sw)});
}
- void setStreamIsConnected(int32_t portConfigId, bool connected) {
+ void setStreamIsConnected(
+ int32_t portConfigId,
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
if (auto it = mStreams.find(portConfigId); it != mStreams.end()) {
- it->second.setStreamIsConnected(connected);
+ it->second.setStreamIsConnected(devices);
}
}
diff --git a/audio/aidl/vts/AudioHalBinderServiceUtil.h b/audio/aidl/vts/AudioHalBinderServiceUtil.h
index c8d81b1..b4b4632 100644
--- a/audio/aidl/vts/AudioHalBinderServiceUtil.h
+++ b/audio/aidl/vts/AudioHalBinderServiceUtil.h
@@ -31,7 +31,7 @@
public:
ndk::SpAIBinder connectToService(const std::string& serviceName) {
mServiceName = serviceName;
- mBinder = ndk::SpAIBinder(AServiceManager_getService(serviceName.c_str()));
+ mBinder = ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str()));
if (mBinder == nullptr) {
LOG(ERROR) << "Failed to get service " << serviceName;
} else {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index c081402..7e4b148 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -28,6 +28,7 @@
using aidl::android::hardware::audio::core::IModule;
using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioEncapsulationMode;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
@@ -62,6 +63,18 @@
return {};
}
+// static
+std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
+ const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
+ std::vector<AudioPort> result;
+ std::copy_if(ports.begin(), ports.end(), std::back_inserter(result), [](const auto& port) {
+ const auto type = port.ext.template get<AudioPortExt::Tag::device>().device.type;
+ return type.connection.empty() && (type.type == AudioDeviceType::IN_MICROPHONE ||
+ type.type == AudioDeviceType::IN_MICROPHONE_BACK);
+ });
+ return result;
+}
+
template <typename T>
auto findById(const std::vector<T>& v, int32_t id) {
return std::find_if(v.begin(), v.end(), [&](const auto& p) { return p.id == id; });
@@ -107,38 +120,45 @@
return result;
}
-std::vector<AudioPort> ModuleConfig::getInputMixPorts() const {
+std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool attachedOnly) const {
std::vector<AudioPort> result;
- std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+ std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
return port.ext.getTag() == AudioPortExt::Tag::mix &&
- port.flags.getTag() == AudioIoFlags::Tag::input;
+ port.flags.getTag() == AudioIoFlags::Tag::input &&
+ (!attachedOnly || !getAttachedSourceDevicesPortsForMixPort(port).empty());
});
return result;
}
-std::vector<AudioPort> ModuleConfig::getOutputMixPorts() const {
+std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool attachedOnly) const {
std::vector<AudioPort> result;
- std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+ std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
return port.ext.getTag() == AudioPortExt::Tag::mix &&
- port.flags.getTag() == AudioIoFlags::Tag::output;
+ port.flags.getTag() == AudioIoFlags::Tag::output &&
+ (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
});
return result;
}
std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool attachedOnly,
bool singlePort) const {
- return findMixPorts(false /*isInput*/, singlePort, [&](const AudioPort& port) {
+ return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
- AudioOutputFlags::NON_BLOCKING) &&
- (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+ AudioOutputFlags::NON_BLOCKING);
});
}
std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
- return findMixPorts(false /*isInput*/, singlePort, [&](const AudioPort& port) {
+ return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
- AudioOutputFlags::COMPRESS_OFFLOAD) &&
- (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+ AudioOutputFlags::COMPRESS_OFFLOAD);
+ });
+}
+
+std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool attachedOnly, bool singlePort) const {
+ return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+ return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::PRIMARY);
});
}
@@ -193,7 +213,7 @@
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
bool isInput) const {
- const auto mixPorts = getMixPorts(isInput);
+ const auto mixPorts = getMixPorts(isInput, false /*attachedOnly*/);
std::set<std::pair<int32_t, int32_t>> allowedRoutes;
for (const auto& route : mRoutes) {
for (const auto srcPortId : route.sourcePortIds) {
@@ -344,9 +364,10 @@
}
std::vector<AudioPort> ModuleConfig::findMixPorts(
- bool isInput, bool singlePort, std::function<bool(const AudioPort&)> pred) const {
+ bool isInput, bool attachedOnly, bool singlePort,
+ const std::function<bool(const AudioPort&)>& pred) const {
std::vector<AudioPort> result;
- const auto mixPorts = getMixPorts(isInput);
+ const auto mixPorts = getMixPorts(isInput, attachedOnly);
for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
if (mixPortIt == mixPorts.end()) break;
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index a85aa7f..7247f3b 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -37,22 +37,32 @@
static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
generateOffloadInfoIfNeeded(
const aidl::android::media::audio::common::AudioPortConfig& portConfig);
+ static std::vector<aidl::android::media::audio::common::AudioPort> getBuiltInMicPorts(
+ const std::vector<aidl::android::media::audio::common::AudioPort>& ports);
explicit ModuleConfig(aidl::android::hardware::audio::core::IModule* module);
const ndk::ScopedAStatus& getStatus() const { return mStatus; }
std::string getError() const { return mStatus.getMessage(); }
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
+ std::vector<aidl::android::media::audio::common::AudioPort> getAttachedMicrophonePorts() const {
+ return getBuiltInMicPorts(getAttachedDevicePorts());
+ }
std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
- std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts() const;
- std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts() const;
- std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
- return isInput ? getInputMixPorts() : getOutputMixPorts();
+ std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts(
+ bool attachedOnly) const;
+ std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts(
+ bool attachedOnly) const;
+ std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(
+ bool isInput, bool attachedOnly) const {
+ return isInput ? getInputMixPorts(attachedOnly) : getOutputMixPorts(attachedOnly);
}
std::vector<aidl::android::media::audio::common::AudioPort> getNonBlockingMixPorts(
bool attachedOnly, bool singlePort) const;
std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
bool attachedOnly, bool singlePort) const;
+ std::vector<aidl::android::media::audio::common::AudioPort> getPrimaryMixPorts(
+ bool attachedOnly, bool singlePort) const;
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
@@ -81,14 +91,17 @@
}
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
const {
- auto inputs = generateAudioMixPortConfigs(getInputMixPorts(), true, false);
- auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(), false, false);
+ auto inputs =
+ generateAudioMixPortConfigs(getInputMixPorts(false /*attachedOnly*/), true, false);
+ auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(false /*attachedOnly*/), false,
+ false);
inputs.insert(inputs.end(), outputs.begin(), outputs.end());
return inputs;
}
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
bool isInput) const {
- return generateAudioMixPortConfigs(getMixPorts(isInput), isInput, false);
+ return generateAudioMixPortConfigs(getMixPorts(isInput, false /*attachedOnly*/), isInput,
+ false);
}
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
@@ -96,7 +109,8 @@
}
std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
bool isInput) const {
- const auto config = generateAudioMixPortConfigs(getMixPorts(isInput), isInput, true);
+ const auto config = generateAudioMixPortConfigs(
+ getMixPorts(isInput, false /*attachedOnly*/), isInput, true);
if (!config.empty()) {
return *config.begin();
}
@@ -125,8 +139,9 @@
private:
std::vector<aidl::android::media::audio::common::AudioPort> findMixPorts(
- bool isInput, bool singlePort,
- std::function<bool(const aidl::android::media::audio::common::AudioPort&)> pred) const;
+ bool isInput, bool attachedOnly, bool singlePort,
+ const std::function<bool(const aidl::android::media::audio::common::AudioPort&)>& pred)
+ const;
std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
const std::vector<aidl::android::media::audio::common::AudioPort>& ports, bool isInput,
bool singleProfile) const;
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 79b20fe..c0c04f4 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -59,6 +59,8 @@
using aidl::android::hardware::audio::core::IStreamIn;
using aidl::android::hardware::audio::core::IStreamOut;
using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::MicrophoneDynamicInfo;
+using aidl::android::hardware::audio::core::MicrophoneInfo;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
@@ -192,6 +194,7 @@
*isSupported = false;
return;
}
+ ASSERT_TRUE(status.isOk()) << "Unexpected status from a getter: " << status;
*isSupported = true;
for (const auto v : validValues) {
EXPECT_IS_OK((inst->*setter)(v)) << "for valid value: " << v;
@@ -1567,6 +1570,42 @@
// TODO: Test that mic mute actually mutes input.
}
+TEST_P(AudioCoreModule, GetMicrophones) {
+ ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+ const std::vector<AudioPort> builtInMicPorts = moduleConfig->getAttachedMicrophonePorts();
+ std::vector<MicrophoneInfo> micInfos;
+ ScopedAStatus status = module->getMicrophones(&micInfos);
+ if (!status.isOk()) {
+ EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+ ASSERT_FALSE(builtInMicPorts.empty())
+ << "When the HAL module does not have built-in microphones, IModule.getMicrophones"
+ << " must complete with no error and return an empty list";
+ GTEST_SKIP() << "Microphone info is not supported";
+ }
+ std::set<int32_t> micPortIdsWithInfo;
+ for (const auto& micInfo : micInfos) {
+ const auto& micDevice = micInfo.device;
+ const auto it =
+ std::find_if(builtInMicPorts.begin(), builtInMicPorts.end(), [&](const auto& port) {
+ return port.ext.template get<AudioPortExt::Tag::device>().device == micDevice;
+ });
+ if (it != builtInMicPorts.end()) {
+ micPortIdsWithInfo.insert(it->id);
+ } else {
+ ADD_FAILURE() << "No device port found with a device specified for the microphone \""
+ << micInfo.id << "\": " << micDevice.toString();
+ }
+ }
+ if (micPortIdsWithInfo.size() != builtInMicPorts.size()) {
+ std::vector<AudioPort> micPortsNoInfo;
+ std::copy_if(builtInMicPorts.begin(), builtInMicPorts.end(),
+ std::back_inserter(micPortsNoInfo),
+ [&](const auto& port) { return micPortIdsWithInfo.count(port.id) == 0; });
+ ADD_FAILURE() << "No MicrophoneInfo is provided for the following microphone device ports: "
+ << ::android::internal::ToString(micPortsNoInfo);
+ }
+}
+
TEST_P(AudioCoreModule, UpdateAudioMode) {
for (const auto mode : ::ndk::enum_range<AudioMode>()) {
EXPECT_IS_OK(module->updateAudioMode(mode)) << toString(mode);
@@ -1747,13 +1786,11 @@
void OpenOverMaxCount() {
constexpr bool isInput = IOTraits<Stream>::is_input;
- auto ports = moduleConfig->getMixPorts(isInput);
+ auto ports = moduleConfig->getMixPorts(isInput, true /*attachedOnly*/);
bool hasSingleRun = false;
for (const auto& port : ports) {
const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
- if (maxStreamCount == 0 ||
- moduleConfig->getAttachedDevicesPortsForMixPort(isInput, port).empty()) {
- // No restrictions or no permanently attached devices.
+ if (maxStreamCount == 0) {
continue;
}
auto portConfigs = moduleConfig->getPortConfigsForMixPorts(isInput, port);
@@ -1878,20 +1915,127 @@
TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
+namespace aidl::android::hardware::audio::core {
+std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
+ os << toString(md);
+ return os;
+}
+} // namespace aidl::android::hardware::audio::core
+
+TEST_P(AudioStreamIn, ActiveMicrophones) {
+ std::vector<MicrophoneInfo> micInfos;
+ ScopedAStatus status = module->getMicrophones(&micInfos);
+ if (!status.isOk()) {
+ GTEST_SKIP() << "Microphone info is not supported";
+ }
+ const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No input mix ports for attached devices";
+ }
+ for (const auto& port : ports) {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+ ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+ WithStream<IStreamIn> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ {
+ // The port of the stream is not connected, thus the list of active mics must be empty.
+ std::vector<MicrophoneDynamicInfo> activeMics;
+ EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+ EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
+ "non-empty list of active microphones";
+ }
+ if (auto micDevicePorts = ModuleConfig::getBuiltInMicPorts(
+ moduleConfig->getAttachedSourceDevicesPortsForMixPort(port));
+ !micDevicePorts.empty()) {
+ auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(micDevicePorts[0]);
+ WithAudioPatch patch(true /*isInput*/, stream.getPortConfig(), devicePortConfig);
+ ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+ std::vector<MicrophoneDynamicInfo> activeMics;
+ EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+ for (const auto& mic : activeMics) {
+ EXPECT_NE(micInfos.end(),
+ std::find_if(micInfos.begin(), micInfos.end(),
+ [&](const auto& micInfo) { return micInfo.id == mic.id; }))
+ << "active microphone \"" << mic.id << "\" is not listed in "
+ << "microphone infos returned by the module: "
+ << ::android::internal::ToString(micInfos);
+ EXPECT_NE(0UL, mic.channelMapping.size())
+ << "No channels specified for the microphone \"" << mic.id << "\"";
+ }
+ }
+ {
+ // Now the port of the stream is not connected again, re-check that there are no
+ // active microphones.
+ std::vector<MicrophoneDynamicInfo> activeMics;
+ EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+ EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
+ "non-empty list of active microphones";
+ }
+ }
+}
+
+TEST_P(AudioStreamIn, MicrophoneDirection) {
+ using MD = IStreamIn::MicrophoneDirection;
+ const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No input mix ports for attached devices";
+ }
+ bool isSupported = false;
+ for (const auto& port : ports) {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+ ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+ WithStream<IStreamIn> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ EXPECT_NO_FATAL_FAILURE(
+ TestAccessors<MD>(stream.get(), &IStreamIn::getMicrophoneDirection,
+ &IStreamIn::setMicrophoneDirection,
+ std::vector<MD>(enum_range<MD>().begin(), enum_range<MD>().end()),
+ {}, &isSupported));
+ if (!isSupported) break;
+ }
+ if (!isSupported) {
+ GTEST_SKIP() << "Microphone direction is not supported";
+ }
+}
+
+TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
+ const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No input mix ports for attached devices";
+ }
+ bool isSupported = false;
+ for (const auto& port : ports) {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+ ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+ WithStream<IStreamIn> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(
+ stream.get(), &IStreamIn::getMicrophoneFieldDimension,
+ &IStreamIn::setMicrophoneFieldDimension,
+ {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE,
+ IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE / 2.0f,
+ IStreamIn::MIC_FIELD_DIMENSION_NO_ZOOM,
+ IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM / 2.0f,
+ IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM},
+ {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 2,
+ IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 2,
+ IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 1.1f,
+ IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 1.1f, -INFINITY, INFINITY, -NAN, NAN},
+ &isSupported));
+ if (!isSupported) break;
+ }
+ if (!isSupported) {
+ GTEST_SKIP() << "Microphone direction is not supported";
+ }
+}
+
TEST_P(AudioStreamOut, OpenTwicePrimary) {
- const auto mixPorts = moduleConfig->getMixPorts(false);
- auto primaryPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [](const AudioPort& port) {
- return port.flags.getTag() == AudioIoFlags::Tag::output &&
- isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
- AudioOutputFlags::PRIMARY);
- });
- if (primaryPortIt == mixPorts.end()) {
- GTEST_SKIP() << "No primary mix port";
+ const auto mixPorts =
+ moduleConfig->getPrimaryMixPorts(true /*attachedOnly*/, true /*singlePort*/);
+ if (mixPorts.empty()) {
+ GTEST_SKIP() << "No primary mix port which could be routed to attached devices";
}
- if (moduleConfig->getAttachedSinkDevicesPortsForMixPort(*primaryPortIt).empty()) {
- GTEST_SKIP() << "Primary mix port can not be routed to any of attached devices";
- }
- const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *primaryPortIt);
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *mixPorts.begin());
ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for the primary mix port";
EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
}
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 18a3329..9c8bfc4 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -630,29 +630,29 @@
targetDisplayId = ids[0];
});
- // Request exclusive access to the first EVS display
- sp<IEvsDisplay_1_1> pDisplay = pEnumerator->openDisplay_1_1(targetDisplayId);
- ASSERT_NE(pDisplay, nullptr);
- LOG(INFO) << "Display " << targetDisplayId << " is alreay in use.";
-
- // Get the display descriptor
- pDisplay->getDisplayInfo_1_1([](const HwDisplayConfig& config, const HwDisplayState& state) {
- ASSERT_GT(config.size(), 0);
- ASSERT_GT(state.size(), 0);
-
- android::ui::DisplayMode* pConfig = (android::ui::DisplayMode*)config.data();
- const auto width = pConfig->resolution.getWidth();
- const auto height = pConfig->resolution.getHeight();
- LOG(INFO) << " Resolution: " << width << "x" << height;
- ASSERT_GT(width, 0);
- ASSERT_GT(height, 0);
-
- android::ui::DisplayState* pState = (android::ui::DisplayState*)state.data();
- ASSERT_NE(pState->layerStack, android::ui::INVALID_LAYER_STACK);
- });
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
+ // Request exclusive access to the first EVS display
+ sp<IEvsDisplay_1_1> pDisplay = pEnumerator->openDisplay_1_1(targetDisplayId);
+ ASSERT_NE(pDisplay, nullptr);
+ LOG(INFO) << "Display " << targetDisplayId << " is already in use.";
+
+ // Get the display descriptor
+ pDisplay->getDisplayInfo_1_1([](const HwDisplayConfig& config, const HwDisplayState& state) {
+ ASSERT_GT(config.size(), 0);
+ ASSERT_GT(state.size(), 0);
+
+ android::ui::DisplayMode* pConfig = (android::ui::DisplayMode*)config.data();
+ const auto width = pConfig->resolution.getWidth();
+ const auto height = pConfig->resolution.getHeight();
+ LOG(INFO) << " Resolution: " << width << "x" << height;
+ ASSERT_GT(width, 0);
+ ASSERT_GT(height, 0);
+
+ android::ui::DisplayState* pState = (android::ui::DisplayState*)state.data();
+ ASSERT_NE(pState->layerStack, android::ui::INVALID_LAYER_STACK);
+ });
+
bool isLogicalCam = false;
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
@@ -707,10 +707,10 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
activeCameras.clear();
- }
- // Explicitly release the display
- pEnumerator->closeDisplay(pDisplay);
+ // Explicitly release the display
+ pEnumerator->closeDisplay(pDisplay);
+ }
}
@@ -1631,12 +1631,12 @@
// Get the camera list
loadCameraList();
- // Request exclusive access to the EVS display
- sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
- ASSERT_NE(pDisplay, nullptr);
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
+ // Request exclusive access to the EVS display
+ sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
+ ASSERT_NE(pDisplay, nullptr);
+
// Read a target resolution from the metadata
Stream targetCfg =
getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
@@ -1978,10 +1978,9 @@
pEnumerator->closeCamera(pCam1);
activeCameras.clear();
+ // Explicitly release the display
+ pEnumerator->closeDisplay(pDisplay);
}
-
- // Explicitly release the display
- pEnumerator->closeDisplay(pDisplay);
}
@@ -1997,12 +1996,12 @@
// Get the camera list
loadCameraList();
- // Request exclusive access to the EVS display
- sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
- ASSERT_NE(pDisplay, nullptr);
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
+ // Request exclusive access to the EVS display
+ sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
+ ASSERT_NE(pDisplay, nullptr);
+
// choose a configuration that has a frame rate faster than minReqFps.
Stream targetCfg = {};
const int32_t minReqFps = 15;
@@ -2078,10 +2077,10 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
activeCameras.clear();
- }
- // Explicitly release the display
- pEnumerator->closeDisplay(pDisplay);
+ // Explicitly release the display
+ pEnumerator->closeDisplay(pDisplay);
+ }
}
diff --git a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
index 3ea1eaa..3cab204 100644
--- a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
+++ b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
@@ -600,21 +600,21 @@
EXPECT_GT(displayIds.size(), 0);
targetDisplayId = displayIds[0];
- // Request exclusive access to the first EVS display
- std::shared_ptr<IEvsDisplay> pDisplay;
- ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
- EXPECT_NE(pDisplay, nullptr);
- LOG(INFO) << "Display " << static_cast<int>(targetDisplayId) << " is in use.";
-
- // Get the display descriptor
- DisplayDesc displayDesc;
- ASSERT_TRUE(pDisplay->getDisplayInfo(&displayDesc).isOk());
- LOG(INFO) << " Resolution: " << displayDesc.width << "x" << displayDesc.height;
- ASSERT_GT(displayDesc.width, 0);
- ASSERT_GT(displayDesc.height, 0);
-
// Test each reported camera
for (auto&& cam : mCameraInfo) {
+ // Request exclusive access to the first EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+ LOG(INFO) << "Display " << static_cast<int>(targetDisplayId) << " is in use.";
+
+ // Get the display descriptor
+ DisplayDesc displayDesc;
+ ASSERT_TRUE(pDisplay->getDisplayInfo(&displayDesc).isOk());
+ LOG(INFO) << " Resolution: " << displayDesc.width << "x" << displayDesc.height;
+ ASSERT_GT(displayDesc.width, 0);
+ ASSERT_GT(displayDesc.height, 0);
+
bool isLogicalCam = false;
getPhysicalCameraIds(cam.id, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
@@ -668,10 +668,10 @@
// Explicitly release the camera
ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
mActiveCameras.clear();
- }
- // Explicitly release the display
- ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ }
}
/*
@@ -1395,20 +1395,20 @@
// Get the camera list
loadCameraList();
- // Request available display IDs
- uint8_t targetDisplayId = 0;
- std::vector<uint8_t> displayIds;
- ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
- EXPECT_GT(displayIds.size(), 0);
- targetDisplayId = displayIds[0];
-
- // Request exclusive access to the EVS display
- std::shared_ptr<IEvsDisplay> pDisplay;
- ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
- EXPECT_NE(pDisplay, nullptr);
-
// Test each reported camera
for (auto&& cam : mCameraInfo) {
+ // Request available display IDs
+ uint8_t targetDisplayId = 0;
+ std::vector<uint8_t> displayIds;
+ ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+ EXPECT_GT(displayIds.size(), 0);
+ targetDisplayId = displayIds[0];
+
+ // Request exclusive access to the EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+
// Read a target resolution from the metadata
Stream targetCfg = getFirstStreamConfiguration(
reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
@@ -1687,10 +1687,10 @@
ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
mActiveCameras.clear();
- }
- // Explicitly release the display
- ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ }
}
/*
@@ -1712,13 +1712,13 @@
EXPECT_GT(displayIds.size(), 0);
targetDisplayId = displayIds[0];
- // Request exclusive access to the EVS display
- std::shared_ptr<IEvsDisplay> pDisplay;
- ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
- EXPECT_NE(pDisplay, nullptr);
-
// Test each reported camera
for (auto&& cam : mCameraInfo) {
+ // Request exclusive access to the EVS display
+ std::shared_ptr<IEvsDisplay> pDisplay;
+ ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+ EXPECT_NE(pDisplay, nullptr);
+
// choose a configuration that has a frame rate faster than minReqFps.
Stream targetCfg = {};
const int32_t minReqFps = 15;
@@ -1791,10 +1791,10 @@
// Explicitly release the camera
ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
mActiveCameras.clear();
- }
- // Explicitly release the display
- ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ // Explicitly release the display
+ ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+ }
}
/*
diff --git a/automotive/remoteaccess/hal/default/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
index a2bf86c..f27b8f8 100644
--- a/automotive/remoteaccess/hal/default/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -18,11 +18,9 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_binary {
- name: "android.hardware.automotive.remoteaccess@V1-default-service",
+cc_defaults {
+ name: "remote-access-hal-defaults",
vendor: true,
- vintf_fragments: ["remoteaccess-default-service.xml"],
- init_rc: ["remoteaccess-default-service.rc"],
relative_install_path: "hw",
srcs: ["src/RemoteAccessImpl.cpp"],
whole_static_libs: [
@@ -41,10 +39,29 @@
],
cflags: [
"-Wno-unused-parameter",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.automotive.remoteaccess@V1-default-service",
+ defaults: ["remote-access-hal-defaults"],
+ vintf_fragments: ["remoteaccess-default-service.xml"],
+ init_rc: ["remoteaccess-default-service.rc"],
+ cflags: [
"-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
],
}
+cc_binary {
+ name: "android.hardware.automotive.remoteaccess@V1-tcu-test-service",
+ defaults: ["remote-access-hal-defaults"],
+ vintf_fragments: ["remoteaccess-default-service.xml"],
+ init_rc: ["remoteaccess-tcu-test-service.rc"],
+ cflags: [
+ "-DGRPC_SERVICE_ADDRESS=\"10.10.10.1:50051\"",
+ ],
+}
+
cc_library {
name: "RemoteAccessService",
vendor_available: true,
diff --git a/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc b/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc
new file mode 100644
index 0000000..6437d70
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc
@@ -0,0 +1,4 @@
+service vendor.remoteaccess-default /vendor/bin/hw/android.hardware.automotive.remoteaccess@V1-tcu-test-service
+ class hal
+ user vehicle_network
+ group system inet
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
index 5cd58d3..4be30a2 100644
--- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -111,7 +111,9 @@
// Try to stop the reading stream.
if (mGetRemoteTasksContext) {
mGetRemoteTasksContext->TryCancel();
- mGetRemoteTasksContext.reset();
+ // Don't reset mGetRemoteTaskContext here since the read stream might still be affective
+ // and might still be using it. This will cause reader->Read to return false and
+ // mGetRemoteTasksContext will be cleared after reader->Finish() is called.
}
mTaskWaitStopped = true;
mCv.notify_all();
@@ -155,6 +157,7 @@
}
}
Status status = reader->Finish();
+ mGetRemoteTasksContext.reset();
ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
status.error_code(), status.error_message().c_str());
diff --git a/automotive/remoteaccess/test_grpc_server/README.md b/automotive/remoteaccess/test_grpc_server/README.md
index 6bc1829..af3d54a 100644
--- a/automotive/remoteaccess/test_grpc_server/README.md
+++ b/automotive/remoteaccess/test_grpc_server/README.md
@@ -75,11 +75,18 @@
* Under android root: `source build/envsetup.sh`
+* Add
+ ```
+ PRODUCT_SOONG_NAMESPACES += hardware/interfaces/automotive/remoteaccess/test_grpc_server/lib`
+ ```
+
+ to `device/generic/car/common/car.mk`.
+
* `lunch sdk_car_x86_64-userdebug`
* `make -j TestWakeupClientServer`
-* `make -j ApPowerControlLib`
+* `make -j ApPOwerControlLib`
## How to push the test wakeup client to a TCU which runs Android.
@@ -99,7 +106,7 @@
* `adb push vendor/bin/TestWakeupClientServer /vendor/bin`
-* `adb push vendor/lib/ApPowerControlLib.so /vendor/lib`
+* `adb push vendor/lib64/ApPowerControlLib.so /vendor/lib64`
* `adb shell`
@@ -116,6 +123,13 @@
* Under android root, `source build/envsetup.sh`
+* Add
+ ```
+ PRODUCT_SOONG_NAMESPACES += hardware/interfaces/automotive/remoteaccess/test_grpc_server/lib`
+ ```
+
+ to `device/generic/car/common/car.mk`.
+
* `lunch sdk_car_x86_64-userdebug`
* `m -j`
@@ -150,8 +164,12 @@
* `make -j TestWakeupClientServer`
+* `make -j ApPOwerControlLib`
+
* `adb push $ANDROID_PRODUCT_OUT/vendor/bin/TestWakeupClientServer /vendor/bin`
+* `adb push $ANDROID_PRODUCT_OUT/vendor/lib64/ApPowerControlLib.so /vendor/lib64`
+
* `adb shell`
* `emulator_car_x86_64:/ # su`
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 8eb69ad..219ea3d 100644
--- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -61,6 +61,7 @@
FUEL_LEVEL = 291504903,
FUEL_DOOR_OPEN = 287310600,
EV_BATTERY_LEVEL = 291504905,
+ EV_CURRENT_BATTERY_CAPACITY = 291504909,
EV_CHARGE_PORT_OPEN = 287310602,
EV_CHARGE_PORT_CONNECTED = 287310603,
EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 291504908,
@@ -71,6 +72,7 @@
CURRENT_GEAR = 289408001,
PARKING_BRAKE_ON = 287310850,
PARKING_BRAKE_AUTO_APPLY = 287310851,
+ EV_BRAKE_REGENERATION_LEVEL = 289408012,
FUEL_LEVEL_LOW = 287310853,
NIGHT_MODE = 287310855,
TURN_SIGNAL_STATE = 289408008,
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 9096cbe..472192f 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -344,6 +344,20 @@
EV_BATTERY_LEVEL = 0x0309 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
/**
+ * Current battery capacity for EV or hybrid vehicle
+ *
+ * Returns the actual value of battery capacity, if EV or hybrid. This property captures the
+ * real-time battery capacity taking into account factors such as battery aging and temperature
+ * dependency. Therefore, this value might be different from INFO_EV_BATTERY_CAPACITY because
+ * INFO_EV_BATTERY_CAPACITY returns the nominal battery capacity from when the vehicle was new.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @unit VehicleUnit:WH
+ */
+ EV_CURRENT_BATTERY_CAPACITY =
+ 0x030D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT,
+ /**
* EV charge port open
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
@@ -491,6 +505,21 @@
PARKING_BRAKE_AUTO_APPLY = 0x0403 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
/**
+ * Regenerative braking level of a electronic vehicle
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported. The minInt32Value must be 0.
+ *
+ * The maxInt32Value in default area's VehicleAreaConfig indicates the maximum amount of energy
+ * regenerated from braking. The minInt32Value in default area's VehicleAreaConfig indicates no
+ * regenerative braking.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ EV_BRAKE_REGENERATION_LEVEL =
+ 0x040C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
* Warning for fuel low level.
*
* This property corresponds to the low fuel warning on the dashboard.
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
index 6574d6f..c898baf 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
@@ -61,6 +61,7 @@
{VehicleProperty::FUEL_LEVEL, VehiclePropertyAccess::READ},
{VehicleProperty::FUEL_DOOR_OPEN, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::EV_BATTERY_LEVEL, VehiclePropertyAccess::READ},
+ {VehicleProperty::EV_CURRENT_BATTERY_CAPACITY, VehiclePropertyAccess::READ},
{VehicleProperty::EV_CHARGE_PORT_OPEN, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::EV_CHARGE_PORT_CONNECTED, VehiclePropertyAccess::READ},
{VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyAccess::READ},
@@ -71,6 +72,7 @@
{VehicleProperty::CURRENT_GEAR, VehiclePropertyAccess::READ},
{VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyAccess::READ},
{VehicleProperty::PARKING_BRAKE_AUTO_APPLY, VehiclePropertyAccess::READ},
+ {VehicleProperty::EV_BRAKE_REGENERATION_LEVEL, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::FUEL_LEVEL_LOW, VehiclePropertyAccess::READ},
{VehicleProperty::NIGHT_MODE, VehiclePropertyAccess::READ},
{VehicleProperty::TURN_SIGNAL_STATE, VehiclePropertyAccess::READ},
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
index 7fffeda..c501d9b 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
@@ -61,6 +61,7 @@
{VehicleProperty::FUEL_LEVEL, VehiclePropertyChangeMode::CONTINUOUS},
{VehicleProperty::FUEL_DOOR_OPEN, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_BATTERY_LEVEL, VehiclePropertyChangeMode::CONTINUOUS},
+ {VehicleProperty::EV_CURRENT_BATTERY_CAPACITY, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_CHARGE_PORT_OPEN, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_CHARGE_PORT_CONNECTED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyChangeMode::CONTINUOUS},
@@ -71,6 +72,7 @@
{VehicleProperty::CURRENT_GEAR, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::PARKING_BRAKE_AUTO_APPLY, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::EV_BRAKE_REGENERATION_LEVEL, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::FUEL_LEVEL_LOW, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::NIGHT_MODE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::TURN_SIGNAL_STATE, VehiclePropertyChangeMode::ON_CHANGE},
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
index 30a6529..ca85de5 100644
--- a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
@@ -53,6 +53,7 @@
Map.entry(VehicleProperty.FUEL_LEVEL, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.FUEL_DOOR_OPEN, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.EV_BATTERY_LEVEL, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.EV_CURRENT_BATTERY_CAPACITY, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.EV_CHARGE_PORT_OPEN, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.EV_CHARGE_PORT_CONNECTED, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyAccess.READ),
@@ -63,6 +64,7 @@
Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.PARKING_BRAKE_AUTO_APPLY, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.EV_BRAKE_REGENERATION_LEVEL, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.FUEL_LEVEL_LOW, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.NIGHT_MODE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.TURN_SIGNAL_STATE, VehiclePropertyAccess.READ),
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
index 0cfbdad..92a83a8 100644
--- a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
@@ -53,6 +53,7 @@
Map.entry(VehicleProperty.FUEL_LEVEL, VehiclePropertyChangeMode.CONTINUOUS),
Map.entry(VehicleProperty.FUEL_DOOR_OPEN, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_BATTERY_LEVEL, VehiclePropertyChangeMode.CONTINUOUS),
+ Map.entry(VehicleProperty.EV_CURRENT_BATTERY_CAPACITY, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_CHARGE_PORT_OPEN, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_CHARGE_PORT_CONNECTED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, VehiclePropertyChangeMode.CONTINUOUS),
@@ -63,6 +64,7 @@
Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.PARKING_BRAKE_AUTO_APPLY, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.EV_BRAKE_REGENERATION_LEVEL, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.FUEL_LEVEL_LOW, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.NIGHT_MODE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.TURN_SIGNAL_STATE, VehiclePropertyChangeMode.ON_CHANGE),
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 95327a3..45e21b2 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -1310,6 +1310,14 @@
"minSampleRate": 1.0
},
{
+ "property": "VehicleProperty::EV_CURRENT_BATTERY_CAPACITY",
+ "defaultValue": {
+ "floatValues": [
+ 150000.0
+ ]
+ }
+ },
+ {
"property": "VehicleProperty::EV_CHARGE_PORT_OPEN",
"defaultValue": {
"int32Values": [
@@ -1545,6 +1553,21 @@
}
},
{
+ "property": "VehicleProperty::EV_BRAKE_REGENERATION_LEVEL",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::FUEL_LEVEL_LOW",
"defaultValue": {
"int32Values": [
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 62e9dc8..4a4e023 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -789,10 +789,13 @@
for (uint32_t i = 0; i < numArgs; i++) {
options.push_back(args[i]);
}
+ if (options.size() == 1 && options[0] == "-a") {
+ // Ignore "-a" option. Bugreport will call with this option.
+ options.clear();
+ }
DumpResult result = mVehicleHardware->dump(options);
dprintf(fd, "%s", (result.buffer + "\n").c_str());
if (!result.callerShouldDumpState) {
- ALOGE("Skip dumping Vehicle HAL State.");
return STATUS_OK;
}
dprintf(fd, "Vehicle HAL State: \n");
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 7eefe2a..1943c41 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -481,6 +481,18 @@
actualPropertyType);
}
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyEvBrakeRegenerationLevelConfig) {
+ verifyProperty(VehicleProperty::EV_BRAKE_REGENERATION_LEVEL,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyEvCurrentBatteryCapacityConfig) {
+ verifyProperty(VehicleProperty::EV_CURRENT_BATTERY_CAPACITY, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::FLOAT);
+}
+
TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyDoorChildLockEnabledConfig) {
verifyProperty(VehicleProperty::DOOR_CHILD_LOCK_ENABLED, VehiclePropertyAccess::READ_WRITE,
VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.rc b/biometrics/fingerprint/aidl/default/fingerprint-example.rc
index 574438e..10db00d 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.rc
+++ b/biometrics/fingerprint/aidl/default/fingerprint-example.rc
@@ -2,3 +2,8 @@
class hal
user nobody
group nobody
+ disabled
+on property:ro.vendor.fingerprint_virtual_hal_start=true
+ enable vendor.fingerprint-example
+on property:persist.vendor.fingerprint.virtual.type=*
+ enable vendor.fingerprint-example
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index d21ae58..e1c9cc5 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -19,6 +19,9 @@
java: {
enabled: false,
},
+ rust: {
+ enabled: true,
+ }
},
versions_with_info: [
{
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index c184677..2e5b667 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -27,6 +27,9 @@
sdk_version: "module_current",
enabled: false,
},
+ rust: {
+ enabled: true,
+ }
},
versions_with_info: [
{
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index 301a943..0113a4b 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -19,6 +19,9 @@
java: {
enabled: false,
},
+ rust: {
+ enabled: true,
+ }
},
versions_with_info: [
{
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
index 8bed156..e28ecad 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl
@@ -70,5 +70,6 @@
ANDROID_HEIC_INFO = 29,
ANDROID_AUTOMOTIVE = 30,
ANDROID_AUTOMOTIVE_LENS = 31,
+ ANDROID_EXTENSION = 32,
VENDOR_SECTION = 32768,
}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
index 1725347..a223309 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
@@ -70,5 +70,6 @@
ANDROID_HEIC_INFO_START = 1900544,
ANDROID_AUTOMOTIVE_START = 1966080,
ANDROID_AUTOMOTIVE_LENS_START = 2031616,
+ ANDROID_EXTENSION_START = 2097152,
VENDOR_SECTION_START = -2147483648,
}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
index 99e28b9..0d79f0d 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl
@@ -61,5 +61,6 @@
ANDROID_HEIC_INFO,
ANDROID_AUTOMOTIVE,
ANDROID_AUTOMOTIVE_LENS,
+ ANDROID_EXTENSION,
VENDOR_SECTION = 0x8000,
}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
index 62c71e9..8f57128 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl
@@ -63,5 +63,6 @@
ANDROID_HEIC_INFO_START = CameraMetadataSection.ANDROID_HEIC_INFO << 16,
ANDROID_AUTOMOTIVE_START = CameraMetadataSection.ANDROID_AUTOMOTIVE << 16,
ANDROID_AUTOMOTIVE_LENS_START = CameraMetadataSection.ANDROID_AUTOMOTIVE_LENS << 16,
+ ANDROID_EXTENSION_START = CameraMetadataSection.ANDROID_EXTENSION << 16,
VENDOR_SECTION_START = CameraMetadataSection.VENDOR_SECTION << 16,
}
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index d7e613e..19dede0 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -26,6 +26,9 @@
cpp: {
enabled: false,
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 7f6890c..f3ea8e8 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -36,6 +36,9 @@
],
min_sdk_version: "29",
},
+ rust: {
+ enabled: true,
+ }
},
frozen: true,
versions: [
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 95fcc41..0715575 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -36,6 +36,9 @@
],
min_sdk_version: "29",
},
+ rust: {
+ enabled: true,
+ }
},
frozen: true,
versions: ["1"],
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d0e844d..9f43219 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -277,7 +277,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.graphics.composer3</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
@@ -693,7 +693,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.weaver</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IWeaver</name>
<instance>default</instance>
diff --git a/current.txt b/current.txt
index 146ded6..0fb8b49 100644
--- a/current.txt
+++ b/current.txt
@@ -931,5 +931,6 @@
# ABI preserving changes to HALs during Android U
2aa559cda86c358c6429114ef6bc72c1b43281e98f9eb6b4df5e7073c8d05767 android.hardware.automotive.vehicle@2.0::types
+42abd285a4293dadb8c89bc63b90cae2872fbffe90c4517aa3ea4965e8aecff7 android.hardware.graphics.common@1.2::types
# There will be no more HIDL HALs. Use AIDL instead.
diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal
index ebea1dc..07e9882 100644
--- a/graphics/common/1.2/types.hal
+++ b/graphics/common/1.2/types.hal
@@ -77,6 +77,8 @@
HEIF = 0x1004,
};
+@export(name="android_color_mode_v1_2_t", value_prefix="HAL_COLOR_MODE_",
+ export_parent="false")
enum ColorMode : @1.1::ColorMode {
/**
* DISPLAY_BT2020 corresponds with display settings that implement the ITU-R
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 84bc1af..6c8ff4b 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -39,6 +39,9 @@
],
min_sdk_version: "29",
},
+ rust: {
+ enabled: true,
+ }
},
frozen: false,
versions_with_info: [
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index fa66812..4d7bf13 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -811,8 +811,7 @@
EXPECT_TRUE(status.isOk());
}
-// TODO(b/250036572): disable this due to no implementation and revup on cuttlefish
-TEST_P(GraphicsComposerAidlTest, DISABLED_GetOverlaySupport) {
+TEST_P(GraphicsComposerAidlTest, GetOverlaySupport) {
const auto& [status, _] = mComposerClient->getOverlaySupport();
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
diff --git a/graphics/mapper/stable-c/Android.bp b/graphics/mapper/stable-c/Android.bp
index c03f67e..d40e160 100644
--- a/graphics/mapper/stable-c/Android.bp
+++ b/graphics/mapper/stable-c/Android.bp
@@ -61,6 +61,10 @@
srcs: [
"implutils/impltests.cpp",
],
+ shared_libs: [
+ "libgralloctypes",
+ "libhidlbase",
+ ],
visibility: [":__subpackages__"],
cpp_std: "experimental",
}
diff --git a/graphics/mapper/stable-c/implutils/impltests.cpp b/graphics/mapper/stable-c/implutils/impltests.cpp
index 9c5d70b..f12b069 100644
--- a/graphics/mapper/stable-c/implutils/impltests.cpp
+++ b/graphics/mapper/stable-c/implutils/impltests.cpp
@@ -18,123 +18,29 @@
#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
+#include <drm/drm_fourcc.h>
+#include <gralloctypes/Gralloc4.h>
+#include <span>
#include <vector>
+using namespace ::android;
using namespace ::android::hardware::graphics::mapper;
using namespace ::aidl::android::hardware::graphics::common;
+namespace gralloc4 = ::android::gralloc4;
+using ::android::hardware::hidl_vec;
// These tests are primarily interested in hitting all the different *types* that can be
// serialized/deserialized than in exhaustively testing all the StandardMetadataTypes.
// Exhaustive testing of the actual metadata types is relegated for IMapper's VTS suite
// where meaning & correctness of values are more narrowly defined (eg, read-only values)
-TEST(Metadata, setGetBufferId) {
- using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+static constexpr auto HeaderSize = 69;
- std::vector<char> buffer;
- buffer.resize(12, 0);
- *reinterpret_cast<int64_t*>(buffer.data()) = 42;
-
- EXPECT_EQ(8, BufferId::encode(18, buffer.data(), 0));
- EXPECT_EQ(42, *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_EQ(8, BufferId::encode(18, buffer.data(), buffer.size()));
- EXPECT_EQ(18, *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
- auto read = BufferId::decode(buffer.data(), buffer.size());
- EXPECT_TRUE(read.has_value());
- EXPECT_EQ(18, read.value_or(0));
+static std::span<uint8_t> SkipHeader(std::vector<uint8_t>& buffer) {
+ return std::span<uint8_t>(buffer).subspan(HeaderSize);
}
-TEST(Metadata, setGetDataspace) {
- using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
- using intType = std::underlying_type_t<Dataspace>;
- std::vector<char> buffer;
- buffer.resize(12, 0);
-
- EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
- EXPECT_EQ(0, *reinterpret_cast<intType*>(buffer.data()));
- EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
- EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(buffer.data()));
- EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
- auto read = DataspaceValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(read.has_value());
- EXPECT_EQ(Dataspace::BT2020, *read);
-}
-
-TEST(Metadata, setGetValidName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
-
- std::vector<char> buffer;
- buffer.resize(100, 'a');
- buffer[buffer.size() - 1] = '\0';
-
- // len("Hello") + sizeof(int64)
- constexpr int expectedSize = 5 + sizeof(int64_t);
- EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
- EXPECT_EQ(5, *reinterpret_cast<int64_t*>(buffer.data()));
- // Verify didn't write past the end of the desired size
- EXPECT_EQ('a', buffer[expectedSize]);
-
- auto readValue = NameValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(readValue.has_value());
- EXPECT_EQ(5, readValue->length());
- EXPECT_EQ("Hello", *readValue);
-}
-
-TEST(Metadata, setGetInvalidName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
-
- std::vector<char> buffer;
- buffer.resize(12, 'a');
- buffer[buffer.size() - 1] = '\0';
-
- // len("This is a long string") + sizeof(int64)
- constexpr int expectedSize = 21 + sizeof(int64_t);
- EXPECT_EQ(expectedSize,
- NameValue::encode("This is a long string", buffer.data(), buffer.size()));
- EXPECT_EQ(21, *reinterpret_cast<int64_t*>(buffer.data()));
- // Verify didn't write the too-long string
- EXPECT_EQ('a', buffer[9]);
- EXPECT_EQ('\0', buffer[buffer.size() - 1]);
-
- auto readValue = NameValue::decode(buffer.data(), buffer.size());
- EXPECT_FALSE(readValue.has_value());
- readValue = NameValue::decode(buffer.data(), 0);
- ASSERT_FALSE(readValue.has_value());
-}
-
-TEST(Metadata, wouldOverflowName) {
- using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
- std::vector<char> buffer(100, 0);
-
- // int_max + sizeof(int64) overflows int32
- std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
- EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
- NameValue::encode(bad_string, buffer.data(), buffer.size()));
-
- // check barely overflows
- bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
- EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
- NameValue::encode(bad_string, buffer.data(), buffer.size()));
-}
-
-TEST(Metadata, setGetCompression) {
- using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
- ExtendableType myCompression{"bestest_compression_ever", 42};
- std::vector<char> buffer(100, '\0');
- const int expectedSize = myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t);
- EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
- EXPECT_EQ(0, buffer[0]);
- EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
- EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(buffer.data()));
- EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
- auto read = CompressionValue::decode(buffer.data(), buffer.size());
- ASSERT_TRUE(read.has_value());
- EXPECT_EQ(myCompression, read.value());
-}
-
-TEST(Metadata, setGetPlaneLayout) {
- using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
+static std::vector<PlaneLayout> fakePlaneLayouts() {
PlaneLayout myPlaneLayout;
myPlaneLayout.offsetInBytes = 10;
myPlaneLayout.sampleIncrementInBits = 11;
@@ -153,23 +59,147 @@
it.sizeInBits = 30 + i;
}
- std::vector<PlaneLayout> layouts{myPlaneLayout, PlaneLayout{}};
+ return std::vector<PlaneLayout>{myPlaneLayout, PlaneLayout{}};
+}
- std::vector<char> buffer(5000, '\0');
+TEST(Metadata, setGetBufferId) {
+ using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+
+ std::vector<uint8_t> buffer(10000, 0);
+ int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
+ *payload = 42;
+
+ EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), 0));
+ EXPECT_EQ(42, *payload);
+ EXPECT_EQ(8 + HeaderSize, BufferId::encode(18, buffer.data(), buffer.size()));
+ EXPECT_EQ(18, *payload);
+ EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
+ auto read = BufferId::decode(buffer.data(), buffer.size());
+ EXPECT_TRUE(read.has_value());
+ EXPECT_EQ(18, read.value_or(0));
+}
+
+TEST(Metadata, setGetDataspace) {
+ using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
+ using intType = std::underlying_type_t<Dataspace>;
+ std::vector<uint8_t> buffer(10000, 0);
+ auto data = SkipHeader(buffer);
+
+ EXPECT_EQ(4 + HeaderSize, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
+ EXPECT_EQ(0, *reinterpret_cast<intType*>(data.data()));
+ EXPECT_EQ(4 + HeaderSize,
+ DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
+ EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(data.data()));
+ EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
+ auto read = DataspaceValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(Dataspace::BT2020, *read);
+}
+
+TEST(Metadata, setGetValidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<uint8_t> buffer(10000, 'a');
+
+ // len("Hello") + sizeof(int64)
+ constexpr int expectedSize = 5 + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
+ EXPECT_EQ(5, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+ // Verify didn't write past the end of the desired size
+ EXPECT_EQ('a', buffer[expectedSize]);
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(readValue.has_value());
+ EXPECT_EQ(5, readValue->length());
+ EXPECT_EQ("Hello", *readValue);
+}
+
+TEST(Metadata, setGetInvalidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<uint8_t> buffer;
+ buffer.resize(12 + HeaderSize, 'a');
+ buffer[buffer.size() - 1] = '\0';
+
+ // len("This is a long string") + sizeof(int64)
+ constexpr int expectedSize = 21 + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize,
+ NameValue::encode("This is a long string", buffer.data(), buffer.size()));
+ EXPECT_EQ(21, *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ EXPECT_FALSE(readValue.has_value());
+ readValue = NameValue::decode(buffer.data(), 0);
+ ASSERT_FALSE(readValue.has_value());
+}
+
+TEST(Metadata, wouldOverflowName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+ std::vector<uint8_t> buffer(10000, 0);
+
+ // int_max + sizeof(int64) overflows int32
+ std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+
+ // check barely overflows
+ bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+}
+
+TEST(Metadata, setGetMismatchedWidthHight) {
+ // Validates that the header is properly validated on decode
+ using WidthValue = StandardMetadata<StandardMetadataType::WIDTH>::value;
+ using HeightValue = StandardMetadata<StandardMetadataType::HEIGHT>::value;
+ std::vector<uint8_t> buffer(10000, 0);
+
+ EXPECT_EQ(8 + HeaderSize, WidthValue::encode(100, buffer.data(), buffer.size()));
+ EXPECT_EQ(100, *reinterpret_cast<uint64_t*>(SkipHeader(buffer).data()));
+ auto read = WidthValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(100, *read);
+ read = HeightValue::decode(buffer.data(), buffer.size());
+ EXPECT_FALSE(read.has_value());
+}
+
+TEST(Metadata, setGetCompression) {
+ using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
+ ExtendableType myCompression{"bestest_compression_ever", 42};
+ std::vector<uint8_t> buffer(10000, 0);
+ const int expectedSize =
+ myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t) + HeaderSize;
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
+ EXPECT_EQ(0, buffer[0]);
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
+ EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(SkipHeader(buffer).data()));
+ EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
+ auto read = CompressionValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(myCompression, read.value());
+}
+
+TEST(Metadata, setGetPlaneLayout) {
+ using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
+
+ std::vector<PlaneLayout> layouts = fakePlaneLayouts();
+
+ std::vector<uint8_t> buffer(10000, 0);
constexpr int componentSize = 8 + (4 * sizeof(int64_t));
constexpr int firstLayoutSize = (8 + 1) * sizeof(int64_t) + (3 * componentSize);
constexpr int secondLayoutSize = (8 + 1) * sizeof(int64_t);
- constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t);
+ constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t) + HeaderSize;
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), 0));
EXPECT_EQ(0, buffer[0]);
EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), buffer.size()));
- EXPECT_EQ(3, reinterpret_cast<int64_t*>(buffer.data())[1]);
- EXPECT_EQ(8, reinterpret_cast<int64_t*>(buffer.data())[2]);
- EXPECT_EQ(40, reinterpret_cast<int64_t*>(buffer.data())[4]);
- EXPECT_EQ(31, reinterpret_cast<int64_t*>(buffer.data())[11]);
- EXPECT_EQ(22, reinterpret_cast<int64_t*>(buffer.data())[15]);
- EXPECT_EQ(10, reinterpret_cast<int64_t*>(buffer.data())[17]);
- EXPECT_EQ(11, reinterpret_cast<int64_t*>(buffer.data())[18]);
+ int64_t* payload = reinterpret_cast<int64_t*>(SkipHeader(buffer).data());
+ EXPECT_EQ(3, payload[1]);
+ EXPECT_EQ(8, payload[2]);
+ EXPECT_EQ(40, payload[4]);
+ EXPECT_EQ(31, payload[11]);
+ EXPECT_EQ(22, payload[15]);
+ EXPECT_EQ(10, payload[17]);
+ EXPECT_EQ(11, payload[18]);
EXPECT_FALSE(PlaneLayoutValue::decode(buffer.data(), 0).has_value());
auto read = PlaneLayoutValue::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -178,15 +208,15 @@
TEST(Metadata, setGetRects) {
using RectsValue = StandardMetadata<StandardMetadataType::CROP>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
std::vector<Rect> cropRects{2};
cropRects[0] = Rect{10, 11, 12, 13};
cropRects[1] = Rect{20, 21, 22, 23};
- constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t));
+ constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t)) + HeaderSize;
EXPECT_EQ(expectedSize, RectsValue::encode(cropRects, buffer.data(), buffer.size()));
- EXPECT_EQ(2, reinterpret_cast<int64_t*>(buffer.data())[0]);
- EXPECT_EQ(10, reinterpret_cast<int32_t*>(buffer.data())[2]);
+ EXPECT_EQ(2, reinterpret_cast<int64_t*>(SkipHeader(buffer).data())[0]);
+ EXPECT_EQ(10, reinterpret_cast<int32_t*>(SkipHeader(buffer).data())[2]);
auto read = RectsValue::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
EXPECT_EQ(cropRects.size(), read->size());
@@ -203,8 +233,8 @@
source.primaryGreen = XyColor{.3f, .4f};
source.primaryBlue = XyColor{.5f, .6f};
- constexpr int expectedSize = 10 * sizeof(float);
- std::vector<uint8_t> buffer(500, 0);
+ constexpr int expectedSize = 10 * sizeof(float) + HeaderSize;
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(expectedSize, Smpte2086Value::encode(source, buffer.data(), buffer.size()));
auto read = Smpte2086Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -223,8 +253,8 @@
source.maxFrameAverageLightLevel = 244.55f;
source.maxContentLightLevel = 202.202f;
- constexpr int expectedSize = 2 * sizeof(float);
- std::vector<uint8_t> buffer(500, 0);
+ constexpr int expectedSize = 2 * sizeof(float) + HeaderSize;
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(expectedSize, Cta861_3Value::encode(source, buffer.data(), buffer.size()));
auto read = Cta861_3Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -240,14 +270,14 @@
TEST(Metadata, setGetSmpte2094_10) {
using SMPTE2094_10Value = StandardMetadata<StandardMetadataType::SMPTE2094_10>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
EXPECT_EQ(0, SMPTE2094_10Value::encode(std::nullopt, buffer.data(), buffer.size()));
auto read = SMPTE2094_10Value::decode(buffer.data(), 0);
ASSERT_TRUE(read.has_value());
EXPECT_FALSE(read->has_value());
const std::vector<uint8_t> emptyBuffer;
- EXPECT_EQ(sizeof(int64_t),
+ EXPECT_EQ(sizeof(int64_t) + HeaderSize,
SMPTE2094_10Value::encode(emptyBuffer, buffer.data(), buffer.size()));
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -255,7 +285,7 @@
EXPECT_EQ(0, read->value().size());
const std::vector<uint8_t> simpleBuffer{0, 1, 2, 3, 4, 5};
- EXPECT_EQ(sizeof(int64_t) + 6,
+ EXPECT_EQ(sizeof(int64_t) + 6 + HeaderSize,
SMPTE2094_10Value::encode(simpleBuffer, buffer.data(), buffer.size()));
read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
ASSERT_TRUE(read.has_value());
@@ -266,7 +296,7 @@
TEST(MetadataProvider, bufferId) {
using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
- std::vector<uint8_t> buffer(500, 0);
+ std::vector<uint8_t> buffer(10000, 0);
int result = provideStandardMetadata(StandardMetadataType::BUFFER_ID, buffer.data(),
buffer.size(), []<StandardMetadataType T>(auto&& provide) {
if constexpr (T == StandardMetadataType::BUFFER_ID) {
@@ -275,7 +305,7 @@
return 0;
});
- EXPECT_EQ(8, result);
+ EXPECT_EQ(8 + HeaderSize, result);
auto read = BufferId::decode(buffer.data(), buffer.size());
EXPECT_EQ(42, read.value_or(0));
}
@@ -312,3 +342,193 @@
EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result)
<< "100 (out of range) should have resulted in UNSUPPORTED";
}
+
+template <StandardMetadataType T>
+std::vector<uint8_t> encode(const typename StandardMetadata<T>::value_type& value) {
+ using Value = typename StandardMetadata<T>::value;
+
+ int desiredSize = Value::encode(value, nullptr, 0);
+ EXPECT_GE(desiredSize, 0);
+ std::vector<uint8_t> buffer;
+ buffer.resize(desiredSize);
+ EXPECT_EQ(desiredSize, Value::encode(value, buffer.data(), buffer.size()));
+ return buffer;
+}
+
+TEST(MetadataGralloc4Interop, BufferId) {
+ auto mpbuf = encode<StandardMetadataType::BUFFER_ID>(42);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeBufferId(42, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Name) {
+ auto mpbuf = encode<StandardMetadataType::NAME>("Hello, Interop!");
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeName("Hello, Interop!", &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Width) {
+ auto mpbuf = encode<StandardMetadataType::WIDTH>(128);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeWidth(128, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Height) {
+ auto mpbuf = encode<StandardMetadataType::HEIGHT>(64);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeHeight(64, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, LayerCount) {
+ auto mpbuf = encode<StandardMetadataType::LAYER_COUNT>(3);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeLayerCount(3, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatRequested) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(PixelFormat::RGBX_8888);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatRequested(
+ hardware::graphics::common::V1_2::PixelFormat::RGBX_8888, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatFourcc) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_FOURCC>(DRM_FORMAT_ABGR8888);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(DRM_FORMAT_ABGR8888, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PixelFormatModifier) {
+ auto mpbuf = encode<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(123456);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(123456, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Usage) {
+ auto mpbuf = encode<StandardMetadataType::USAGE>(BufferUsage::COMPOSER_OVERLAY);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeUsage(
+ static_cast<uint64_t>(
+ hardware::graphics::common::V1_2::BufferUsage::COMPOSER_OVERLAY),
+ &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, AllocationSize) {
+ auto mpbuf = encode<StandardMetadataType::ALLOCATION_SIZE>(10200);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(10200, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, ProtectedContent) {
+ auto mpbuf = encode<StandardMetadataType::PROTECTED_CONTENT>(1);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeProtectedContent(1, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Compression) {
+ auto mpbuf = encode<StandardMetadataType::COMPRESSION>(
+ gralloc4::Compression_DisplayStreamCompression);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeCompression(gralloc4::Compression_DisplayStreamCompression, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Interlaced) {
+ auto mpbuf = encode<StandardMetadataType::INTERLACED>(gralloc4::Interlaced_TopBottom);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(gralloc4::Interlaced_TopBottom, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, ChromeSitting) {
+ auto mpbuf =
+ encode<StandardMetadataType::CHROMA_SITING>(gralloc4::ChromaSiting_SitedInterstitial);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR,
+ gralloc4::encodeChromaSiting(gralloc4::ChromaSiting_SitedInterstitial, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, PlaneLayouts) {
+ auto mpbuf = encode<StandardMetadataType::PLANE_LAYOUTS>(fakePlaneLayouts());
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodePlaneLayouts(fakePlaneLayouts(), &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Crop) {
+ std::vector<Rect> cropRects{Rect{10, 11, 12, 13}, Rect{20, 21, 22, 23}};
+ auto mpbuf = encode<StandardMetadataType::CROP>(cropRects);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(cropRects, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Dataspace) {
+ auto mpbuf = encode<StandardMetadataType::DATASPACE>(Dataspace::DISPLAY_P3);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::DISPLAY_P3, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, BlendMode) {
+ auto mpbuf = encode<StandardMetadataType::BLEND_MODE>(BlendMode::PREMULTIPLIED);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(BlendMode::PREMULTIPLIED, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2086) {
+ Smpte2086 hdrdata{XyColor{.1f, .2f}, XyColor{.3f, .4f}, XyColor{.5f, .6f},
+ XyColor{.7f, .8f}, 452.889f, 12.335f};
+
+ auto mpbuf = encode<StandardMetadataType::SMPTE2086>(hdrdata);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Cta861_3) {
+ Cta861_3 hdrdata{302.202f, 244.55f};
+ auto mpbuf = encode<StandardMetadataType::CTA861_3>(hdrdata);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeCta861_3(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2094_10) {
+ auto mpbuf = encode<StandardMetadataType::SMPTE2094_10>(std::nullopt);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(std::nullopt, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+
+ std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
+ mpbuf = encode<StandardMetadataType::SMPTE2094_10>(hdrdata);
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_10(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
+
+TEST(MetadataGralloc4Interop, Smpte2094_40) {
+ auto mpbuf = encode<StandardMetadataType::SMPTE2094_40>(std::nullopt);
+ hidl_vec<uint8_t> g4buf;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(std::nullopt, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+
+ std::vector<uint8_t> hdrdata{1, 2, 3, 4, 5, 6};
+ mpbuf = encode<StandardMetadataType::SMPTE2094_40>(hdrdata);
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2094_40(hdrdata, &g4buf));
+ EXPECT_EQ(mpbuf, g4buf);
+}
diff --git a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
index 7861af8..25af6d1 100644
--- a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
+++ b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
@@ -82,7 +82,12 @@
explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
: mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
- int32_t desiredSize() const { return mDesiredSize; }
+ [[nodiscard]] int32_t desiredSize() const { return mDesiredSize; }
+
+ template <typename HEADER>
+ MetadataWriter& writeHeader() {
+ return write(HEADER::name).template write<int64_t>(HEADER::value);
+ }
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
MetadataWriter& write(T value) {
@@ -150,6 +155,18 @@
[[nodiscard]] size_t remaining() const { return mSizeRemaining; }
[[nodiscard]] bool ok() const { return mOk; }
+ template <typename HEADER>
+ MetadataReader& checkHeader() {
+ if (HEADER::name != readString()) {
+ mOk = false;
+ }
+ auto value = readInt<int64_t>();
+ if (!value || *value != HEADER::value) {
+ mOk = false;
+ }
+ return *this;
+ }
+
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
MetadataReader& read(T& dest) {
if (const void* src = advance(sizeof(T))) {
@@ -228,27 +245,33 @@
}
};
-template <typename T, class Enable = void>
+template <typename HEADER, typename T, class Enable = void>
struct MetadataValue {};
-template <typename T>
-struct MetadataValue<T, std::enable_if_t<std::is_integral_v<T>>> {
+template <typename HEADER, typename T>
+struct MetadataValue<HEADER, T, std::enable_if_t<std::is_integral_v<T>>> {
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- return MetadataReader{metadata, metadataSize}.readInt<T>();
+ return MetadataReader{metadata, metadataSize}
+ .template checkHeader<HEADER>()
+ .template readInt<T>();
}
};
-template <typename T>
-struct MetadataValue<T, std::enable_if_t<std::is_enum_v<T>>> {
+template <typename HEADER, typename T>
+struct MetadataValue<HEADER, T, std::enable_if_t<std::is_enum_v<T>>> {
[[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
size_t destBufferSize) {
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(static_cast<std::underlying_type_t<T>>(value))
.desiredSize();
}
@@ -256,47 +279,56 @@
[[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
size_t metadataSize) {
std::underlying_type_t<T> temp;
- return MetadataReader{metadata, metadataSize}.read(temp).ok()
+ return MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>().read(temp).ok()
? std::optional<T>(static_cast<T>(temp))
: std::nullopt;
}
};
-template <>
-struct MetadataValue<std::string> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::string> {
[[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- auto reader = MetadataReader{metadata, metadataSize};
+ auto reader = MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>();
auto result = reader.readString();
return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
}
};
-template <>
-struct MetadataValue<ExtendableType> {
+template <typename HEADER>
+struct MetadataValue<HEADER, ExtendableType> {
static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
[[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
size_t destBufferSize) {
- return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(value)
+ .desiredSize();
}
[[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
size_t metadataSize) {
- return MetadataReader{metadata, metadataSize}.readExtendable();
+ return MetadataReader{metadata, metadataSize}
+ .template checkHeader<HEADER>()
+ .readExtendable();
}
};
-template <>
-struct MetadataValue<std::vector<PlaneLayout>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::vector<PlaneLayout>> {
[[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
void* _Nullable destBuffer, size_t destBufferSize) {
MetadataWriter writer{destBuffer, destBufferSize};
+ writer.template writeHeader<HEADER>();
writer.write<int64_t>(values.size());
for (const auto& value : values) {
writer.write<int64_t>(value.components.size());
@@ -321,13 +353,14 @@
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
std::vector<PlaneLayout> values;
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
auto numPlanes = reader.readInt<int64_t>().value_or(0);
values.reserve(numPlanes);
for (int i = 0; i < numPlanes && reader.ok(); i++) {
PlaneLayout& value = values.emplace_back();
auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
value.components.reserve(numPlaneComponents);
- for (int i = 0; i < numPlaneComponents && reader.ok(); i++) {
+ for (int j = 0; j < numPlaneComponents && reader.ok(); j++) {
PlaneLayoutComponent& component = value.components.emplace_back();
reader.read(component.type)
.read<int64_t>(component.offsetInBits)
@@ -346,11 +379,12 @@
}
};
-template <>
-struct MetadataValue<std::vector<Rect>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::vector<Rect>> {
[[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
size_t destBufferSize) {
MetadataWriter writer{destBuffer, destBufferSize};
+ writer.template writeHeader<HEADER>();
writer.write<int64_t>(value.size());
for (auto& rect : value) {
writer.write<int32_t>(rect.left)
@@ -364,6 +398,7 @@
using DecodeResult = std::optional<std::vector<Rect>>;
[[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
std::vector<Rect> value;
auto numRects = reader.readInt<int64_t>().value_or(0);
value.reserve(numRects);
@@ -378,13 +413,14 @@
}
};
-template <>
-struct MetadataValue<std::optional<Smpte2086>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<Smpte2086>> {
[[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
void* _Nullable destBuffer, size_t destBufferSize) {
if (optValue.has_value()) {
const auto& value = *optValue;
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(value.primaryRed)
.write(value.primaryGreen)
.write(value.primaryBlue)
@@ -404,6 +440,7 @@
if (metadataSize > 0) {
Smpte2086 value;
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
reader.read(value.primaryRed)
.read(value.primaryGreen)
.read(value.primaryBlue)
@@ -420,13 +457,14 @@
}
};
-template <>
-struct MetadataValue<std::optional<Cta861_3>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<Cta861_3>> {
[[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
void* _Nullable destBuffer, size_t destBufferSize) {
if (optValue.has_value()) {
const auto& value = *optValue;
return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
.write(value.maxContentLightLevel)
.write(value.maxFrameAverageLightLevel)
.desiredSize();
@@ -441,6 +479,7 @@
std::optional<Cta861_3> optValue{std::nullopt};
if (metadataSize > 0) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
Cta861_3 value;
reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
if (reader.ok()) {
@@ -453,14 +492,17 @@
}
};
-template <>
-struct MetadataValue<std::optional<std::vector<uint8_t>>> {
+template <typename HEADER>
+struct MetadataValue<HEADER, std::optional<std::vector<uint8_t>>> {
[[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
void* _Nullable destBuffer, size_t destBufferSize) {
if (!value.has_value()) {
return 0;
}
- return MetadataWriter{destBuffer, destBufferSize}.write(*value).desiredSize();
+ return MetadataWriter{destBuffer, destBufferSize}
+ .template writeHeader<HEADER>()
+ .write(*value)
+ .desiredSize();
}
using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
@@ -468,6 +510,7 @@
std::optional<std::vector<uint8_t>> optValue;
if (metadataSize > 0) {
MetadataReader reader{metadata, metadataSize};
+ reader.template checkHeader<HEADER>();
auto value = reader.readBuffer();
if (reader.ok()) {
optValue = std::move(value);
@@ -482,16 +525,20 @@
template <StandardMetadataType>
struct StandardMetadata {};
-#define DEFINE_TYPE(name, typeArg) \
- template <> \
- struct StandardMetadata<StandardMetadataType::name> { \
- using value_type = typeArg; \
- using value = MetadataValue<value_type>; \
- static_assert( \
- StandardMetadataType::name == \
- ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
- StandardMetadataType::name)], \
- "StandardMetadataType must have equivalent value to index"); \
+#define DEFINE_TYPE(typeName, typeArg) \
+ template <> \
+ struct StandardMetadata<StandardMetadataType::typeName> { \
+ using value_type = typeArg; \
+ struct Header { \
+ static constexpr auto name = "android.hardware.graphics.common.StandardMetadataType"; \
+ static constexpr auto value = static_cast<int64_t>(StandardMetadataType::typeName); \
+ }; \
+ using value = MetadataValue<Header, value_type>; \
+ static_assert( \
+ StandardMetadataType::typeName == \
+ ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
+ StandardMetadataType::typeName)], \
+ "StandardMetadataType must have equivalent value to index"); \
}
DEFINE_TYPE(BUFFER_ID, uint64_t);
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 326346c..85246ee 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -234,7 +234,7 @@
sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
buffer.data(), buffer.size());
}
- if (sizeRequired < 0 || sizeRequired >= buffer.size()) {
+ if (sizeRequired < 0 || sizeRequired > buffer.size()) {
ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
<< " with buffer size " << buffer.size();
// Generate a fail type
diff --git a/input/OWNERS b/input/OWNERS
new file mode 100644
index 0000000..21d208f
--- /dev/null
+++ b/input/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 136048
+include platform/frameworks/base:/INPUT_OWNERS
diff --git a/media/OWNERS b/media/OWNERS
new file mode 100644
index 0000000..71a53ef
--- /dev/null
+++ b/media/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 25690
+
+# Media team
+jgus@google.com
+lajos@google.com
+taklee@google.com
+wonsik@google.com
diff --git a/media/bufferpool/aidl/Android.bp b/media/bufferpool/aidl/Android.bp
index 68ac489..5ea2948 100644
--- a/media/bufferpool/aidl/Android.bp
+++ b/media/bufferpool/aidl/Android.bp
@@ -24,6 +24,7 @@
aidl_interface {
name: "android.hardware.media.bufferpool2",
vendor_available: true,
+ double_loadable: true,
srcs: ["android/hardware/media/bufferpool2/*.aidl"],
imports: [
"android.hardware.common-V2",
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
index 10867c0..56531db 100644
--- a/media/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -1,8 +1,18 @@
// This is the expected build file, but it may not be right in all cases
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
aidl_interface {
name: "android.hardware.media.c2",
vendor_available: true,
+ double_loadable: true,
srcs: ["android/hardware/media/c2/*.aidl"],
include_dirs: [
"frameworks/native/aidl/gui",
diff --git a/weaver/aidl/Android.bp b/weaver/aidl/Android.bp
index caa92aa..74cec99 100644
--- a/weaver/aidl/Android.bp
+++ b/weaver/aidl/Android.bp
@@ -17,5 +17,10 @@
platform_apis: true,
},
},
- versions: ["1"],
+ versions_with_info: [
+ {
+ version: "1",
+ imports: [],
+ },
+ ],
}
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
index 47ee4c8..96e528f 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,4 +36,5 @@
parcelable WeaverReadResponse {
long timeout;
byte[] value;
+ android.hardware.weaver.WeaverReadStatus status = android.hardware.weaver.WeaverReadStatus.FAILED;
}
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl
new file mode 100644
index 0000000..fce9758
--- /dev/null
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.weaver;
+@Backing(type="int") @VintfStability
+enum WeaverReadStatus {
+ OK = 0,
+ FAILED = 1,
+ INCORRECT_KEY = 2,
+ THROTTLE = 3,
+}
diff --git a/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
index ec006e8..17ea718 100644
--- a/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,22 @@
package android.hardware.weaver;
+import android.hardware.weaver.WeaverReadStatus;
+
@VintfStability
parcelable WeaverReadResponse {
/**
- * The time to wait, in milliseconds, before making the next request.
+ * The time to wait, in milliseconds, before making the next request,
+ * must be greater than or equal to zero and less than INT_MAX.
*/
long timeout;
/**
* The value read from the slot or empty if the value was not read.
*/
byte[] value;
+ /**
+ * Status from WeaverReadStatus
+ */
+ WeaverReadStatus status = WeaverReadStatus.FAILED;
}
diff --git a/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl b/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl
new file mode 100644
index 0000000..36e731f
--- /dev/null
+++ b/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.weaver;
+
+@VintfStability
+@Backing(type="int")
+enum WeaverReadStatus {
+ OK,
+ FAILED,
+ INCORRECT_KEY,
+ THROTTLE,
+}
diff --git a/weaver/aidl/default/Android.bp b/weaver/aidl/default/Android.bp
index 70d9171..494cb1b 100644
--- a/weaver/aidl/default/Android.bp
+++ b/weaver/aidl/default/Android.bp
@@ -34,7 +34,7 @@
"Weaver.cpp",
],
shared_libs: [
- "android.hardware.weaver-V1-ndk",
+ "android.hardware.weaver-V2-ndk",
"libbase",
"libbinder_ndk",
],
diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp
index 6b77924..c9ffe85 100644
--- a/weaver/aidl/default/Weaver.cpp
+++ b/weaver/aidl/default/Weaver.cpp
@@ -37,18 +37,19 @@
}
::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector<uint8_t>& in_key, WeaverReadResponse* out_response) {
+ using ::aidl::android::hardware::weaver::WeaverReadStatus;
if (in_slotId > 15 || in_key.size() > 16) {
- *out_response = {0, {}};
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_FAILED));
+ *out_response = {0, {}, WeaverReadStatus::FAILED};
+ return ndk::ScopedAStatus::ok();
}
if (slot_array[in_slotId].key != in_key) {
- *out_response = {0, {}};
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_INCORRECT_KEY));
+ *out_response = {0, {}, WeaverReadStatus::INCORRECT_KEY};
+ return ndk::ScopedAStatus::ok();
}
- *out_response = {0, slot_array[in_slotId].value};
+ *out_response = {0, slot_array[in_slotId].value, WeaverReadStatus::OK};
return ::ndk::ScopedAStatus::ok();
}
diff --git a/weaver/aidl/default/android.hardware.weaver-service.example.xml b/weaver/aidl/default/android.hardware.weaver-service.example.xml
index ed291cd..bfe4396 100644
--- a/weaver/aidl/default/android.hardware.weaver-service.example.xml
+++ b/weaver/aidl/default/android.hardware.weaver-service.example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.weaver</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IWeaver</name>
<instance>default</instance>
diff --git a/weaver/aidl/vts/Android.bp b/weaver/aidl/vts/Android.bp
index cf1661c..557fe47 100644
--- a/weaver/aidl/vts/Android.bp
+++ b/weaver/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
"libbinder_ndk",
"libbase",
],
- static_libs: ["android.hardware.weaver-V1-ndk"],
+ static_libs: ["android.hardware.weaver-V2-ndk"],
test_suites: [
"general-tests",
"vts",
diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
index 878c762..f016515 100644
--- a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
+++ b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
@@ -25,6 +25,7 @@
using ::aidl::android::hardware::weaver::IWeaver;
using ::aidl::android::hardware::weaver::WeaverConfig;
using ::aidl::android::hardware::weaver::WeaverReadResponse;
+using ::aidl::android::hardware::weaver::WeaverReadStatus;
using ::ndk::SpAIBinder;
@@ -102,14 +103,17 @@
WeaverReadResponse response;
std::vector<uint8_t> readValue;
uint32_t timeout;
+ WeaverReadStatus status;
const auto readRet = weaver->read(slotId, KEY, &response);
readValue = response.value;
timeout = response.timeout;
+ status = response.status;
ASSERT_TRUE(readRet.isOk());
EXPECT_EQ(readValue, VALUE);
EXPECT_EQ(timeout, 0u);
+ EXPECT_EQ(status, WeaverReadStatus::OK);
}
/*
@@ -128,14 +132,17 @@
WeaverReadResponse response;
std::vector<uint8_t> readValue;
uint32_t timeout;
+ WeaverReadStatus status;
const auto readRet = weaver->read(slotId, KEY, &response);
readValue = response.value;
timeout = response.timeout;
+ status = response.status;
ASSERT_TRUE(readRet.isOk());
EXPECT_EQ(readValue, OTHER_VALUE);
EXPECT_EQ(timeout, 0u);
+ EXPECT_EQ(status, WeaverReadStatus::OK);
}
/*
@@ -149,15 +156,16 @@
WeaverReadResponse response;
std::vector<uint8_t> readValue;
+ WeaverReadStatus status;
const auto readRet =
weaver->read(slotId, WRONG_KEY, &response);
readValue = response.value;
+ status = response.status;
- ASSERT_FALSE(readRet.isOk());
- ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
- ASSERT_EQ(IWeaver::STATUS_INCORRECT_KEY, readRet.getServiceSpecificError());
+ ASSERT_TRUE(readRet.isOk());
EXPECT_TRUE(readValue.empty());
+ EXPECT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
}
/*
@@ -193,17 +201,18 @@
WeaverReadResponse response;
std::vector<uint8_t> readValue;
uint32_t timeout;
+ WeaverReadStatus status;
const auto readRet =
weaver->read(config.slots, KEY, &response);
readValue = response.value;
timeout = response.timeout;
+ status = response.status;
- ASSERT_FALSE(readRet.isOk());
- ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
- ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
+ ASSERT_TRUE(readRet.isOk());
EXPECT_TRUE(readValue.empty());
EXPECT_EQ(timeout, 0u);
+ EXPECT_EQ(status, WeaverReadStatus::FAILED);
}
/*
@@ -250,17 +259,18 @@
WeaverReadResponse response;
std::vector<uint8_t> readValue;
uint32_t timeout;
+ WeaverReadStatus status;
const auto readRet =
weaver->read(slotId, bigKey, &response);
readValue = response.value;
timeout = response.timeout;
+ status = response.status;
- ASSERT_FALSE(readRet.isOk());
- ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
- ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
+ ASSERT_TRUE(readRet.isOk());
EXPECT_TRUE(readValue.empty());
EXPECT_EQ(timeout, 0u);
+ EXPECT_EQ(status, WeaverReadStatus::FAILED);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverAidlTest);
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppConfigurationData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppConfigurationData.aidl
new file mode 100644
index 0000000..2225330
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppConfigurationData.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable DppConfigurationData {
+ byte[] ssid;
+ String password;
+ byte[] psk;
+ android.hardware.wifi.supplicant.DppAkm securityAkm;
+ android.hardware.wifi.supplicant.DppConnectionKeys dppConnectionKeys;
+ boolean connStatusRequested;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl
new file mode 100644
index 0000000..d72633b
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppStatusErrorCode {
+ UNKNOWN = -1,
+ SUCCESS = 0,
+ NOT_COMPATIBLE = 1,
+ AUTH_FAILURE = 2,
+ UNWRAP_FAILURE = 3,
+ BAD_GROUP = 4,
+ CONFIGURE_FAILURE = 5,
+ RESPONSE_PENDING = 6,
+ INVALID_CONNECTOR = 7,
+ NO_MATCH = 8,
+ CONFIG_REJECTED = 9,
+ NO_AP = 10,
+ CONFIGURE_PENDING = 11,
+ CSR_NEEDED = 12,
+ CSR_BAD = 13,
+ NEW_KEY_NEEDED = 14,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index efd51b5b..45563b3 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -44,6 +44,9 @@
oneway void onDppFailure(in android.hardware.wifi.supplicant.DppFailureCode code, in String ssid, in String channelList, in char[] bandList);
oneway void onDppProgress(in android.hardware.wifi.supplicant.DppProgressCode code);
oneway void onDppSuccess(in android.hardware.wifi.supplicant.DppEventType event);
+ /**
+ * @deprecated This callback is deprecated from AIDL v2, newer HAL should call onDppConfigReceived.
+ */
oneway void onDppSuccessConfigReceived(in byte[] ssid, in String password, in byte[] psk, in android.hardware.wifi.supplicant.DppAkm securityAkm, in android.hardware.wifi.supplicant.DppConnectionKeys dppConnectionKeys);
oneway void onDppSuccessConfigSent();
oneway void onEapFailure(in byte[] bssid, in int errorCode);
@@ -65,6 +68,8 @@
oneway void onQosPolicyRequest(in int qosPolicyRequestId, in android.hardware.wifi.supplicant.QosPolicyData[] qosPolicyData);
oneway void onStateChangedWithAkm(in android.hardware.wifi.supplicant.StaIfaceCallbackState newState, in byte[] bssid, in int id, in byte[] ssid, in boolean filsHlpSent, in android.hardware.wifi.supplicant.KeyMgmtMask keyMgmtMask);
oneway void onMloLinksInfoChanged(in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.MloLinkInfoChangeReason reason);
+ oneway void onDppConfigReceived(in android.hardware.wifi.supplicant.DppConfigurationData configData);
+ oneway void onDppConnectionStatusResultSent(in android.hardware.wifi.supplicant.DppStatusErrorCode code);
@Backing(type="int") @VintfStability
enum MloLinkInfoChangeReason {
TID_TO_LINK_MAP = 0,
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppConfigurationData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppConfigurationData.aidl
new file mode 100644
index 0000000..b25bc40
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppConfigurationData.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppConnectionKeys;
+
+/**
+ * DPP configuration related information.
+ */
+@VintfStability
+parcelable DppConfigurationData {
+ /*
+ * SSID of the network.
+ */
+ byte[] ssid;
+ /*
+ * WPA2 or SAE passphrase.
+ */
+ String password;
+ /*
+ * Pre-shared key encoded in hex.
+ */
+ byte[] psk;
+ /*
+ * AKM that can be provisioned using DPP.
+ */
+ DppAkm securityAkm;
+ /*
+ * Connection keys that are used for DPP network connection.
+ */
+ DppConnectionKeys dppConnectionKeys;
+ /*
+ * Optional flag to indicate that the configurator requested connection status
+ * result.
+ * This flag is set to true if the enrollee receives the configuration response
+ * frame with sendConnStatus attribute.
+ */
+ boolean connStatusRequested;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl
new file mode 100644
index 0000000..30965d6
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppStatusErrorCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppStatusErrorCode: The possible values for the DPP status and error codes
+ * in the DPP protocol.
+ * See Easy Connect specification V2.0 section 8.3.4 for details.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppStatusErrorCode {
+ UNKNOWN = -1,
+ SUCCESS = 0,
+ NOT_COMPATIBLE = 1,
+ AUTH_FAILURE = 2,
+ UNWRAP_FAILURE = 3,
+ BAD_GROUP = 4,
+ CONFIGURE_FAILURE = 5,
+ RESPONSE_PENDING = 6,
+ INVALID_CONNECTOR = 7,
+ NO_MATCH = 8,
+ CONFIG_REJECTED = 9,
+ NO_AP = 10,
+ CONFIGURE_PENDING = 11,
+ CSR_NEEDED = 12,
+ CSR_BAD = 13,
+ NEW_KEY_NEEDED = 14,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 4bd095e..29bb0f9 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -22,10 +22,12 @@
import android.hardware.wifi.supplicant.BssTmData;
import android.hardware.wifi.supplicant.BssidChangeReason;
import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppConfigurationData;
import android.hardware.wifi.supplicant.DppConnectionKeys;
import android.hardware.wifi.supplicant.DppEventType;
import android.hardware.wifi.supplicant.DppFailureCode;
import android.hardware.wifi.supplicant.DppProgressCode;
+import android.hardware.wifi.supplicant.DppStatusErrorCode;
import android.hardware.wifi.supplicant.Hs20AnqpData;
import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.OsuMethod;
@@ -144,6 +146,9 @@
* Indicates DPP configuration received success event in Enrolee mode.
* This is also triggered when Configurator generates credentials for itself
* using generateSelfDppConfiguration() API
+ * <p>
+ * @deprecated This callback is deprecated from AIDL v2, newer HAL should call
+ * onDppConfigReceived.
*/
void onDppSuccessConfigReceived(in byte[] ssid, in String password, in byte[] psk,
in DppAkm securityAkm, in DppConnectionKeys dppConnectionKeys);
@@ -367,4 +372,16 @@
* @param reason Reason as given in MloLinkInfoChangeReason.
*/
void onMloLinksInfoChanged(in MloLinkInfoChangeReason reason);
+
+ /**
+ * Indicates DPP configuration received success event in Enrollee mode.
+ * This is also triggered when Configurator generates credentials for itself
+ * using generateSelfDppConfiguration() API
+ */
+ void onDppConfigReceived(in DppConfigurationData configData);
+
+ /**
+ * Indicates that DPP connection status result frame is sent.
+ */
+ void onDppConnectionStatusResultSent(in DppStatusErrorCode code);
}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
index e42608e..cb2881b 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -218,6 +218,15 @@
MloLinkInfoChangeReason /* reason */) override {
return ndk::ScopedAStatus::ok();
}
+ ::ndk::ScopedAStatus onDppConfigReceived(
+ const ::aidl::android::hardware::wifi::supplicant::
+ DppConfigurationData& /* configData */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppConnectionStatusResultSent(
+ ::aidl::android::hardware::wifi::supplicant::DppStatusErrorCode /* code */) override {
+ return ndk::ScopedAStatus::ok();
+ }
};
class SupplicantStaIfaceAidlTest : public testing::TestWithParam<std::string> {