[automerger skipped] Allow extra error code in device ID attestation am: 94042a987c am: 7a46f5c9aa am: 6d11e19f39 -s ours
am skip reason: Merged-In Ic01c53cbe79f55c2d403a66acbfd04029395c287 with SHA-1 f42238c99f is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/23916423
Change-Id: I16bde6c020c62fa9747c3a489cde6f1e1c324fdd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 3e06595..81c99f7 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "VtsHalAudioCoreTargetTest"
},
{
+ "name": "audio_policy_config_xml_converter_tests"
+ },
+ {
"name": "VtsHalAudioEffectFactoryTargetTest"
},
{
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 305c924..3b08de7 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -29,6 +29,21 @@
#include <aidl/android/media/audio/common/AudioMode.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include <aidl/android/media/audio/common/PcmType.h>
+#include <android/binder_auto_utils.h>
+
+namespace ndk {
+
+// This enables use of 'error/expected_utils' for ScopedAStatus.
+
+inline bool errorIsOk(const ScopedAStatus& s) {
+ return s.isOk();
+}
+
+inline std::string errorToString(const ScopedAStatus& s) {
+ return s.getDescription();
+}
+
+} // namespace ndk
namespace aidl::android::hardware::audio::common {
@@ -102,7 +117,8 @@
constexpr bool isDefaultAudioFormat(
const ::aidl::android::media::audio::common::AudioFormatDescription& desc) {
return desc.type == ::aidl::android::media::audio::common::AudioFormatType::DEFAULT &&
- desc.pcm == ::aidl::android::media::audio::common::PcmType::DEFAULT;
+ desc.pcm == ::aidl::android::media::audio::common::PcmType::DEFAULT &&
+ desc.encoding.empty();
}
constexpr bool isTelephonyDeviceType(
@@ -111,30 +127,6 @@
device == ::aidl::android::media::audio::common::AudioDeviceType::OUT_TELEPHONY_TX;
}
-constexpr bool isUsbInputDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
- switch (type) {
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_DOCK:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_ACCESSORY:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_DEVICE:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_HEADSET:
- return true;
- default:
- return false;
- }
-}
-
-constexpr bool isUsbOutputtDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
- switch (type) {
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DOCK:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_ACCESSORY:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DEVICE:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_HEADSET:
- return true;
- default:
- return false;
- }
-}
-
constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode mode) {
return std::find(kValidAudioModes.begin(), kValidAudioModes.end(), mode) !=
kValidAudioModes.end();
diff --git a/audio/aidl/default/AidlConversionXsdc.cpp b/audio/aidl/default/AidlConversionXsdc.cpp
new file mode 100644
index 0000000..c404d67
--- /dev/null
+++ b/audio/aidl/default/AidlConversionXsdc.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_AidlXsdc"
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+
+#include "core-impl/AidlConversionXsdc.h"
+
+using aidl::android::media::audio::common::AudioFormatDescription;
+
+namespace xsd = android::audio::policy::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<AudioFormatDescription> xsdc2aidl_AudioFormatDescription(const std::string& xsdc) {
+ return legacy2aidl_audio_format_t_AudioFormatDescription(::android::formatFromString(xsdc));
+}
+
+ConversionResult<SurroundSoundConfig::SurroundFormatFamily> xsdc2aidl_SurroundFormatFamily(
+ const ::xsd::SurroundFormats::Format& xsdc) {
+ SurroundSoundConfig::SurroundFormatFamily aidl;
+ aidl.primaryFormat = VALUE_OR_RETURN(xsdc2aidl_AudioFormatDescription(xsdc.getName()));
+ if (xsdc.hasSubformats()) {
+ aidl.subFormats = VALUE_OR_RETURN(convertContainer<std::vector<AudioFormatDescription>>(
+ xsdc.getSubformats(), xsdc2aidl_AudioFormatDescription));
+ }
+ return aidl;
+}
+
+ConversionResult<SurroundSoundConfig> xsdc2aidl_SurroundSoundConfig(
+ const ::xsd::SurroundSound& xsdc) {
+ SurroundSoundConfig aidl;
+ if (!xsdc.hasFormats() || !xsdc.getFirstFormats()->hasFormat()) return aidl;
+ aidl.formatFamilies = VALUE_OR_RETURN(
+ convertContainer<std::vector<SurroundSoundConfig::SurroundFormatFamily>>(
+ xsdc.getFirstFormats()->getFormat(), xsdc2aidl_SurroundFormatFamily));
+ return aidl;
+}
+
+} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index c9edae0..78b59d4 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -18,6 +18,7 @@
"libbinder_ndk",
"libcutils",
"libfmq",
+ "libnbaio_mono",
"libstagefright_foundation",
"libtinyalsav2",
"libutils",
@@ -65,6 +66,7 @@
],
export_include_dirs: ["include"],
srcs: [
+ "AidlConversionXsdc.cpp",
"AudioPolicyConfigXmlConverter.cpp",
"Bluetooth.cpp",
"Config.cpp",
@@ -75,6 +77,10 @@
"Stream.cpp",
"StreamStub.cpp",
"Telephony.cpp",
+ "r_submix/ModuleRemoteSubmix.cpp",
+ "r_submix/RemoteSubmixUtils.cpp",
+ "r_submix/SubmixRoute.cpp",
+ "r_submix/StreamRemoteSubmix.cpp",
"usb/ModuleUsb.cpp",
"usb/StreamUsb.cpp",
"usb/UsbAlsaMixerControl.cpp",
@@ -92,6 +98,21 @@
"audio_policy_configuration_aidl_default",
"audio_policy_engine_configuration_aidl_default",
],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libmedia_helper",
+ "libstagefright_foundation",
+ ],
+ export_shared_lib_headers: [
+ "libaudio_aidl_conversion_common_ndk",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_NDK",
+ ],
}
cc_binary {
@@ -108,7 +129,63 @@
static_libs: [
"libaudioserviceexampleimpl",
],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libmedia_helper",
+ "libstagefright_foundation",
+ ],
srcs: ["main.cpp"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_NDK",
+ ],
+}
+
+cc_test {
+ name: "audio_policy_config_xml_converter_tests",
+ vendor_available: true,
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_static",
+ "latest_android_hardware_audio_core_ndk_static",
+ ],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudioaidlcommon",
+ "libaudioutils",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libmedia_helper",
+ "libstagefright_foundation",
+ "libutils",
+ "libxml2",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libaudioaidl_headers",
+ "libxsdc-utils",
+ ],
+ generated_sources: [
+ "audio_policy_configuration_aidl_default",
+ ],
+ generated_headers: [
+ "audio_policy_configuration_aidl_default",
+ ],
+ srcs: [
+ "AudioPolicyConfigXmlConverter.cpp",
+ "tests/AudioPolicyConfigXmlConverterTest.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_NDK",
+ ],
+ test_suites: ["general-tests"],
}
cc_defaults {
diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
index 6290912..7452c8e 100644
--- a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
+++ b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
@@ -21,11 +21,17 @@
#include <functional>
#include <unordered_map>
+#define LOG_TAG "AHAL_ApmXmlConverter"
+#include <android-base/logging.h>
+
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <system/audio-base-utils.h>
+#include "core-impl/AidlConversionXsdc.h"
#include "core-impl/AudioPolicyConfigXmlConverter.h"
+using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::common::AudioHalVolumeCurve;
using aidl::android::media::audio::common::AudioHalVolumeGroup;
@@ -68,13 +74,13 @@
getXsdcConfig()->getVolumes());
}
aidlVolumeCurve.curvePoints =
- convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+ convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
std::placeholders::_1));
} else {
aidlVolumeCurve.curvePoints =
- convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+ convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
xsdcVolumeCurve.getPoint(),
std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
std::placeholders::_1));
@@ -87,6 +93,22 @@
convertVolumeCurveToAidl(xsdcVolumeCurve));
}
+const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
+ static const SurroundSoundConfig aidlSurroundSoundConfig = [this]() {
+ if (auto xsdcConfig = getXsdcConfig(); xsdcConfig && xsdcConfig->hasSurroundSound()) {
+ auto configConv = xsdc2aidl_SurroundSoundConfig(*xsdcConfig->getFirstSurroundSound());
+ if (configConv.ok()) {
+ return configConv.value();
+ }
+ LOG(ERROR) << "There was an error converting surround formats to AIDL: "
+ << configConv.error();
+ }
+ LOG(WARNING) << "Audio policy config does not have <surroundSound> section, using default";
+ return getDefaultSurroundSoundConfig();
+ }();
+ return aidlSurroundSoundConfig;
+}
+
const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
getXsdcConfig()->hasVolumes()) {
@@ -95,6 +117,47 @@
return mAidlEngineConfig;
}
+// static
+const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig() {
+ // Provide a config similar to the one used by the framework by default
+ // (see AudioPolicyConfig::setDefaultSurroundFormats).
+#define ENCODED_FORMAT(format) \
+ AudioFormatDescription { \
+ .encoding = ::android::format \
+ }
+#define SIMPLE_FORMAT(format) \
+ SurroundSoundConfig::SurroundFormatFamily { \
+ .primaryFormat = ENCODED_FORMAT(format) \
+ }
+
+ static const SurroundSoundConfig defaultConfig = {
+ .formatFamilies = {
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC3),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD),
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3_JOC),
+ SurroundSoundConfig::SurroundFormatFamily{
+ .primaryFormat = ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_LC),
+ .subFormats =
+ {
+ ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1),
+ ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2),
+ ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_ELD),
+ ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_XHE),
+ }},
+ SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC4),
+ }};
+#undef SIMPLE_FORMAT
+#undef ENCODED_FORMAT
+
+ return defaultConfig;
+}
+
void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
if (getXsdcConfig()->hasVolumes()) {
for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index 87c0ace..d1023da 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -27,9 +27,16 @@
namespace aidl::android::hardware::audio::core {
ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
- SurroundSoundConfig surroundSoundConfig;
- // TODO: parse from XML; for now, use empty config as default
- *_aidl_return = std::move(surroundSoundConfig);
+ static const SurroundSoundConfig surroundSoundConfig = [this]() {
+ SurroundSoundConfig surroundCfg;
+ if (mAudioPolicyConverter.getStatus() == ::android::OK) {
+ surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
+ } else {
+ LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
+ }
+ return surroundCfg;
+ }();
+ *_aidl_return = surroundSoundConfig;
LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
return ndk::ScopedAStatus::ok();
}
@@ -47,10 +54,14 @@
LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
}
}
+ // Logging full contents of the config is an overkill, just provide statistics.
+ LOG(DEBUG) << "getEngineConfig: number of strategies parsed: "
+ << engConfig.productStrategies.size()
+ << ", default strategy: " << engConfig.defaultProductStrategyId
+ << ", number of volume groups parsed: " << engConfig.volumeGroups.size();
return engConfig;
}();
*_aidl_return = returnEngCfg;
- LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index e1e1f79..d41ea67 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -81,6 +81,8 @@
deviceExt.device.address = "bottom";
} else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
deviceExt.device.address = "back";
+ } else if (devType == AudioDeviceType::IN_SUBMIX || devType == AudioDeviceType::OUT_SUBMIX) {
+ deviceExt.device.address = "0";
}
deviceExt.device.type.connection = std::move(connection);
deviceExt.flags = flags;
@@ -365,8 +367,10 @@
// Device ports
- AudioPort rsubmixOutDevice = createPort(c.nextPortId++, "Remote Submix Out", 0, false,
- createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
+ AudioPort rsubmixOutDevice =
+ createPort(c.nextPortId++, "Remote Submix Out", 0, false,
+ createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
+ AudioDeviceDescription::CONNECTION_VIRTUAL));
rsubmixOutDevice.profiles.push_back(
createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
c.ports.push_back(rsubmixOutDevice);
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index 71d111b..f3f674f 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -18,6 +18,7 @@
#include <string>
#define LOG_TAG "AHAL_EffectConfig"
#include <android-base/logging.h>
+#include <system/audio_aidl_utils.h>
#include <system/audio_effects/audio_effects_conf.h>
#include <system/audio_effects/effect_uuid.h>
@@ -162,7 +163,7 @@
RETURN_VALUE_IF((libraryUuid.uuid == getEffectUuidZero()), false, "invalidUuidAttribute");
LOG(DEBUG) << __func__ << (isProxy ? " proxy " : libraryUuid.name) << " : "
- << libraryUuid.uuid.toString();
+ << ::android::audio::utils::toString(libraryUuid.uuid);
return true;
}
@@ -250,6 +251,7 @@
V("downmix", Downmix) \
V("dynamics_processing", DynamicsProcessing) \
V("equalizer", Equalizer) \
+ V("extensioneffect", Extension) \
V("haptic_generator", HapticGenerator) \
V("loudness_enhancer", LoudnessEnhancer) \
V("env_reverb", EnvReverb) \
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index 7073a10..8ed62c9 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -25,6 +25,7 @@
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
+#include <system/audio_aidl_utils.h>
#include <system/audio_effects/effect_uuid.h>
#include <system/thread_defs.h>
@@ -47,7 +48,7 @@
for (const auto& it : mEffectMap) {
if (auto spEffect = it.first.lock()) {
LOG(ERROR) << __func__ << " erase remaining instance UUID "
- << it.second.first.toString();
+ << ::android::audio::utils::toString(it.second.first);
destroyEffectImpl(spEffect);
}
}
@@ -123,7 +124,7 @@
ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
std::shared_ptr<IEffect>* _aidl_return) {
- LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
+ LOG(DEBUG) << __func__ << ": UUID " << ::android::audio::utils::toString(in_impl_uuid);
if (mEffectLibMap.count(in_impl_uuid)) {
auto& entry = mEffectLibMap[in_impl_uuid];
getDlSyms(entry);
@@ -163,7 +164,8 @@
"dlNulldestroyEffectFunc");
RETURN_IF_BINDER_EXCEPTION(interface->destroyEffectFunc(in_handle));
} else {
- LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
+ LOG(ERROR) << __func__ << ": UUID " << ::android::audio::utils::toString(uuid)
+ << " does not exist in libMap!";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
mEffectMap.erase(effectIt);
@@ -207,8 +209,8 @@
return false;
}
- LOG(INFO) << __func__ << " dlopen lib:" << path << "\nimpl:" << impl.toString()
- << "\nhandle:" << libHandle;
+ LOG(INFO) << __func__ << " dlopen lib:" << path
+ << "\nimpl:" << ::android::audio::utils::toString(impl) << "\nhandle:" << libHandle;
auto interface = new effect_dl_interface_s{nullptr, nullptr, nullptr};
mEffectLibMap.insert(
{impl,
@@ -228,8 +230,10 @@
id.uuid = configLib.uuid;
id.proxy = proxyUuid;
LOG(DEBUG) << __func__ << " loading lib " << path->second << ": typeUuid "
- << id.type.toString() << "\nimplUuid " << id.uuid.toString() << " proxyUuid "
- << (proxyUuid.has_value() ? proxyUuid->toString() : "null");
+ << ::android::audio::utils::toString(id.type) << "\nimplUuid "
+ << ::android::audio::utils::toString(id.uuid) << " proxyUuid "
+ << (proxyUuid.has_value() ? ::android::audio::utils::toString(proxyUuid.value())
+ : "null");
if (openEffectLibrary(id.uuid, path->second)) {
mIdentitySet.insert(std::move(id));
}
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 5f17d71..96b555c 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -140,7 +140,7 @@
aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
if (xsdcAttributesGroup.hasAttributes_optional()) {
aidlAttributesGroup.attributes =
- convertCollectionToAidl<xsd::AttributesType, AudioAttributes>(
+ convertCollectionToAidlUnchecked<xsd::AttributesType, AudioAttributes>(
xsdcAttributesGroup.getAttributes_optional(),
std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
std::placeholders::_1));
@@ -172,7 +172,7 @@
if (xsdcProductStrategy.hasAttributesGroup()) {
aidlProductStrategy.attributesGroups =
- convertCollectionToAidl<xsd::AttributesGroup, AudioHalAttributesGroup>(
+ convertCollectionToAidlUnchecked<xsd::AttributesGroup, AudioHalAttributesGroup>(
xsdcProductStrategy.getAttributesGroup(),
std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
std::placeholders::_1));
@@ -204,13 +204,13 @@
getXsdcConfig()->getVolumes());
}
aidlVolumeCurve.curvePoints =
- convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+ convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
std::placeholders::_1));
} else {
aidlVolumeCurve.curvePoints =
- convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+ convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
xsdcVolumeCurve.getPoint(),
std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
std::placeholders::_1));
@@ -224,10 +224,11 @@
aidlVolumeGroup.name = xsdcVolumeGroup.getName();
aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
- aidlVolumeGroup.volumeCurves = convertCollectionToAidl<xsd::Volume, AudioHalVolumeCurve>(
- xsdcVolumeGroup.getVolume(),
- std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
- std::placeholders::_1));
+ aidlVolumeGroup.volumeCurves =
+ convertCollectionToAidlUnchecked<xsd::Volume, AudioHalVolumeCurve>(
+ xsdcVolumeGroup.getVolume(),
+ std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
+ std::placeholders::_1));
return aidlVolumeGroup;
}
@@ -251,7 +252,7 @@
aidlCapCriterionType.name = xsdcCriterionType.getName();
aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
aidlCapCriterionType.values =
- convertWrappedCollectionToAidl<xsd::ValuesType, xsd::ValueType, std::string>(
+ convertWrappedCollectionToAidlUnchecked<xsd::ValuesType, xsd::ValueType, std::string>(
xsdcCriterionType.getValues(), &xsd::ValuesType::getValue,
std::bind(&EngineConfigXmlConverter::convertCriterionTypeValueToAidl, this,
std::placeholders::_1));
@@ -266,9 +267,9 @@
initProductStrategyMap();
if (getXsdcConfig()->hasProductStrategies()) {
mAidlEngineConfig.productStrategies =
- convertWrappedCollectionToAidl<xsd::ProductStrategies,
- xsd::ProductStrategies::ProductStrategy,
- AudioHalProductStrategy>(
+ convertWrappedCollectionToAidlUnchecked<xsd::ProductStrategies,
+ xsd::ProductStrategies::ProductStrategy,
+ AudioHalProductStrategy>(
getXsdcConfig()->getProductStrategies(),
&xsd::ProductStrategies::getProductStrategy,
std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
@@ -278,7 +279,7 @@
}
}
if (getXsdcConfig()->hasVolumeGroups()) {
- mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidl<
+ mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidlUnchecked<
xsd::VolumeGroupsType, xsd::VolumeGroupsType::VolumeGroup, AudioHalVolumeGroup>(
getXsdcConfig()->getVolumeGroups(), &xsd::VolumeGroupsType::getVolumeGroup,
std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
@@ -287,19 +288,17 @@
if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
capSpecificConfig.criteria =
- convertWrappedCollectionToAidl<xsd::CriteriaType, xsd::CriterionType,
- AudioHalCapCriterion>(
+ convertWrappedCollectionToAidlUnchecked<xsd::CriteriaType, xsd::CriterionType,
+ AudioHalCapCriterion>(
getXsdcConfig()->getCriteria(), &xsd::CriteriaType::getCriterion,
std::bind(&EngineConfigXmlConverter::convertCapCriterionToAidl, this,
std::placeholders::_1));
- capSpecificConfig.criterionTypes =
- convertWrappedCollectionToAidl<xsd::CriterionTypesType, xsd::CriterionTypeType,
- AudioHalCapCriterionType>(
- getXsdcConfig()->getCriterion_types(),
- &xsd::CriterionTypesType::getCriterion_type,
- std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
- std::placeholders::_1));
+ capSpecificConfig.criterionTypes = convertWrappedCollectionToAidlUnchecked<
+ xsd::CriterionTypesType, xsd::CriterionTypeType, AudioHalCapCriterionType>(
+ getXsdcConfig()->getCriterion_types(), &xsd::CriterionTypesType::getCriterion_type,
+ std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
+ std::placeholders::_1));
mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
}
}
-} // namespace aidl::android::hardware::audio::core::internal
\ No newline at end of file
+} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 6b417a4..48d1458 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -18,19 +18,19 @@
#include <set>
#define LOG_TAG "AHAL_Module"
-#include <android-base/logging.h>
-#include <android/binder_ibinder_platform.h>
-
#include <Utils.h>
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <error/expected_utils.h>
#include "core-impl/Bluetooth.h"
#include "core-impl/Module.h"
+#include "core-impl/ModuleRemoteSubmix.h"
#include "core-impl/ModuleUsb.h"
#include "core-impl/SoundDose.h"
#include "core-impl/StreamStub.h"
-#include "core-impl/StreamUsb.h"
#include "core-impl/Telephony.h"
#include "core-impl/utils.h"
@@ -112,37 +112,14 @@
switch (type) {
case Module::Type::USB:
return ndk::SharedRefBase::make<ModuleUsb>(type);
- case Type::DEFAULT:
case Type::R_SUBMIX:
+ return ndk::SharedRefBase::make<ModuleRemoteSubmix>(type);
+ case Type::DEFAULT:
default:
return ndk::SharedRefBase::make<Module>(type);
}
}
-// static
-StreamIn::CreateInstance Module::getStreamInCreator(Type type) {
- switch (type) {
- case Type::USB:
- return StreamInUsb::createInstance;
- case Type::DEFAULT:
- case Type::R_SUBMIX:
- default:
- return StreamInStub::createInstance;
- }
-}
-
-// static
-StreamOut::CreateInstance Module::getStreamOutCreator(Type type) {
- switch (type) {
- case Type::USB:
- return StreamOutUsb::createInstance;
- case Type::DEFAULT:
- case Type::R_SUBMIX:
- default:
- return StreamOutStub::createInstance;
- }
-}
-
std::ostream& operator<<(std::ostream& os, Module::Type t) {
switch (t) {
case Module::Type::DEFAULT:
@@ -187,7 +164,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
LOG(DEBUG) << __func__ << ": frame size " << frameSize << " bytes";
- if (frameSize > kMaximumStreamBufferSizeBytes / in_bufferSizeFrames) {
+ if (frameSize > static_cast<size_t>(kMaximumStreamBufferSizeBytes / in_bufferSizeFrames)) {
LOG(ERROR) << __func__ << ": buffer size " << in_bufferSizeFrames
<< " frames is too large, maximum size is "
<< kMaximumStreamBufferSizeBytes / frameSize;
@@ -206,8 +183,9 @@
StreamContext temp(
std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
- portConfigIt->format.value(), portConfigIt->channelMask.value(),
- portConfigIt->sampleRate.value().value,
+ portConfigIt->portId, portConfigIt->format.value(),
+ portConfigIt->channelMask.value(), portConfigIt->sampleRate.value().value, flags,
+ portConfigIt->ext.get<AudioPortExt::mix>().handle,
std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
asyncCallback, outEventCallback, params);
if (temp.isValid()) {
@@ -281,7 +259,7 @@
<< " does not correspond to a mix port";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- const int32_t maxOpenStreamCount = portIt->ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
+ const size_t maxOpenStreamCount = portIt->ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
if (maxOpenStreamCount != 0 && mStreams.count(portId) >= maxOpenStreamCount) {
LOG(ERROR) << __func__ << ": port id " << portId
<< " has already reached maximum allowed opened stream count: "
@@ -339,30 +317,61 @@
do_insert(patch.sinkPortConfigIds);
}
-void Module::updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch) {
+ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatch,
+ const AudioPatch& newPatch) {
// Streams from the old patch need to be disconnected, streams from the new
// patch need to be connected. If the stream belongs to both patches, no need
// to update it.
- std::set<int32_t> idsToDisconnect, idsToConnect;
+ auto maybeFailure = ndk::ScopedAStatus::ok();
+ std::set<int32_t> idsToDisconnect, idsToConnect, idsToDisconnectOnFailure;
idsToDisconnect.insert(oldPatch.sourcePortConfigIds.begin(),
oldPatch.sourcePortConfigIds.end());
idsToDisconnect.insert(oldPatch.sinkPortConfigIds.begin(), oldPatch.sinkPortConfigIds.end());
idsToConnect.insert(newPatch.sourcePortConfigIds.begin(), newPatch.sourcePortConfigIds.end());
idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end());
std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) {
- if (idsToConnect.count(portConfigId) == 0) {
- LOG(DEBUG) << "The stream on port config id " << portConfigId << " is not connected";
- mStreams.setStreamIsConnected(portConfigId, {});
+ if (idsToConnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
+ if (auto status = mStreams.setStreamConnectedDevices(portConfigId, {}); status.isOk()) {
+ LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
+ << portConfigId << " has been disconnected";
+ } else {
+ // Disconnection is tricky to roll back, just register a failure.
+ maybeFailure = std::move(status);
+ }
}
});
+ if (!maybeFailure.isOk()) return maybeFailure;
std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) {
- if (idsToDisconnect.count(portConfigId) == 0) {
+ if (idsToDisconnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
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);
+ if (connectedDevices.empty()) {
+ // This is important as workers use the vector size to derive the connection status.
+ LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port "
+ "config id "
+ << portConfigId;
+ }
+ if (auto status = mStreams.setStreamConnectedDevices(portConfigId, connectedDevices);
+ status.isOk()) {
+ LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
+ << portConfigId << " has been connected to: "
+ << ::android::internal::ToString(connectedDevices);
+ } else {
+ maybeFailure = std::move(status);
+ idsToDisconnectOnFailure.insert(portConfigId);
+ }
}
});
+ if (!maybeFailure.isOk()) {
+ LOG(WARNING) << __func__ << ": Due to a failure, disconnecting streams on port config ids "
+ << ::android::internal::ToString(idsToDisconnectOnFailure);
+ std::for_each(idsToDisconnectOnFailure.begin(), idsToDisconnectOnFailure.end(),
+ [&](const auto& portConfigId) {
+ auto status = mStreams.setStreamConnectedDevices(portConfigId, {});
+ (void)status.isOk(); // Can't do much about a failure here.
+ });
+ return maybeFailure;
+ }
+ return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Module::setModuleDebug(
@@ -469,10 +478,7 @@
}
if (!mDebug.simulateDeviceConnections) {
- if (ndk::ScopedAStatus status = populateConnectedDevicePort(&connectedPort);
- !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
} else {
auto& connectedProfiles = getConfig().connectedProfiles;
if (auto connectedProfilesIt = connectedProfiles.find(templateId);
@@ -486,6 +492,17 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
+ for (auto profile : connectedPort.profiles) {
+ if (profile.channelMasks.empty()) {
+ LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no channel masks";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (profile.sampleRates.empty()) {
+ LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no sample rates";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+
connectedPort.id = ++getConfig().nextPortId;
auto [connectedPortsIt, _] =
mConnectedDevicePorts.insert(std::pair(connectedPort.id, std::vector<int32_t>()));
@@ -647,34 +664,26 @@
LOG(DEBUG) << __func__ << ": port config id " << in_args.portConfigId << ", buffer size "
<< in_args.bufferSizeFrames << " frames";
AudioPort* port = nullptr;
- if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(findPortIdForNewStream(in_args.portConfigId, &port));
if (port->flags.getTag() != AudioIoFlags::Tag::input) {
LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
<< " does not correspond to an input mix port";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
StreamContext context;
- if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames, nullptr,
- nullptr, &context);
- !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
+ nullptr, nullptr, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamIn> stream;
- ndk::ScopedAStatus status = getStreamInCreator(mType)(in_args.sinkMetadata, std::move(context),
- mConfig->microphones, &stream);
- if (!status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(createInputStream(in_args.sinkMetadata, std::move(context),
+ mConfig->microphones, &stream));
StreamWrapper streamWrapper(stream);
+ if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
+ RETURN_STATUS_IF_ERROR(
+ streamWrapper.setConnectedDevices(findConnectedDevices(in_args.portConfigId)));
+ }
AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
- auto patchIt = mPatches.find(in_args.portConfigId);
- if (patchIt != mPatches.end()) {
- streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
- }
mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
_aidl_return->stream = std::move(stream);
return ndk::ScopedAStatus::ok();
@@ -686,9 +695,7 @@
<< (in_args.offloadInfo.has_value()) << ", buffer size " << in_args.bufferSizeFrames
<< " frames";
AudioPort* port = nullptr;
- if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(findPortIdForNewStream(in_args.portConfigId, &port));
if (port->flags.getTag() != AudioIoFlags::Tag::output) {
LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
<< " does not correspond to an output mix port";
@@ -709,26 +716,20 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
StreamContext context;
- if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
- isNonBlocking ? in_args.callback : nullptr,
- in_args.eventCallback, &context);
- !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
+ isNonBlocking ? in_args.callback : nullptr,
+ in_args.eventCallback, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamOut> stream;
- ndk::ScopedAStatus status = getStreamOutCreator(mType)(
- in_args.sourceMetadata, std::move(context), in_args.offloadInfo, &stream);
- if (!status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(createOutputStream(in_args.sourceMetadata, std::move(context),
+ in_args.offloadInfo, &stream));
StreamWrapper streamWrapper(stream);
+ if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
+ RETURN_STATUS_IF_ERROR(
+ streamWrapper.setConnectedDevices(findConnectedDevices(in_args.portConfigId)));
+ }
AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
- auto patchIt = mPatches.find(in_args.portConfigId);
- if (patchIt != mPatches.end()) {
- streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
- }
mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
_aidl_return->stream = std::move(stream);
return ndk::ScopedAStatus::ok();
@@ -796,10 +797,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
}
-
- if (auto status = checkAudioPatchEndpointsMatch(sources, sinks); !status.isOk()) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(checkAudioPatchEndpointsMatch(sources, sinks));
auto& patches = getConfig().patches;
auto existing = patches.end();
@@ -834,13 +832,20 @@
if (existing == patches.end()) {
_aidl_return->id = getConfig().nextPatchId++;
patches.push_back(*_aidl_return);
- existing = patches.begin() + (patches.size() - 1);
} else {
oldPatch = *existing;
- *existing = *_aidl_return;
}
- registerPatch(*existing);
- updateStreamsConnectedState(oldPatch, *_aidl_return);
+ patchesBackup = mPatches;
+ registerPatch(*_aidl_return);
+ if (auto status = updateStreamsConnectedState(oldPatch, *_aidl_return); !status.isOk()) {
+ mPatches = std::move(*patchesBackup);
+ if (existing == patches.end()) {
+ patches.pop_back();
+ } else {
+ *existing = oldPatch;
+ }
+ return status;
+ }
LOG(DEBUG) << __func__ << ": " << (oldPatch.id == 0 ? "created" : "updated") << " patch "
<< _aidl_return->toString();
@@ -992,8 +997,12 @@
auto& patches = getConfig().patches;
auto patchIt = findById<AudioPatch>(patches, in_patchId);
if (patchIt != patches.end()) {
+ auto patchesBackup = mPatches;
cleanUpPatch(patchIt->id);
- updateStreamsConnectedState(*patchIt, AudioPatch{});
+ if (auto status = updateStreamsConnectedState(*patchIt, AudioPatch{}); !status.isOk()) {
+ mPatches = std::move(patchesBackup);
+ return status;
+ }
patches.erase(patchIt);
LOG(DEBUG) << __func__ << ": erased patch " << in_patchId;
return ndk::ScopedAStatus::ok();
@@ -1325,6 +1334,22 @@
return mIsMmapSupported.value();
}
+ndk::ScopedAStatus Module::createInputStream(const SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
+ microphones);
+}
+
+ndk::ScopedAStatus Module::createOutputStream(const SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ std::shared_ptr<StreamOut>* result) {
+ return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
+ offloadInfo);
+}
+
ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort __unused) {
LOG(VERBOSE) << __func__ << ": do nothing and return ok";
return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 77b0601..251dea0 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -152,6 +152,7 @@
case Tag::halReservedExit:
if (const int32_t cookie = command.get<Tag::halReservedExit>();
cookie == mInternalCommandCookie) {
+ mDriver->shutdown();
setClosed();
// This is an internal command, no need to reply.
return Status::EXIT;
@@ -165,10 +166,15 @@
case Tag::start:
if (mState == StreamDescriptor::State::STANDBY ||
mState == StreamDescriptor::State::DRAINING) {
- populateReply(&reply, mIsConnected);
- mState = mState == StreamDescriptor::State::STANDBY
- ? StreamDescriptor::State::IDLE
- : StreamDescriptor::State::ACTIVE;
+ if (::android::status_t status = mDriver->start(); status == ::android::OK) {
+ populateReply(&reply, mIsConnected);
+ mState = mState == StreamDescriptor::State::STANDBY
+ ? StreamDescriptor::State::IDLE
+ : StreamDescriptor::State::ACTIVE;
+ } else {
+ LOG(ERROR) << __func__ << ": start failed: " << status;
+ mState = StreamDescriptor::State::ERROR;
+ }
} else {
populateReplyWrongState(&reply, command);
}
@@ -364,6 +370,7 @@
case Tag::halReservedExit:
if (const int32_t cookie = command.get<Tag::halReservedExit>();
cookie == mInternalCommandCookie) {
+ mDriver->shutdown();
setClosed();
// This is an internal command, no need to reply.
return Status::EXIT;
@@ -375,26 +382,36 @@
populateReply(&reply, mIsConnected);
break;
case Tag::start: {
- bool commandAccepted = true;
+ std::optional<StreamDescriptor::State> nextState;
switch (mState) {
case StreamDescriptor::State::STANDBY:
- mState = StreamDescriptor::State::IDLE;
+ nextState = StreamDescriptor::State::IDLE;
break;
case StreamDescriptor::State::PAUSED:
- mState = StreamDescriptor::State::ACTIVE;
+ nextState = StreamDescriptor::State::ACTIVE;
break;
case StreamDescriptor::State::DRAIN_PAUSED:
- switchToTransientState(StreamDescriptor::State::DRAINING);
+ nextState = StreamDescriptor::State::DRAINING;
break;
case StreamDescriptor::State::TRANSFER_PAUSED:
- switchToTransientState(StreamDescriptor::State::TRANSFERRING);
+ nextState = StreamDescriptor::State::TRANSFERRING;
break;
default:
populateReplyWrongState(&reply, command);
- commandAccepted = false;
}
- if (commandAccepted) {
- populateReply(&reply, mIsConnected);
+ if (nextState.has_value()) {
+ if (::android::status_t status = mDriver->start(); status == ::android::OK) {
+ populateReply(&reply, mIsConnected);
+ if (*nextState == StreamDescriptor::State::IDLE ||
+ *nextState == StreamDescriptor::State::ACTIVE) {
+ mState = *nextState;
+ } else {
+ switchToTransientState(*nextState);
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": start failed: " << status;
+ mState = StreamDescriptor::State::ERROR;
+ }
}
} break;
case Tag::burst:
@@ -567,8 +584,7 @@
return !fatal;
}
-template <class Metadata>
-StreamCommonImpl<Metadata>::~StreamCommonImpl() {
+StreamCommonImpl::~StreamCommonImpl() {
if (!isClosed()) {
LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
stopWorker();
@@ -576,19 +592,16 @@
}
}
-template <class Metadata>
-void StreamCommonImpl<Metadata>::createStreamCommon(
+ndk::ScopedAStatus StreamCommonImpl::initInstance(
const std::shared_ptr<StreamCommonInterface>& delegate) {
- if (mCommon != nullptr) {
- LOG(FATAL) << __func__ << ": attempting to create the common interface twice";
- }
- mCommon = ndk::SharedRefBase::make<StreamCommon>(delegate);
+ mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
mCommonBinder = mCommon->asBinder();
AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ return mWorker->start() ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::getStreamCommon(
+ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
std::shared_ptr<IStreamCommon>* _aidl_return) {
if (mCommon == nullptr) {
LOG(FATAL) << __func__ << ": the common interface was not created";
@@ -598,30 +611,26 @@
return ndk::ScopedAStatus::ok();
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::updateHwAvSyncId(int32_t in_hwAvSyncId) {
+ndk::ScopedAStatus StreamCommonImpl::updateHwAvSyncId(int32_t in_hwAvSyncId) {
LOG(DEBUG) << __func__ << ": id " << in_hwAvSyncId;
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::getVendorParameters(
+ndk::ScopedAStatus StreamCommonImpl::getVendorParameters(
const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) {
LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
(void)_aidl_return;
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::setVendorParameters(
+ndk::ScopedAStatus StreamCommonImpl::setVendorParameters(
const std::vector<VendorParameter>& in_parameters, bool in_async) {
LOG(DEBUG) << __func__ << ": parameters count " << in_parameters.size()
<< ", async: " << in_async;
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::addEffect(
+ndk::ScopedAStatus StreamCommonImpl::addEffect(
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
if (in_effect == nullptr) {
LOG(DEBUG) << __func__ << ": null effect";
@@ -631,8 +640,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::removeEffect(
+ndk::ScopedAStatus StreamCommonImpl::removeEffect(
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
if (in_effect == nullptr) {
LOG(DEBUG) << __func__ << ": null effect";
@@ -642,8 +650,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::close() {
+ndk::ScopedAStatus StreamCommonImpl::close() {
LOG(DEBUG) << __func__;
if (!isClosed()) {
stopWorker();
@@ -659,8 +666,7 @@
}
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::prepareToClose() {
+ndk::ScopedAStatus StreamCommonImpl::prepareToClose() {
LOG(DEBUG) << __func__;
if (!isClosed()) {
return ndk::ScopedAStatus::ok();
@@ -669,8 +675,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
-template <class Metadata>
-void StreamCommonImpl<Metadata>::stopWorker() {
+void StreamCommonImpl::stopWorker() {
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
@@ -686,10 +691,12 @@
}
}
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::updateMetadata(const Metadata& metadata) {
+ndk::ScopedAStatus StreamCommonImpl::updateMetadataCommon(const Metadata& metadata) {
LOG(DEBUG) << __func__;
if (!isClosed()) {
+ if (metadata.index() != mMetadata.index()) {
+ LOG(FATAL) << __func__ << ": changing metadata variant is not allowed";
+ }
mMetadata = metadata;
return ndk::ScopedAStatus::ok();
}
@@ -697,12 +704,10 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
-// static
-ndk::ScopedAStatus StreamIn::initInstance(const std::shared_ptr<StreamIn>& stream) {
- if (auto status = stream->init(); !status.isOk()) {
- return status;
- }
- stream->createStreamCommon(stream);
+ndk::ScopedAStatus StreamCommonImpl::setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ mWorker->setIsConnected(!devices.empty());
+ mConnectedDevices = devices;
return ndk::ScopedAStatus::ok();
}
@@ -716,12 +721,8 @@
}
} // namespace
-StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext&& context,
- const DriverInterface::CreateInstance& createDriver,
- const StreamWorkerInterface::CreateInstance& createWorker,
- const std::vector<MicrophoneInfo>& microphones)
- : StreamCommonImpl<SinkMetadata>(sinkMetadata, std::move(context), createDriver, createWorker),
- mMicrophones(transformMicrophones(microphones)) {
+StreamIn::StreamIn(const std::vector<MicrophoneInfo>& microphones)
+ : mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
@@ -729,9 +730,9 @@
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
std::vector<MicrophoneDynamicInfo> result;
std::vector<MicrophoneDynamicInfo::ChannelMapping> channelMapping{
- getChannelCount(mContext.getChannelLayout()),
+ getChannelCount(getContext().getChannelLayout()),
MicrophoneDynamicInfo::ChannelMapping::DIRECT};
- for (auto it = mConnectedDevices.begin(); it != mConnectedDevices.end(); ++it) {
+ for (auto it = getConnectedDevices().begin(); it != getConnectedDevices().end(); ++it) {
if (auto micIt = mMicrophones.find(*it); micIt != mMicrophones.end()) {
MicrophoneDynamicInfo dynMic;
dynMic.id = micIt->second;
@@ -777,22 +778,8 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-// static
-ndk::ScopedAStatus StreamOut::initInstance(const std::shared_ptr<StreamOut>& stream) {
- if (auto status = stream->init(); !status.isOk()) {
- return status;
- }
- stream->createStreamCommon(stream);
- return ndk::ScopedAStatus::ok();
-}
-
-StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext&& context,
- const DriverInterface::CreateInstance& createDriver,
- const StreamWorkerInterface::CreateInstance& createWorker,
- const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamCommonImpl<SourceMetadata>(sourceMetadata, std::move(context), createDriver,
- createWorker),
- mOffloadInfo(offloadInfo) {
+StreamOut::StreamOut(const std::optional<AudioOffloadInfo>& offloadInfo)
+ : mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
diff --git a/audio/aidl/default/StreamStub.cpp b/audio/aidl/default/StreamStub.cpp
index 2467320..2dcf4d4 100644
--- a/audio/aidl/default/StreamStub.cpp
+++ b/audio/aidl/default/StreamStub.cpp
@@ -31,34 +31,69 @@
namespace aidl::android::hardware::audio::core {
-DriverStub::DriverStub(const StreamContext& context, bool isInput)
- : mFrameSizeBytes(context.getFrameSize()),
- mSampleRate(context.getSampleRate()),
- mIsAsynchronous(!!context.getAsyncCallback()),
- mIsInput(isInput) {}
+StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context)
+ : StreamCommonImpl(metadata, std::move(context)),
+ mFrameSizeBytes(getContext().getFrameSize()),
+ mSampleRate(getContext().getSampleRate()),
+ mIsAsynchronous(!!getContext().getAsyncCallback()),
+ mIsInput(isInput(metadata)) {}
-::android::status_t DriverStub::init() {
+::android::status_t StreamStub::init() {
+ mIsInitialized = true;
usleep(500);
return ::android::OK;
}
-::android::status_t DriverStub::drain(StreamDescriptor::DrainMode) {
+::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
usleep(500);
return ::android::OK;
}
-::android::status_t DriverStub::flush() {
+::android::status_t StreamStub::flush() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
usleep(500);
return ::android::OK;
}
-::android::status_t DriverStub::pause() {
+::android::status_t StreamStub::pause() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
usleep(500);
return ::android::OK;
}
-::android::status_t DriverStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+::android::status_t StreamStub::standby() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ usleep(500);
+ mIsStandby = true;
+ return ::android::OK;
+}
+
+::android::status_t StreamStub::start() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ usleep(500);
+ mIsStandby = false;
+ return ::android::OK;
+}
+
+::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ if (mIsStandby) {
+ LOG(FATAL) << __func__ << ": must not happen while in standby";
+ }
static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
static constexpr float kScaleFactor = .8f;
if (mIsAsynchronous) {
@@ -79,69 +114,16 @@
return ::android::OK;
}
-::android::status_t DriverStub::standby() {
- usleep(500);
- return ::android::OK;
-}
-
-::android::status_t DriverStub::setConnectedDevices(
- const std::vector<AudioDevice>& connectedDevices __unused) {
- usleep(500);
- return ::android::OK;
-}
-
-// static
-ndk::ScopedAStatus StreamInStub::createInstance(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result) {
- std::shared_ptr<StreamIn> stream =
- ndk::SharedRefBase::make<StreamInStub>(sinkMetadata, std::move(context), microphones);
- if (auto status = initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
+void StreamStub::shutdown() {
+ mIsInitialized = false;
}
StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(
- sinkMetadata, std::move(context),
- [](const StreamContext& ctx) -> DriverInterface* {
- return new DriverStub(ctx, true /*isInput*/);
- },
- [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
- // The default worker implementation is used.
- return new StreamInWorker(ctx, driver);
- },
- microphones) {}
-
-// static
-ndk::ScopedAStatus StreamOutStub::createInstance(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<AudioOffloadInfo>& offloadInfo,
- std::shared_ptr<StreamOut>* result) {
- std::shared_ptr<StreamOut> stream = ndk::SharedRefBase::make<StreamOutStub>(
- sourceMetadata, std::move(context), offloadInfo);
- if (auto status = initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
+ : StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {}
StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamOut(
- sourceMetadata, std::move(context),
- [](const StreamContext& ctx) -> DriverInterface* {
- return new DriverStub(ctx, false /*isInput*/);
- },
- [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
- // The default worker implementation is used.
- return new StreamOutWorker(ctx, driver);
- },
- offloadInfo) {}
+ : StreamStub(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index fabb93b..e2bc833 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -33,14 +33,19 @@
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_6;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_PENTA;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_QUAD;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_TRI;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index d57790a..9a3a447 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -535,12 +535,17 @@
<xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_MONO"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_STEREO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_TRI"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_6"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_2POINT0POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_3POINT0POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_QUAD"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_PENTA"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_5POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO"/>
diff --git a/audio/aidl/default/extension/ExtensionEffect.cpp b/audio/aidl/default/extension/ExtensionEffect.cpp
index c4eebc0..4a4d71b6 100644
--- a/audio/aidl/default/extension/ExtensionEffect.cpp
+++ b/audio/aidl/default/extension/ExtensionEffect.cpp
@@ -30,8 +30,8 @@
using aidl::android::hardware::audio::effect::DefaultExtension;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::ExtensionEffect;
-using aidl::android::hardware::audio::effect::getEffectUuidExtensionImpl;
-using aidl::android::hardware::audio::effect::getEffectUuidExtensionType;
+using aidl::android::hardware::audio::effect::getEffectImplUuidExtension;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidExtension;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::Range;
using aidl::android::hardware::audio::effect::VendorExtension;
@@ -39,7 +39,7 @@
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
std::shared_ptr<IEffect>* instanceSpp) {
- if (!in_impl_uuid || *in_impl_uuid != getEffectUuidExtensionImpl()) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
@@ -54,7 +54,7 @@
}
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
- if (!in_impl_uuid || *in_impl_uuid != getEffectUuidExtensionImpl()) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
@@ -67,8 +67,8 @@
const std::string ExtensionEffect::kEffectName = "ExtensionEffectExample";
const Descriptor ExtensionEffect::kDescriptor = {
- .common = {.id = {.type = getEffectUuidExtensionType(),
- .uuid = getEffectUuidExtensionImpl(),
+ .common = {.id = {.type = getEffectTypeUuidExtension(),
+ .uuid = getEffectImplUuidExtension(),
.proxy = std::nullopt},
.name = ExtensionEffect::kEffectName,
.implementor = "The Android Open Source Project"}};
diff --git a/audio/aidl/default/include/core-impl/AidlConversionXsdc.h b/audio/aidl/default/include/core-impl/AidlConversionXsdc.h
new file mode 100644
index 0000000..c9aefc7
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/AidlConversionXsdc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/SurroundSoundConfig.h>
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <android_audio_policy_configuration.h>
+#include <media/AidlConversionUtil.h>
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<::aidl::android::media::audio::common::AudioFormatDescription>
+xsdc2aidl_AudioFormatDescription(const std::string& xsdc);
+
+ConversionResult<SurroundSoundConfig> xsdc2aidl_SurroundSoundConfig(
+ const ::android::audio::policy::configuration::SurroundSound& xsdc);
+
+} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
index 47918f0..090d585 100644
--- a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
@@ -18,6 +18,7 @@
#include <string>
+#include <aidl/android/hardware/audio/core/SurroundSoundConfig.h>
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
#include <android_audio_policy_configuration.h>
#include <android_audio_policy_configuration_enums.h>
@@ -35,6 +36,10 @@
::android::status_t getStatus() const { return mConverter.getStatus(); }
const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
+ const SurroundSoundConfig& getSurroundSoundConfig();
+
+ // Public for testing purposes.
+ static const SurroundSoundConfig& getDefaultSurroundSoundConfig();
private:
const std::optional<::android::audio::policy::configuration::AudioPolicyConfiguration>&
@@ -48,7 +53,6 @@
void parseVolumes();
::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
const std::string& xsdcCurvePoint);
-
::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 83ecfaa..4a23637 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -33,39 +33,13 @@
static constexpr int32_t kLatencyMs = 10;
enum Type : int { DEFAULT, R_SUBMIX, USB };
+ static std::shared_ptr<Module> createInstance(Type type);
+
explicit Module(Type type) : mType(type) {}
- static std::shared_ptr<Module> createInstance(Type type);
- static StreamIn::CreateInstance getStreamInCreator(Type type);
- static StreamOut::CreateInstance getStreamOutCreator(Type type);
-
- private:
- struct VendorDebug {
- static const std::string kForceTransientBurstName;
- static const std::string kForceSynchronousDrainName;
- bool forceTransientBurst = false;
- bool forceSynchronousDrain = false;
- };
- // Helper used for interfaces that require a persistent instance. We hold them via a strong
- // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
- template <class C>
- struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
- ChildInterface() {}
- ChildInterface& operator=(const std::shared_ptr<C>& c) {
- return operator=(std::shared_ptr<C>(c));
- }
- ChildInterface& operator=(std::shared_ptr<C>&& c) {
- this->first = std::move(c);
- this->second = this->first->asBinder();
- AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- return *this;
- }
- explicit operator bool() const { return !!this->first; }
- C& operator*() const { return *(this->first); }
- C* operator->() const { return this->first; }
- std::shared_ptr<C> getPtr() const { return this->first; }
- };
+ protected:
+ // The vendor extension done via inheritance can override interface methods and augment
+ // a call to the base implementation.
ndk::ScopedAStatus setModuleDebug(
const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
@@ -146,29 +120,46 @@
ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
- void cleanUpPatch(int32_t patchId);
- ndk::ScopedAStatus createStreamContext(
- int32_t in_portConfigId, int64_t in_bufferSizeFrames,
- std::shared_ptr<IStreamCallback> asyncCallback,
- std::shared_ptr<IStreamOutEventCallback> outEventCallback,
- ::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);
- bool isMmapSupported();
-
// This value is used for all AudioPatches.
static constexpr int32_t kMinimumStreamBufferSizeFrames = 256;
// The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
+ private:
+ struct VendorDebug {
+ static const std::string kForceTransientBurstName;
+ static const std::string kForceSynchronousDrainName;
+ bool forceTransientBurst = false;
+ bool forceSynchronousDrain = false;
+ };
+ // Helper used for interfaces that require a persistent instance. We hold them via a strong
+ // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
+ template <class C>
+ struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
+ ChildInterface() {}
+ ChildInterface& operator=(const std::shared_ptr<C>& c) {
+ return operator=(std::shared_ptr<C>(c));
+ }
+ ChildInterface& operator=(std::shared_ptr<C>&& c) {
+ this->first = std::move(c);
+ this->second = this->first->asBinder();
+ AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
+ return *this;
+ }
+ explicit operator bool() const { return !!this->first; }
+ C& operator*() const { return *(this->first); }
+ C* operator->() const { return this->first; }
+ std::shared_ptr<C> getPtr() const { return this->first; }
+ };
+ // ids of device ports created at runtime via 'connectExternalDevice'.
+ // Also stores a list of ids of mix ports with dynamic profiles that were populated from
+ // the connected port. This list can be empty, thus an int->int multimap can't be used.
+ using ConnectedDevicePorts = std::map<int32_t, std::vector<int32_t>>;
+ // Maps port ids and port config ids to patch ids.
+ // Multimap because both ports and configs can be used by multiple patches.
+ using Patches = std::multimap<int32_t, int32_t>;
+
const Type mType;
std::unique_ptr<internal::Configuration> mConfig;
ModuleDebug mDebug;
@@ -177,19 +168,29 @@
ChildInterface<IBluetooth> mBluetooth;
ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
ChildInterface<IBluetoothLe> mBluetoothLe;
- // ids of device ports created at runtime via 'connectExternalDevice'.
- // Also stores ids of mix ports with dynamic profiles which got populated from the connected
- // port.
- std::map<int32_t, std::vector<int32_t>> mConnectedDevicePorts;
+ ConnectedDevicePorts mConnectedDevicePorts;
Streams mStreams;
- // Maps port ids and port config ids to patch ids.
- // Multimap because both ports and configs can be used by multiple patches.
- std::multimap<int32_t, int32_t> mPatches;
+ Patches mPatches;
bool mMicMute = false;
+ bool mMasterMute = false;
+ float mMasterVolume = 1.0f;
ChildInterface<sounddose::ISoundDose> mSoundDose;
std::optional<bool> mIsMmapSupported;
protected:
+ // The following virtual functions are intended for vendor extension via inheritance.
+
+ virtual ndk::ScopedAStatus createInputStream(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result);
+ virtual ndk::ScopedAStatus createOutputStream(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result);
// If the module is unable to populate the connected device port correctly, the returned error
// code must correspond to the errors of `IModule.connectedExternalDevice` method.
virtual ndk::ScopedAStatus populateConnectedDevicePort(
@@ -204,8 +205,31 @@
virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
- bool mMasterMute = false;
- float mMasterVolume = 1.0f;
+ // Utility and helper functions accessible to subclasses.
+ void cleanUpPatch(int32_t patchId);
+ ndk::ScopedAStatus createStreamContext(
+ int32_t in_portConfigId, int64_t in_bufferSizeFrames,
+ std::shared_ptr<IStreamCallback> asyncCallback,
+ std::shared_ptr<IStreamOutEventCallback> outEventCallback,
+ ::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();
+ const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
+ bool getMasterMute() const { return mMasterMute; }
+ bool getMasterVolume() const { return mMasterVolume; }
+ bool getMicMute() const { return mMicMute; }
+ const Patches& getPatches() const { return mPatches; }
+ const Streams& getStreams() const { return mStreams; }
+ bool isMmapSupported();
+ template <typename C>
+ std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
+ void registerPatch(const AudioPatch& patch);
+ ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
+ const AudioPatch& newPatch);
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
new file mode 100644
index 0000000..7b1d375
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleRemoteSubmix : public Module {
+ public:
+ explicit ModuleRemoteSubmix(Module::Type type) : Module(type) {}
+
+ private:
+ // IModule interfaces
+ ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
+ ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
+ ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+ ndk::ScopedAStatus setMicMute(bool in_mute) override;
+
+ // Module interfaces
+ ndk::ScopedAStatus createInputStream(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) override;
+ ndk::ScopedAStatus createOutputStream(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result) override;
+ ndk::ScopedAStatus populateConnectedDevicePort(
+ ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+ ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
+ const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
+ const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
+ override;
+ void onExternalDeviceConnectionChanged(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort,
+ bool connected) override;
+ ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
+ ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index 1aa2244..5a5429d 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -32,6 +32,17 @@
ndk::ScopedAStatus setMicMute(bool in_mute) override;
// Module interfaces
+ ndk::ScopedAStatus createInputStream(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) override;
+ ndk::ScopedAStatus createOutputStream(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus populateConnectedDevicePort(
::aidl::android::media::audio::common::AudioPort* audioPort) override;
ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 65680df..aaf5860 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -25,6 +25,7 @@
#include <variant>
#include <StreamWorker.h>
+#include <Utils.h>
#include <aidl/android/hardware/audio/common/SinkMetadata.h>
#include <aidl/android/hardware/audio/common/SourceMetadata.h>
#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
@@ -34,8 +35,10 @@
#include <aidl/android/hardware/audio/core/IStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <aidl/android/media/audio/common/AudioDevice.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
#include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include <error/expected_utils.h>
#include <fmq/AidlMessageQueue.h>
#include <system/thread_defs.h>
#include <utils/Errors.h>
@@ -75,18 +78,23 @@
StreamContext() = default;
StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
+ int portId,
const ::aidl::android::media::audio::common::AudioFormatDescription& format,
const ::aidl::android::media::audio::common::AudioChannelLayout& channelLayout,
- int sampleRate, std::unique_ptr<DataMQ> dataMQ,
+ int sampleRate, const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ int32_t mixPortHandle, std::unique_ptr<DataMQ> dataMQ,
std::shared_ptr<IStreamCallback> asyncCallback,
std::shared_ptr<IStreamOutEventCallback> outEventCallback,
DebugParameters debugParameters)
: mCommandMQ(std::move(commandMQ)),
mInternalCommandCookie(std::rand()),
mReplyMQ(std::move(replyMQ)),
+ mPortId(portId),
mFormat(format),
mChannelLayout(channelLayout),
mSampleRate(sampleRate),
+ mFlags(flags),
+ mMixPortHandle(mixPortHandle),
mDataMQ(std::move(dataMQ)),
mAsyncCallback(asyncCallback),
mOutEventCallback(outEventCallback),
@@ -95,9 +103,12 @@
: mCommandMQ(std::move(other.mCommandMQ)),
mInternalCommandCookie(other.mInternalCommandCookie),
mReplyMQ(std::move(other.mReplyMQ)),
+ mPortId(other.mPortId),
mFormat(other.mFormat),
mChannelLayout(other.mChannelLayout),
mSampleRate(other.mSampleRate),
+ mFlags(std::move(other.mFlags)),
+ mMixPortHandle(other.mMixPortHandle),
mDataMQ(std::move(other.mDataMQ)),
mAsyncCallback(std::move(other.mAsyncCallback)),
mOutEventCallback(std::move(other.mOutEventCallback)),
@@ -106,9 +117,12 @@
mCommandMQ = std::move(other.mCommandMQ);
mInternalCommandCookie = other.mInternalCommandCookie;
mReplyMQ = std::move(other.mReplyMQ);
+ mPortId = std::move(other.mPortId);
mFormat = std::move(other.mFormat);
mChannelLayout = std::move(other.mChannelLayout);
mSampleRate = other.mSampleRate;
+ mFlags = std::move(other.mFlags);
+ mMixPortHandle = other.mMixPortHandle;
mDataMQ = std::move(other.mDataMQ);
mAsyncCallback = std::move(other.mAsyncCallback);
mOutEventCallback = std::move(other.mOutEventCallback);
@@ -126,13 +140,16 @@
::aidl::android::media::audio::common::AudioFormatDescription getFormat() const {
return mFormat;
}
+ ::aidl::android::media::audio::common::AudioIoFlags getFlags() const { return mFlags; }
bool getForceTransientBurst() const { return mDebugParameters.forceTransientBurst; }
bool getForceSynchronousDrain() const { return mDebugParameters.forceSynchronousDrain; }
size_t getFrameSize() const;
int getInternalCommandCookie() const { return mInternalCommandCookie; }
+ int32_t getMixPortHandle() const { return mMixPortHandle; }
std::shared_ptr<IStreamOutEventCallback> getOutEventCallback() const {
return mOutEventCallback;
}
+ int getPortId() const { return mPortId; }
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
int getSampleRate() const { return mSampleRate; }
@@ -143,32 +160,31 @@
std::unique_ptr<CommandMQ> mCommandMQ;
int mInternalCommandCookie; // The value used to confirm that the command was posted internally
std::unique_ptr<ReplyMQ> mReplyMQ;
+ int mPortId;
::aidl::android::media::audio::common::AudioFormatDescription mFormat;
::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
int mSampleRate;
+ ::aidl::android::media::audio::common::AudioIoFlags mFlags;
+ int32_t mMixPortHandle;
std::unique_ptr<DataMQ> mDataMQ;
std::shared_ptr<IStreamCallback> mAsyncCallback;
std::shared_ptr<IStreamOutEventCallback> mOutEventCallback; // Only used by output streams
DebugParameters mDebugParameters;
};
+// This interface provides operations of the stream which are executed on the worker thread.
struct DriverInterface {
- using CreateInstance = std::function<DriverInterface*(const StreamContext&)>;
virtual ~DriverInterface() = default;
- // This function is called once, on the main thread, before starting the worker thread.
- virtual ::android::status_t init() = 0;
- // This function is called from Binder pool thread. It must be done in a thread-safe manner
- // if this method and other methods in this interface share data.
- virtual ::android::status_t setConnectedDevices(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>&
- connectedDevices) = 0;
- // All the functions below are called on the worker thread.
+ // All the methods below are called on the worker thread.
+ virtual ::android::status_t init() = 0; // This function is only called once.
virtual ::android::status_t drain(StreamDescriptor::DrainMode mode) = 0;
virtual ::android::status_t flush() = 0;
virtual ::android::status_t pause() = 0;
+ virtual ::android::status_t standby() = 0;
+ virtual ::android::status_t start() = 0;
virtual ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) = 0;
- virtual ::android::status_t standby() = 0;
+ virtual void shutdown() = 0; // This function is only called once.
};
class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
@@ -285,14 +301,20 @@
};
using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;
-// This provides a C++ interface with methods of the IStreamCommon Binder interface,
-// but intentionally does not inherit from it. This is needed to avoid inheriting
-// StreamIn and StreamOut from two Binder interface classes, as these parts of the class
-// will be reference counted separately.
-//
-// The implementation of these common methods is in the StreamCommonImpl template class.
+// This interface provides operations of the stream which are executed on a Binder pool thread.
+// These methods originate both from the AIDL interface and its implementation.
struct StreamCommonInterface {
+ using ConnectedDevices = std::vector<::aidl::android::media::audio::common::AudioDevice>;
+ using Metadata =
+ std::variant<::aidl::android::hardware::audio::common::SinkMetadata /*IStreamIn*/,
+ ::aidl::android::hardware::audio::common::SourceMetadata /*IStreamOut*/>;
+
+ static constexpr bool isInput(const Metadata& metadata) { return metadata.index() == 0; }
+
virtual ~StreamCommonInterface() = default;
+ // Methods below originate from the 'IStreamCommon' interface.
+ // This is semantically equivalent to inheriting from 'IStreamCommon' with a benefit
+ // that concrete stream implementations can inherit both from this interface and IStreamIn/Out.
virtual ndk::ScopedAStatus close() = 0;
virtual ndk::ScopedAStatus prepareToClose() = 0;
virtual ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) = 0;
@@ -306,11 +328,30 @@
virtual ndk::ScopedAStatus removeEffect(
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
in_effect) = 0;
+ // Methods below are common for both 'IStreamIn' and 'IStreamOut'. Note that
+ // 'updateMetadata' in them uses an individual structure which is wrapped here.
+ // The 'Common' suffix is added to distinguish them from the methods from 'IStreamIn/Out'.
+ virtual ndk::ScopedAStatus getStreamCommonCommon(
+ std::shared_ptr<IStreamCommon>* _aidl_return) = 0;
+ virtual ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) = 0;
+ // Methods below are called by implementation of 'IModule', 'IStreamIn' and 'IStreamOut'.
+ virtual ndk::ScopedAStatus initInstance(
+ const std::shared_ptr<StreamCommonInterface>& delegate) = 0;
+ virtual const StreamContext& getContext() const = 0;
+ virtual bool isClosed() const = 0;
+ virtual const ConnectedDevices& getConnectedDevices() const = 0;
+ virtual ndk::ScopedAStatus setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
};
-class StreamCommon : public BnStreamCommon {
+// This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
+// a weak pointer to avoid creating a reference loop. The loop will occur because
+// 'IStreamIn/Out.getStreamCommon' must return the same instance every time, thus
+// the stream implementation must hold a strong pointer to an instance of 'IStreamCommon'.
+// Also, we use 'StreamCommonInterface' here instead of 'IStreamCommon'.
+class StreamCommonDelegator : public BnStreamCommon {
public:
- explicit StreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate)
+ explicit StreamCommonDelegator(const std::shared_ptr<StreamCommonInterface>& delegate)
: mDelegate(delegate) {}
private:
@@ -361,9 +402,20 @@
std::weak_ptr<StreamCommonInterface> mDelegate;
};
-template <class Metadata>
-class StreamCommonImpl : public StreamCommonInterface {
+// The implementation of DriverInterface must be provided by each concrete stream implementation.
+class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface {
public:
+ StreamCommonImpl(const Metadata& metadata, StreamContext&& context,
+ const StreamWorkerInterface::CreateInstance& createWorker)
+ : mMetadata(metadata),
+ mContext(std::move(context)),
+ mWorker(createWorker(mContext, this)) {}
+ StreamCommonImpl(const Metadata& metadata, StreamContext&& context)
+ : StreamCommonImpl(
+ metadata, std::move(context),
+ isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
+ ~StreamCommonImpl();
+
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus prepareToClose() override;
ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
@@ -378,46 +430,50 @@
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
override;
- ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return);
- ndk::ScopedAStatus init() {
- return mWorker->start() ? ndk::ScopedAStatus::ok()
- : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- bool isClosed() const { return mWorker->isClosed(); }
- void setIsConnected(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- mWorker->setIsConnected(!devices.empty());
- mConnectedDevices = devices;
- mDriver->setConnectedDevices(devices);
- }
- ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
+ ndk::ScopedAStatus getStreamCommonCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override;
+ ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+
+ ndk::ScopedAStatus initInstance(
+ const std::shared_ptr<StreamCommonInterface>& delegate) override;
+ const StreamContext& getContext() const override { return mContext; }
+ bool isClosed() const override { return mWorker->isClosed(); }
+ const ConnectedDevices& getConnectedDevices() const override { return mConnectedDevices; }
+ ndk::ScopedAStatus setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
protected:
- StreamCommonImpl(const Metadata& metadata, StreamContext&& context,
- const DriverInterface::CreateInstance& createDriver,
- const StreamWorkerInterface::CreateInstance& createWorker)
- : mMetadata(metadata),
- mContext(std::move(context)),
- mDriver(createDriver(mContext)),
- mWorker(createWorker(mContext, mDriver.get())) {}
- ~StreamCommonImpl();
- void stopWorker();
- void createStreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate);
+ static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
+ return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+ return new StreamInWorker(ctx, driver);
+ };
+ }
+ static StreamWorkerInterface::CreateInstance getDefaultOutWorkerCreator() {
+ return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+ return new StreamOutWorker(ctx, driver);
+ };
+ }
- std::shared_ptr<StreamCommon> mCommon;
- ndk::SpAIBinder mCommonBinder;
+ void stopWorker();
+
Metadata mMetadata;
StreamContext mContext;
- std::unique_ptr<DriverInterface> mDriver;
std::unique_ptr<StreamWorkerInterface> mWorker;
- std::vector<::aidl::android::media::audio::common::AudioDevice> mConnectedDevices;
+ std::shared_ptr<StreamCommonDelegator> mCommon;
+ ndk::SpAIBinder mCommonBinder;
+ ConnectedDevices mConnectedDevices;
};
-class StreamIn : public StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>,
- public BnStreamIn {
+// Note: 'StreamIn/Out' can not be used on their own. Instead, they must be used for defining
+// concrete input/output stream implementations.
+class StreamIn : virtual public StreamCommonInterface, public BnStreamIn {
+ protected:
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
- return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>::
- getStreamCommon(_aidl_return);
+ return getStreamCommonCommon(_aidl_return);
+ }
+ ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
+ in_sinkMetadata) override {
+ return updateMetadataCommon(in_sinkMetadata);
}
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
@@ -426,49 +482,26 @@
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 StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>::
- updateMetadata(in_sinkMetadata);
- }
ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
- protected:
friend class ndk::SharedRefBase;
- static ndk::ScopedAStatus initInstance(const std::shared_ptr<StreamIn>& stream);
-
- StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context, const DriverInterface::CreateInstance& createDriver,
- const StreamWorkerInterface::CreateInstance& createWorker,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
- void createStreamCommon(const std::shared_ptr<StreamIn>& myPtr) {
- StreamCommonImpl<
- ::aidl::android::hardware::audio::common::SinkMetadata>::createStreamCommon(myPtr);
- }
+ explicit StreamIn(
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
-
- public:
- using CreateInstance = std::function<ndk::ScopedAStatus(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result)>;
};
-class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>,
- public BnStreamOut {
+class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
+ protected:
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
- return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
- getStreamCommon(_aidl_return);
+ return getStreamCommonCommon(_aidl_return);
}
ndk::ScopedAStatus updateMetadata(
const ::aidl::android::hardware::audio::common::SourceMetadata& in_sourceMetadata)
override {
- return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
- updateMetadata(in_sourceMetadata);
+ return updateMetadataCommon(in_sourceMetadata);
}
ndk::ScopedAStatus updateOffloadMetadata(
const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&
@@ -493,34 +526,27 @@
override;
ndk::ScopedAStatus selectPresentation(int32_t in_presentationId, int32_t in_programId) override;
- void createStreamCommon(const std::shared_ptr<StreamOut>& myPtr) {
- StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
- createStreamCommon(myPtr);
- }
-
- protected:
friend class ndk::SharedRefBase;
- static ndk::ScopedAStatus initInstance(const std::shared_ptr<StreamOut>& stream);
-
- StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context, const DriverInterface::CreateInstance& createDriver,
- const StreamWorkerInterface::CreateInstance& createWorker,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo);
+ explicit StreamOut(const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
-
- public:
- using CreateInstance = std::function<ndk::ScopedAStatus(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result)>;
};
+// The recommended way to create a stream instance.
+// 'StreamImpl' is the concrete stream implementation, 'StreamInOrOut' is either 'StreamIn' or
+// 'StreamOut', the rest are the arguments forwarded to the constructor of 'StreamImpl'.
+template <class StreamImpl, class StreamInOrOut, class... Args>
+ndk::ScopedAStatus createStreamInstance(std::shared_ptr<StreamInOrOut>* result, Args&&... args) {
+ std::shared_ptr<StreamInOrOut> stream =
+ ::ndk::SharedRefBase::make<StreamImpl>(std::forward<Args>(args)...);
+ RETURN_STATUS_IF_ERROR(stream->initInstance(stream));
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
class StreamWrapper {
public:
explicit StreamWrapper(const std::shared_ptr<StreamIn>& streamIn)
@@ -529,25 +555,18 @@
: mStream(streamOut), mStreamBinder(streamOut->asBinder()) {}
ndk::SpAIBinder getBinder() const { return mStreamBinder; }
bool isStreamOpen() const {
- return std::visit(
- [](auto&& ws) -> bool {
- auto s = ws.lock();
- return s && !s->isClosed();
- },
- mStream);
+ auto s = mStream.lock();
+ return s && !s->isClosed();
}
- void setStreamIsConnected(
+ ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- std::visit(
- [&](auto&& ws) {
- auto s = ws.lock();
- if (s) s->setIsConnected(devices);
- },
- mStream);
+ auto s = mStream.lock();
+ if (s) return s->setConnectedDevices(devices);
+ return ndk::ScopedAStatus::ok();
}
private:
- std::variant<std::weak_ptr<StreamIn>, std::weak_ptr<StreamOut>> mStream;
+ std::weak_ptr<StreamCommonInterface> mStream;
ndk::SpAIBinder mStreamBinder;
};
@@ -565,12 +584,13 @@
mStreams.insert(std::pair{portConfigId, sw});
mStreams.insert(std::pair{portId, std::move(sw)});
}
- void setStreamIsConnected(
+ ndk::ScopedAStatus setStreamConnectedDevices(
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(devices);
+ return it->second.setConnectedDevices(devices);
}
+ return ndk::ScopedAStatus::ok();
}
private:
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
new file mode 100644
index 0000000..2253ec7
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+#include "core-impl/Stream.h"
+#include "r_submix/SubmixRoute.h"
+
+namespace aidl::android::hardware::audio::core {
+
+using aidl::android::hardware::audio::core::r_submix::AudioConfig;
+using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
+
+class StreamRemoteSubmix : public StreamCommonImpl {
+ public:
+ StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context);
+
+ ::android::status_t init() override;
+ ::android::status_t drain(StreamDescriptor::DrainMode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
+ ::android::status_t standby() override;
+ ::android::status_t start() override;
+ ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+ int32_t* latencyMs) override;
+ void shutdown() override;
+
+ // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+ ndk::ScopedAStatus prepareToClose() override;
+
+ private:
+ size_t getPipeSizeInFrames();
+ size_t getStreamPipeSizeInFrames();
+ ::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
+ ::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
+
+ const int mPortId;
+ const bool mIsInput;
+ AudioConfig mStreamConfig;
+ std::shared_ptr<SubmixRoute> mCurrentRoute = nullptr;
+
+ // Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
+ // locks and none of the mutex locks should be taken together.
+ static std::mutex sSubmixRoutesLock;
+ static std::map<int32_t, std::shared_ptr<SubmixRoute>> sSubmixRoutes
+ GUARDED_BY(sSubmixRoutesLock);
+
+ // limit for number of read error log entries to avoid spamming the logs
+ static constexpr int kMaxReadErrorLogs = 5;
+ // The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
+ // to the duration of a record buffer at the current record sample rate (of the device, not of
+ // the recording itself). Here we have: 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
+ static constexpr int kMaxReadFailureAttempts = 3;
+ // 5ms between two read attempts when pipe is empty
+ static constexpr int kReadAttemptSleepUs = 5000;
+};
+
+class StreamInRemoteSubmix final : public StreamRemoteSubmix, public StreamIn {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamInRemoteSubmix(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+ private:
+ ndk::ScopedAStatus getActiveMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+ override;
+};
+
+class StreamOutRemoteSubmix final : public StreamRemoteSubmix, public StreamOut {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamOutRemoteSubmix(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index df0182c..6b1b2dd 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -20,36 +20,31 @@
namespace aidl::android::hardware::audio::core {
-class DriverStub : public DriverInterface {
+class StreamStub : public StreamCommonImpl {
public:
- DriverStub(const StreamContext& context, bool isInput);
+ StreamStub(const Metadata& metadata, StreamContext&& context);
+ // Methods of 'DriverInterface'.
::android::status_t init() override;
- ::android::status_t setConnectedDevices(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
- override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
+ ::android::status_t standby() override;
+ ::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
- ::android::status_t standby() override;
+ void shutdown() override;
private:
const size_t mFrameSizeBytes;
const int mSampleRate;
const bool mIsAsynchronous;
const bool mIsInput;
+ bool mIsInitialized = false; // Used for validating the state machine logic.
+ bool mIsStandby = true; // Used for validating the state machine logic.
};
-class StreamInStub final : public StreamIn {
+class StreamInStub final : public StreamStub, public StreamIn {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamInStub(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
@@ -57,16 +52,8 @@
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
};
-class StreamOutStub final : public StreamOut {
+class StreamOutStub final : public StreamStub, public StreamOut {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 36e64cb..8c40782 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -16,7 +16,10 @@
#pragma once
+#include <atomic>
+#include <functional>
#include <mutex>
+#include <optional>
#include <vector>
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
@@ -30,71 +33,64 @@
namespace aidl::android::hardware::audio::core {
-class DriverUsb : public DriverInterface {
+class StreamUsb : public StreamCommonImpl {
public:
- DriverUsb(const StreamContext& context, bool isInput);
+ StreamUsb(const Metadata& metadata, StreamContext&& context);
+ // Methods of 'DriverInterface'.
::android::status_t init() override;
- ::android::status_t setConnectedDevices(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
- override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
+ ::android::status_t standby() override;
+ ::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
- ::android::status_t standby() override;
+ void shutdown() override;
+
+ // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+ const ConnectedDevices& getConnectedDevices() const override;
+ ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
private:
- ::android::status_t exitStandby();
+ using AlsaDeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
+ using AlsaDeviceProxy = std::unique_ptr<alsa_device_proxy, AlsaDeviceProxyDeleter>;
- std::mutex mLock;
+ static std::optional<struct pcm_config> maybePopulateConfig(const StreamContext& context,
+ bool isInput);
+
+ mutable std::mutex mLock;
const size_t mFrameSizeBytes;
- std::optional<struct pcm_config> mConfig;
const bool mIsInput;
- // Cached device addresses for connected devices.
- std::vector<::aidl::android::media::audio::common::AudioDeviceAddress> mConnectedDevices
- GUARDED_BY(mLock);
- std::vector<std::shared_ptr<alsa_device_proxy>> mAlsaDeviceProxies GUARDED_BY(mLock);
- bool mIsStandby = true;
+ const std::optional<struct pcm_config> mConfig;
+ std::atomic<bool> mConnectedDevicesUpdated = false;
+ // All fields below are only used on the worker thread.
+ std::vector<AlsaDeviceProxy> mAlsaDeviceProxies;
};
-class StreamInUsb final : public StreamIn {
- ndk::ScopedAStatus getActiveMicrophones(
- std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
- override;
-
+class StreamInUsb final : public StreamUsb, public StreamIn {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamInUsb(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
-};
-
-class StreamOutUsb final : public StreamOut {
- public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result);
private:
+ ndk::ScopedAStatus getActiveMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+ override;
+};
+
+class StreamOutUsb final : public StreamUsb, public StreamOut {
+ public:
friend class ndk::SharedRefBase;
StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
+ private:
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
index ec23edb..a68a6fd 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -20,6 +20,7 @@
#include <string>
#include <unordered_map>
+#include <media/AidlConversionUtil.h>
#include <system/audio_config.h>
#include <utils/Errors.h>
@@ -78,7 +79,7 @@
* </Modules>
*/
template <typename W, typename X, typename A>
-static std::vector<A> convertWrappedCollectionToAidl(
+std::vector<A> convertWrappedCollectionToAidlUnchecked(
const std::vector<W>& xsdcWrapperTypeVec,
std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
std::function<A(const X&)> convertToAidl) {
@@ -100,12 +101,12 @@
}
template <typename X, typename A>
-static std::vector<A> convertCollectionToAidl(const std::vector<X>& xsdcTypeVec,
- std::function<A(const X&)> convertToAidl) {
+std::vector<A> convertCollectionToAidlUnchecked(const std::vector<X>& xsdcTypeVec,
+ std::function<A(const X&)> itemConversion) {
std::vector<A> resultAidlTypeVec;
resultAidlTypeVec.reserve(xsdcTypeVec.size());
std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
- convertToAidl);
+ itemConversion);
return resultAidlTypeVec;
}
@@ -121,8 +122,7 @@
* </Wrapper>
*/
template <typename W, typename R>
-static std::unordered_map<std::string, R> generateReferenceMap(
- const std::vector<W>& xsdcWrapperTypeVec) {
+std::unordered_map<std::string, R> generateReferenceMap(const std::vector<W>& xsdcWrapperTypeVec) {
std::unordered_map<std::string, R> resultMap;
if (!xsdcWrapperTypeVec.empty()) {
/*
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index af71aa8..12c0c4b 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -64,6 +64,7 @@
auto modules = {createModule(Module::Type::DEFAULT, "default"),
createModule(Module::Type::R_SUBMIX, "r_submix"),
createModule(Module::Type::USB, "usb")};
+ (void)modules;
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
new file mode 100644
index 0000000..2b79f51
--- /dev/null
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_ModuleRemoteSubmix"
+
+#include <vector>
+
+#include <android-base/logging.h>
+
+#include "RemoteSubmixUtils.h"
+#include "core-impl/ModuleRemoteSubmix.h"
+#include "core-impl/StreamRemoteSubmix.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus ModuleRemoteSubmix::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
+ *_aidl_return = nullptr;
+ LOG(DEBUG) << __func__ << ": returning null";
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
+ *_aidl_return = nullptr;
+ LOG(DEBUG) << __func__ << ": returning null";
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::setMicMute(bool in_mute __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
+ const SinkMetadata& sinkMetadata, StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInRemoteSubmix>(result, sinkMetadata, std::move(context),
+ microphones);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
+ const SourceMetadata& sourceMetadata, StreamContext&& context,
+ const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+ return createStreamInstance<StreamOutRemoteSubmix>(result, sourceMetadata, std::move(context),
+ offloadInfo);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
+ LOG(VERBOSE) << __func__ << ": Profiles already populated by Configuration";
+ for (auto profile : audioPort->profiles) {
+ for (auto channelMask : profile.channelMasks) {
+ if (!r_submix::isChannelMaskSupported(channelMask)) {
+ LOG(ERROR) << __func__ << ": the profile " << profile.name
+ << " has unsupported channel mask : " << channelMask.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+ for (auto sampleRate : profile.sampleRates) {
+ if (!r_submix::isSampleRateSupported(sampleRate)) {
+ LOG(ERROR) << __func__ << ": the profile " << profile.name
+ << " has unsupported sample rate : " << sampleRate;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::checkAudioPatchEndpointsMatch(
+ const std::vector<AudioPortConfig*>& sources, const std::vector<AudioPortConfig*>& sinks) {
+ for (const auto& source : sources) {
+ for (const auto& sink : sinks) {
+ if (source->sampleRate != sink->sampleRate ||
+ source->channelMask != sink->channelMask || source->format != sink->format) {
+ LOG(ERROR) << __func__
+ << ": mismatch port configuration, source=" << source->toString()
+ << ", sink=" << sink->toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+void ModuleRemoteSubmix::onExternalDeviceConnectionChanged(
+ const ::aidl::android::media::audio::common::AudioPort& audioPort __unused,
+ bool connected __unused) {
+ LOG(DEBUG) << __func__ << ": do nothing and return";
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::onMasterMuteChanged(bool __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::onMasterVolumeChanged(float __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp b/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp
new file mode 100644
index 0000000..2f5d17d
--- /dev/null
+++ b/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vector>
+
+#include "RemoteSubmixUtils.h"
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+bool isChannelMaskSupported(const AudioChannelLayout& channelMask) {
+ const static std::vector<AudioChannelLayout> kSupportedChannelMask = {
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::LAYOUT_MONO),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO)};
+
+ if (std::find(kSupportedChannelMask.begin(), kSupportedChannelMask.end(), channelMask) !=
+ kSupportedChannelMask.end()) {
+ return true;
+ }
+ return false;
+}
+
+bool isSampleRateSupported(int sampleRate) {
+ const static std::vector<int> kSupportedSampleRates = {8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000};
+
+ if (std::find(kSupportedSampleRates.begin(), kSupportedSampleRates.end(), sampleRate) !=
+ kSupportedSampleRates.end()) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/RemoteSubmixUtils.h b/audio/aidl/default/r_submix/RemoteSubmixUtils.h
new file mode 100644
index 0000000..952a992
--- /dev/null
+++ b/audio/aidl/default/r_submix/RemoteSubmixUtils.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+bool isChannelMaskSupported(const AudioChannelLayout& channelMask);
+
+bool isSampleRateSupported(int sampleRate);
+
+} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
new file mode 100644
index 0000000..5af0d91
--- /dev/null
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_StreamRemoteSubmix"
+#include <android-base/logging.h>
+
+#include <cmath>
+
+#include "core-impl/StreamRemoteSubmix.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamRemoteSubmix::StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context)
+ : StreamCommonImpl(metadata, std::move(context)),
+ mPortId(context.getPortId()),
+ mIsInput(isInput(metadata)) {
+ mStreamConfig.frameSize = context.getFrameSize();
+ mStreamConfig.format = context.getFormat();
+ mStreamConfig.channelLayout = context.getChannelLayout();
+ mStreamConfig.sampleRate = context.getSampleRate();
+}
+
+std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
+std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
+
+::android::status_t StreamRemoteSubmix::init() {
+ {
+ std::lock_guard guard(sSubmixRoutesLock);
+ if (sSubmixRoutes.find(mPortId) != sSubmixRoutes.end()) {
+ mCurrentRoute = sSubmixRoutes[mPortId];
+ }
+ }
+ // If route is not available for this port, add it.
+ if (mCurrentRoute == nullptr) {
+ // Initialize the pipe.
+ mCurrentRoute = std::make_shared<SubmixRoute>();
+ if (::android::OK != mCurrentRoute->createPipe(mStreamConfig)) {
+ LOG(ERROR) << __func__ << ": create pipe failed";
+ return ::android::NO_INIT;
+ }
+ {
+ std::lock_guard guard(sSubmixRoutesLock);
+ sSubmixRoutes.emplace(mPortId, mCurrentRoute);
+ }
+ } else {
+ if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
+ LOG(ERROR) << __func__ << ": invalid stream config";
+ return ::android::NO_INIT;
+ }
+ sp<MonoPipe> sink = mCurrentRoute->getSink();
+ if (sink == nullptr) {
+ LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
+ return ::android::NO_INIT;
+ }
+ // If the sink has been shutdown or pipe recreation is forced, delete the pipe and
+ // recreate it.
+ if (sink->isShutdown()) {
+ LOG(DEBUG) << __func__ << ": Non-nullptr shut down sink when opening stream";
+ if (::android::OK != mCurrentRoute->resetPipe()) {
+ LOG(ERROR) << __func__ << ": reset pipe failed";
+ return ::android::NO_INIT;
+ }
+ }
+ }
+
+ mCurrentRoute->openStream(mIsInput);
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::flush() {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::pause() {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::standby() {
+ mCurrentRoute->standby(mIsInput);
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::start() {
+ mCurrentRoute->exitStandby(mIsInput);
+ return ::android::OK;
+}
+
+ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
+ if (!mIsInput) {
+ std::shared_ptr<SubmixRoute> route = nullptr;
+ {
+ std::lock_guard guard(sSubmixRoutesLock);
+ if (sSubmixRoutes.find(mPortId) != sSubmixRoutes.end()) {
+ route = sSubmixRoutes[mPortId];
+ }
+ }
+ if (route != nullptr) {
+ sp<MonoPipe> sink = route->getSink();
+ if (sink == nullptr) {
+ ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
+
+ sink->shutdown(true);
+ } else {
+ LOG(DEBUG) << __func__ << ": stream already closed.";
+ ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+// Remove references to the specified input and output streams. When the device no longer
+// references input and output streams destroy the associated pipe.
+void StreamRemoteSubmix::shutdown() {
+ mCurrentRoute->closeStream(mIsInput);
+ // If all stream instances are closed, we can remove route information for this port.
+ if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
+ mCurrentRoute->releasePipe();
+ LOG(DEBUG) << __func__ << ": pipe destroyed";
+
+ std::lock_guard guard(sSubmixRoutesLock);
+ sSubmixRoutes.erase(mPortId);
+ }
+ mCurrentRoute.reset();
+}
+
+::android::status_t StreamRemoteSubmix::transfer(void* buffer, size_t frameCount,
+ size_t* actualFrameCount, int32_t* latencyMs) {
+ *latencyMs = (getStreamPipeSizeInFrames() * MILLIS_PER_SECOND) / mStreamConfig.sampleRate;
+ LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
+
+ sp<MonoPipe> sink = mCurrentRoute->getSink();
+ if (sink != nullptr) {
+ if (sink->isShutdown()) {
+ sink.clear();
+ LOG(VERBOSE) << __func__ << ": pipe shutdown, ignoring the transfer.";
+ // the pipe has already been shutdown, this buffer will be lost but we must simulate
+ // timing so we don't drain the output faster than realtime
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+ usleep(delayUs);
+
+ *actualFrameCount = frameCount;
+ return ::android::OK;
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": transfer without a pipe!";
+ return ::android::UNEXPECTED_NULL;
+ }
+
+ return (mIsInput ? inRead(buffer, frameCount, actualFrameCount)
+ : outWrite(buffer, frameCount, actualFrameCount));
+}
+
+// Calculate the maximum size of the pipe buffer in frames for the specified stream.
+size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
+ auto pipeConfig = mCurrentRoute->mPipeConfig;
+ const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
+ return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
+}
+
+::android::status_t StreamRemoteSubmix::outWrite(void* buffer, size_t frameCount,
+ size_t* actualFrameCount) {
+ sp<MonoPipe> sink = mCurrentRoute->getSink();
+ if (sink != nullptr) {
+ if (sink->isShutdown()) {
+ sink.clear();
+ LOG(VERBOSE) << __func__ << ": pipe shutdown, ignoring the write.";
+ // the pipe has already been shutdown, this buffer will be lost but we must
+ // simulate timing so we don't drain the output faster than realtime
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+ usleep(delayUs);
+ *actualFrameCount = frameCount;
+ return ::android::OK;
+ }
+ } else {
+ LOG(FATAL) << __func__ << ": without a pipe!";
+ return ::android::UNKNOWN_ERROR;
+ }
+
+ const size_t availableToWrite = sink->availableToWrite();
+ // NOTE: sink has been checked above and sink and source life cycles are synchronized
+ sp<MonoPipeReader> source = mCurrentRoute->getSource();
+ // If the write to the sink should be blocked, flush enough frames from the pipe to make space
+ // to write the most recent data.
+ if (!mCurrentRoute->shouldBlockWrite() && availableToWrite < frameCount) {
+ static uint8_t flushBuffer[64];
+ const size_t flushBufferSizeFrames = sizeof(flushBuffer) / mStreamConfig.frameSize;
+ size_t framesToFlushFromSource = frameCount - availableToWrite;
+ LOG(VERBOSE) << __func__ << ": flushing " << framesToFlushFromSource
+ << " frames from the pipe to avoid blocking";
+ while (framesToFlushFromSource) {
+ const size_t flushSize = std::min(framesToFlushFromSource, flushBufferSizeFrames);
+ framesToFlushFromSource -= flushSize;
+ // read does not block
+ source->read(flushBuffer, flushSize);
+ }
+ }
+
+ ssize_t writtenFrames = sink->write(buffer, frameCount);
+ if (writtenFrames < 0) {
+ if (writtenFrames == (ssize_t)::android::NEGOTIATE) {
+ LOG(ERROR) << __func__ << ": write to pipe returned NEGOTIATE";
+ sink.clear();
+ *actualFrameCount = 0;
+ return ::android::UNKNOWN_ERROR;
+ } else {
+ // write() returned UNDERRUN or WOULD_BLOCK, retry
+ LOG(ERROR) << __func__ << ": write to pipe returned unexpected " << writtenFrames;
+ writtenFrames = sink->write(buffer, frameCount);
+ }
+ }
+ sink.clear();
+
+ if (writtenFrames < 0) {
+ LOG(ERROR) << __func__ << ": failed writing to pipe with " << writtenFrames;
+ *actualFrameCount = 0;
+ return ::android::UNKNOWN_ERROR;
+ }
+ LOG(VERBOSE) << __func__ << ": wrote " << writtenFrames << "frames";
+ *actualFrameCount = writtenFrames;
+ return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::inRead(void* buffer, size_t frameCount,
+ size_t* actualFrameCount) {
+ // about to read from audio source
+ sp<MonoPipeReader> source = mCurrentRoute->getSource();
+ if (source == nullptr) {
+ int readErrorCount = mCurrentRoute->notifyReadError();
+ if (readErrorCount < kMaxReadErrorLogs) {
+ LOG(ERROR)
+ << __func__
+ << ": no audio pipe yet we're trying to read! (not all errors will be logged)";
+ } else {
+ LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
+ }
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+ usleep(delayUs);
+ memset(buffer, 0, mStreamConfig.frameSize * frameCount);
+ *actualFrameCount = frameCount;
+ return ::android::OK;
+ }
+
+ // read the data from the pipe
+ int attempts = 0;
+ const size_t delayUs = static_cast<size_t>(std::roundf(kReadAttemptSleepUs));
+ char* buff = (char*)buffer;
+ size_t remainingFrames = frameCount;
+
+ while ((remainingFrames > 0) && (attempts < kMaxReadFailureAttempts)) {
+ LOG(VERBOSE) << __func__ << ": frames available to read " << source->availableToRead();
+
+ ssize_t framesRead = source->read(buff, remainingFrames);
+
+ LOG(VERBOSE) << __func__ << ": frames read " << framesRead;
+
+ if (framesRead > 0) {
+ remainingFrames -= framesRead;
+ buff += framesRead * mStreamConfig.frameSize;
+ LOG(VERBOSE) << __func__ << ": (attempts = " << attempts << ") got " << framesRead
+ << " frames, remaining=" << remainingFrames;
+ } else {
+ attempts++;
+ LOG(WARNING) << __func__ << ": read returned " << framesRead
+ << " , read failure attempts = " << attempts;
+ usleep(delayUs);
+ }
+ }
+ // done using the source
+ source.clear();
+
+ if (remainingFrames > 0) {
+ const size_t remainingBytes = remainingFrames * mStreamConfig.frameSize;
+ LOG(VERBOSE) << __func__ << ": clearing remaining_frames = " << remainingFrames;
+ memset(((char*)buffer) + (mStreamConfig.frameSize * frameCount) - remainingBytes, 0,
+ remainingBytes);
+ }
+
+ long readCounterFrames = mCurrentRoute->updateReadCounterFrames(frameCount);
+ *actualFrameCount = frameCount;
+
+ // compute how much we need to sleep after reading the data by comparing the wall clock with
+ // the projected time at which we should return.
+ // wall clock after reading from the pipe
+ auto recordDurationUs = std::chrono::steady_clock::now() - mCurrentRoute->getRecordStartTime();
+
+ // readCounterFrames contains the number of frames that have been read since the beginning of
+ // recording (including this call): it's converted to usec and compared to how long we've been
+ // recording for, which gives us how long we must wait to sync the projected recording time, and
+ // the observed recording time.
+ static constexpr float kScaleFactor = .8f;
+ const size_t projectedVsObservedOffsetUs =
+ kScaleFactor * (static_cast<size_t>(std::roundf((readCounterFrames * MICROS_PER_SECOND /
+ mStreamConfig.sampleRate) -
+ recordDurationUs.count())));
+
+ LOG(VERBOSE) << __func__ << ": record duration " << recordDurationUs.count()
+ << " microseconds, will wait: " << projectedVsObservedOffsetUs << " microseconds";
+ if (projectedVsObservedOffsetUs > 0) {
+ usleep(projectedVsObservedOffsetUs);
+ }
+ return ::android::OK;
+}
+
+StreamInRemoteSubmix::StreamInRemoteSubmix(const SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones)
+ : StreamRemoteSubmix(sinkMetadata, std::move(context)), StreamIn(microphones) {}
+
+ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
+ std::vector<MicrophoneDynamicInfo>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": not supported";
+ *_aidl_return = std::vector<MicrophoneDynamicInfo>();
+ return ndk::ScopedAStatus::ok();
+}
+
+StreamOutRemoteSubmix::StreamOutRemoteSubmix(const SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<AudioOffloadInfo>& offloadInfo)
+ : StreamRemoteSubmix(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
new file mode 100644
index 0000000..8f5b8cb
--- /dev/null
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_SubmixRoute"
+#include <android-base/logging.h>
+#include <media/AidlConversionCppNdk.h>
+
+#include <Utils.h>
+
+#include "SubmixRoute.h"
+
+using aidl::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+// Verify a submix input or output stream can be opened.
+bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig streamConfig) {
+ // If the stream is already open, don't open it again.
+ // ENABLE_LEGACY_INPUT_OPEN is default behaviour
+ if (!isInput && isStreamOutOpen()) {
+ LOG(ERROR) << __func__ << ": output stream already open.";
+ return false;
+ }
+ // If either stream is open, verify the existing pipe config matches the stream config.
+ if (hasAtleastOneStreamOpen() && !isStreamConfigCompatible(streamConfig)) {
+ return false;
+ }
+ return true;
+}
+
+// Compare this stream config with existing pipe config, returning false if they do *not*
+// match, true otherwise.
+bool SubmixRoute::isStreamConfigCompatible(const AudioConfig streamConfig) {
+ if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
+ LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
+ << streamConfig.channelLayout.toString()
+ << " pipe config channels = " << mPipeConfig.channelLayout.toString();
+ return false;
+ }
+ if (streamConfig.sampleRate != mPipeConfig.sampleRate) {
+ LOG(ERROR) << __func__
+ << ": sample rate mismatch, stream sample rate = " << streamConfig.sampleRate
+ << " pipe config sample rate = " << mPipeConfig.sampleRate;
+ return false;
+ }
+ if (streamConfig.format != mPipeConfig.format) {
+ LOG(ERROR) << __func__
+ << ": format mismatch, stream format = " << streamConfig.format.toString()
+ << " pipe config format = " << mPipeConfig.format.toString();
+ return false;
+ }
+ return true;
+}
+
+bool SubmixRoute::hasAtleastOneStreamOpen() {
+ std::lock_guard guard(mLock);
+ return (mStreamInOpen || mStreamOutOpen);
+}
+
+// We DO NOT block if:
+// - no peer input stream is present
+// - the peer input is in standby AFTER having been active.
+// We DO block if:
+// - the input was never activated to avoid discarding first frames in the pipe in case capture
+// start was delayed
+bool SubmixRoute::shouldBlockWrite() {
+ std::lock_guard guard(mLock);
+ return (mStreamInOpen || (mStreamInStandby && (mReadCounterFrames != 0)));
+}
+
+int SubmixRoute::notifyReadError() {
+ std::lock_guard guard(mLock);
+ return ++mReadErrorCount;
+}
+
+long SubmixRoute::updateReadCounterFrames(size_t frameCount) {
+ std::lock_guard guard(mLock);
+ mReadCounterFrames += frameCount;
+ return mReadCounterFrames;
+}
+
+void SubmixRoute::openStream(bool isInput) {
+ std::lock_guard guard(mLock);
+ if (isInput) {
+ if (mStreamInOpen) {
+ mInputRefCount++;
+ } else {
+ mInputRefCount = 1;
+ mStreamInOpen = true;
+ }
+ mStreamInStandby = true;
+ mReadCounterFrames = 0;
+ mReadErrorCount = 0;
+ } else {
+ mStreamOutOpen = true;
+ }
+}
+
+void SubmixRoute::closeStream(bool isInput) {
+ std::lock_guard guard(mLock);
+ if (isInput) {
+ mInputRefCount--;
+ if (mInputRefCount == 0) {
+ mStreamInOpen = false;
+ if (mSink != nullptr) {
+ mSink->shutdown(true);
+ }
+ }
+ } else {
+ mStreamOutOpen = false;
+ }
+}
+
+// If SubmixRoute doesn't exist for a port, create a pipe for the submix audio device of size
+// buffer_size_frames and store config of the submix audio device.
+::android::status_t SubmixRoute::createPipe(const AudioConfig streamConfig) {
+ const int channelCount = getChannelCount(streamConfig.channelLayout);
+ const audio_format_t audioFormat = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioFormatDescription_audio_format_t(streamConfig.format));
+ const ::android::NBAIO_Format format =
+ ::android::Format_from_SR_C(streamConfig.sampleRate, channelCount, audioFormat);
+ const ::android::NBAIO_Format offers[1] = {format};
+ size_t numCounterOffers = 0;
+
+ const size_t pipeSizeInFrames =
+ r_submix::kDefaultPipeSizeInFrames *
+ ((float)streamConfig.sampleRate / r_submix::kDefaultSampleRateHz);
+ LOG(VERBOSE) << __func__ << ": creating pipe, rate : " << streamConfig.sampleRate
+ << ", pipe size : " << pipeSizeInFrames;
+
+ // Create a MonoPipe with optional blocking set to true.
+ sp<MonoPipe> sink = sp<MonoPipe>::make(pipeSizeInFrames, format, true /*writeCanBlock*/);
+ if (sink == nullptr) {
+ LOG(FATAL) << __func__ << ": sink is null";
+ return ::android::UNEXPECTED_NULL;
+ }
+
+ // Negotiation between the source and sink cannot fail as the device open operation
+ // creates both ends of the pipe using the same audio format.
+ ssize_t index = sink->negotiate(offers, 1, nullptr, numCounterOffers);
+ if (index != 0) {
+ LOG(FATAL) << __func__ << ": Negotiation for the sink failed, index = " << index;
+ return ::android::BAD_INDEX;
+ }
+ sp<MonoPipeReader> source = sp<MonoPipeReader>::make(sink.get());
+ if (source == nullptr) {
+ LOG(FATAL) << __func__ << ": source is null";
+ return ::android::UNEXPECTED_NULL;
+ }
+ numCounterOffers = 0;
+ index = source->negotiate(offers, 1, nullptr, numCounterOffers);
+ if (index != 0) {
+ LOG(FATAL) << __func__ << ": Negotiation for the source failed, index = " << index;
+ return ::android::BAD_INDEX;
+ }
+ LOG(VERBOSE) << __func__ << ": created pipe";
+
+ mPipeConfig = streamConfig;
+ mPipeConfig.frameCount = sink->maxFrames();
+
+ LOG(VERBOSE) << __func__ << ": Pipe frame size : " << mPipeConfig.frameSize
+ << ", pipe frames : " << mPipeConfig.frameCount;
+
+ // Save references to the source and sink.
+ {
+ std::lock_guard guard(mLock);
+ mSink = std::move(sink);
+ mSource = std::move(source);
+ }
+
+ return ::android::OK;
+}
+
+// Release references to the sink and source.
+void SubmixRoute::releasePipe() {
+ std::lock_guard guard(mLock);
+ mSink.clear();
+ mSource.clear();
+}
+
+::android::status_t SubmixRoute::resetPipe() {
+ releasePipe();
+ return createPipe(mPipeConfig);
+}
+
+void SubmixRoute::standby(bool isInput) {
+ std::lock_guard guard(mLock);
+
+ if (isInput) {
+ mStreamInStandby = true;
+ } else {
+ mStreamOutStandby = true;
+ mStreamOutStandbyTransition = !mStreamOutStandbyTransition;
+ }
+}
+
+void SubmixRoute::exitStandby(bool isInput) {
+ std::lock_guard guard(mLock);
+
+ if (isInput) {
+ if (mStreamInStandby || mStreamOutStandbyTransition) {
+ mStreamInStandby = false;
+ mStreamOutStandbyTransition = false;
+ // keep track of when we exit input standby (== first read == start "real recording")
+ // or when we start recording silence, and reset projected time
+ mRecordStartTime = std::chrono::steady_clock::now();
+ mReadCounterFrames = 0;
+ }
+ } else {
+ if (mStreamOutStandby) {
+ mStreamOutStandby = false;
+ mStreamOutStandbyTransition = true;
+ }
+ }
+}
+
+} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
new file mode 100644
index 0000000..5f7ea75
--- /dev/null
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mutex>
+
+#include <audio_utils/clock.h>
+
+#include <media/nbaio/MonoPipe.h>
+#include <media/nbaio/MonoPipeReader.h>
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+
+#include "core-impl/Stream.h"
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::PcmType;
+using ::android::MonoPipe;
+using ::android::MonoPipeReader;
+using ::android::sp;
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+static constexpr int kDefaultSampleRateHz = 48000;
+// Size at default sample rate
+// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe().
+static constexpr int kDefaultPipeSizeInFrames = (1024 * 4);
+
+// Configuration of the audio stream.
+struct AudioConfig {
+ int sampleRate = kDefaultSampleRateHz;
+ AudioFormatDescription format =
+ AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
+ AudioChannelLayout channelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO);
+ size_t frameSize;
+ size_t frameCount;
+};
+
+class SubmixRoute {
+ public:
+ AudioConfig mPipeConfig;
+
+ bool isStreamInOpen() {
+ std::lock_guard guard(mLock);
+ return mStreamInOpen;
+ }
+ bool getStreamInStandby() {
+ std::lock_guard guard(mLock);
+ return mStreamInStandby;
+ }
+ bool isStreamOutOpen() {
+ std::lock_guard guard(mLock);
+ return mStreamOutOpen;
+ }
+ bool getStreamOutStandby() {
+ std::lock_guard guard(mLock);
+ return mStreamOutStandby;
+ }
+ long getReadCounterFrames() {
+ std::lock_guard guard(mLock);
+ return mReadCounterFrames;
+ }
+ int getReadErrorCount() {
+ std::lock_guard guard(mLock);
+ return mReadErrorCount;
+ }
+ std::chrono::time_point<std::chrono::steady_clock> getRecordStartTime() {
+ std::lock_guard guard(mLock);
+ return mRecordStartTime;
+ }
+ sp<MonoPipe> getSink() {
+ std::lock_guard guard(mLock);
+ return mSink;
+ }
+ sp<MonoPipeReader> getSource() {
+ std::lock_guard guard(mLock);
+ return mSource;
+ }
+
+ bool isStreamConfigValid(bool isInput, const AudioConfig streamConfig);
+ void closeStream(bool isInput);
+ ::android::status_t createPipe(const AudioConfig streamConfig);
+ void exitStandby(bool isInput);
+ bool hasAtleastOneStreamOpen();
+ int notifyReadError();
+ void openStream(bool isInput);
+ void releasePipe();
+ ::android::status_t resetPipe();
+ bool shouldBlockWrite();
+ void standby(bool isInput);
+ long updateReadCounterFrames(size_t frameCount);
+
+ private:
+ bool isStreamConfigCompatible(const AudioConfig streamConfig);
+
+ std::mutex mLock;
+
+ bool mStreamInOpen GUARDED_BY(mLock) = false;
+ int mInputRefCount GUARDED_BY(mLock) = 0;
+ bool mStreamInStandby GUARDED_BY(mLock) = true;
+ bool mStreamOutStandbyTransition GUARDED_BY(mLock) = false;
+ bool mStreamOutOpen GUARDED_BY(mLock) = false;
+ bool mStreamOutStandby GUARDED_BY(mLock) = true;
+ // how many frames have been requested to be read since standby
+ long mReadCounterFrames GUARDED_BY(mLock) = 0;
+ int mReadErrorCount GUARDED_BY(mLock) = 0;
+ // wall clock when recording starts
+ std::chrono::time_point<std::chrono::steady_clock> mRecordStartTime GUARDED_BY(mLock);
+
+ // Pipe variables: they handle the ring buffer that "pipes" audio:
+ // - from the submix virtual audio output == what needs to be played
+ // remotely, seen as an output for the client
+ // - to the virtual audio source == what is captured by the component
+ // which "records" the submix / virtual audio source, and handles it as needed.
+ // A usecase example is one where the component capturing the audio is then sending it over
+ // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a
+ // TV with Wifi Display capabilities), or to a wireless audio player.
+ sp<MonoPipe> mSink GUARDED_BY(mLock);
+ sp<MonoPipeReader> mSource GUARDED_BY(mLock);
+};
+
+} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp b/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp
new file mode 100644
index 0000000..572bc5a
--- /dev/null
+++ b/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <memory>
+// #include <string>
+// #include <vector>
+
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+#define LOG_TAG "AudioPolicyConfigXmlConverterTest"
+#include <log/log.h>
+
+#include <core-impl/AudioPolicyConfigXmlConverter.h>
+#include <media/AidlConversionCppNdk.h>
+
+using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter;
+using aidl::android::media::audio::common::AudioFormatDescription;
+
+namespace {
+
+void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
+ auto conv = ::aidl::android::aidl2legacy_AudioFormatDescription_audio_format_t(format);
+ ASSERT_TRUE(conv.ok()) << format.toString();
+}
+
+} // namespace
+
+TEST(AudioPolicyConfigXmlConverterTest, DefaultSurroundSoundConfigIsValid) {
+ auto config = AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig();
+ for (const auto& family : config.formatFamilies) {
+ EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
+ SCOPED_TRACE(family.primaryFormat.toString());
+ for (const auto& sub : family.subFormats) {
+ EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(sub));
+ }
+ }
+}
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index ecdbd5c..5c9d477 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -25,22 +25,27 @@
#include "UsbAlsaMixerControl.h"
#include "UsbAlsaUtils.h"
#include "core-impl/ModuleUsb.h"
+#include "core-impl/StreamUsb.h"
extern "C" {
#include "alsa_device_profile.h"
}
-using aidl::android::hardware::audio::common::isUsbInputDeviceType;
+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::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
@@ -97,6 +102,25 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus ModuleUsb::createInputStream(const SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInUsb>(result, sinkMetadata, std::move(context), microphones);
+}
+
+ndk::ScopedAStatus ModuleUsb::createOutputStream(const SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ std::shared_ptr<StreamOut>* result) {
+ if (offloadInfo.has_value()) {
+ LOG(ERROR) << __func__ << ": offload is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ return createStreamInstance<StreamOutUsb>(result, sourceMetadata, std::move(context),
+ offloadInfo);
+}
+
ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
if (audioPort->ext.getTag() != AudioPortExt::Tag::device) {
LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a device port";
@@ -117,7 +141,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- const bool isInput = isUsbInputDeviceType(devicePort.device.type.type);
+ const bool isInput = audioPort->flags.getTag() == AudioIoFlags::input;
alsa_device_profile profile;
profile_init(&profile, isInput ? PCM_IN : PCM_OUT);
profile.card = alsaAddress[0];
@@ -175,8 +199,8 @@
return;
}
const int card = address.get<AudioDeviceAddress::alsa>()[0];
- usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, mMasterMute,
- mMasterVolume, connected);
+ usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, getMasterMute(),
+ getMasterVolume(), connected);
}
ndk::ScopedAStatus ModuleUsb::onMasterMuteChanged(bool mute) {
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index 5d1d7fe..17e1ab4 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -14,10 +14,13 @@
* limitations under the License.
*/
+#include <limits>
+
#define LOG_TAG "AHAL_StreamUsb"
#include <android-base/logging.h>
#include <Utils.h>
+#include <error/expected_utils.h>
#include "UsbAlsaMixerControl.h"
#include "UsbAlsaUtils.h"
@@ -42,116 +45,126 @@
namespace aidl::android::hardware::audio::core {
-DriverUsb::DriverUsb(const StreamContext& context, bool isInput)
- : mFrameSizeBytes(context.getFrameSize()), mIsInput(isInput) {
+StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context)
+ : StreamCommonImpl(metadata, std::move(context)),
+ mFrameSizeBytes(getContext().getFrameSize()),
+ mIsInput(isInput(metadata)),
+ mConfig(maybePopulateConfig(getContext(), mIsInput)) {}
+
+// static
+std::optional<struct pcm_config> StreamUsb::maybePopulateConfig(const StreamContext& context,
+ bool isInput) {
struct pcm_config config;
config.channels = usb::getChannelCountFromChannelMask(context.getChannelLayout(), isInput);
if (config.channels == 0) {
LOG(ERROR) << __func__ << ": invalid channel=" << context.getChannelLayout().toString();
- return;
+ return std::nullopt;
}
config.format = usb::aidl2legacy_AudioFormatDescription_pcm_format(context.getFormat());
if (config.format == PCM_FORMAT_INVALID) {
LOG(ERROR) << __func__ << ": invalid format=" << context.getFormat().toString();
- return;
+ return std::nullopt;
}
config.rate = context.getSampleRate();
if (config.rate == 0) {
LOG(ERROR) << __func__ << ": invalid sample rate=" << config.rate;
- return;
+ return std::nullopt;
}
- mConfig = config;
+ return config;
}
-::android::status_t DriverUsb::init() {
+::android::status_t StreamUsb::init() {
return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
}
-::android::status_t DriverUsb::setConnectedDevices(
+const StreamCommonInterface::ConnectedDevices& StreamUsb::getConnectedDevices() const {
+ std::lock_guard guard(mLock);
+ return mConnectedDevices;
+}
+
+ndk::ScopedAStatus StreamUsb::setConnectedDevices(
const std::vector<AudioDevice>& connectedDevices) {
if (mIsInput && connectedDevices.size() > 1) {
LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
<< ") for input stream";
- return ::android::BAD_VALUE;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
for (const auto& connectedDevice : connectedDevices) {
if (connectedDevice.address.getTag() != AudioDeviceAddress::alsa) {
LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
- return ::android::BAD_VALUE;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
}
std::lock_guard guard(mLock);
- mAlsaDeviceProxies.clear();
- mConnectedDevices.clear();
- for (const auto& connectedDevice : connectedDevices) {
- mConnectedDevices.push_back(connectedDevice.address);
- }
- return ::android::OK;
+ RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
+ mConnectedDevicesUpdated.store(true, std::memory_order_release);
+ return ndk::ScopedAStatus::ok();
}
-::android::status_t DriverUsb::drain(StreamDescriptor::DrainMode) {
+::android::status_t StreamUsb::drain(StreamDescriptor::DrainMode) {
usleep(1000);
return ::android::OK;
}
-::android::status_t DriverUsb::flush() {
+::android::status_t StreamUsb::flush() {
usleep(1000);
return ::android::OK;
}
-::android::status_t DriverUsb::pause() {
+::android::status_t StreamUsb::pause() {
usleep(1000);
return ::android::OK;
}
-::android::status_t DriverUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) {
- if (!mConfig.has_value() || mConnectedDevices.empty()) {
- LOG(ERROR) << __func__ << ": failed, has config: " << mConfig.has_value()
- << ", has connected devices: " << mConnectedDevices.empty();
- return ::android::NO_INIT;
- }
- if (mIsStandby) {
- if (::android::status_t status = exitStandby(); status != ::android::OK) {
- LOG(ERROR) << __func__ << ": failed to exit standby, status=" << status;
- return status;
- }
- }
- std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
- {
- std::lock_guard guard(mLock);
- alsaDeviceProxies = mAlsaDeviceProxies;
+ if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) {
+ // 'setConnectedDevices' has been called. I/O will be restarted.
+ *actualFrameCount = 0;
+ *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
+ return ::android::OK;
}
const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
+ unsigned maxLatency = 0;
if (mIsInput) {
+ if (mAlsaDeviceProxies.empty()) {
+ LOG(FATAL) << __func__ << ": no input devices";
+ return ::android::NO_INIT;
+ }
// For input case, only support single device.
- proxy_read(alsaDeviceProxies[0].get(), buffer, bytesToTransfer);
+ proxy_read(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer);
+ maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
} else {
- for (auto& proxy : alsaDeviceProxies) {
+ for (auto& proxy : mAlsaDeviceProxies) {
proxy_write(proxy.get(), buffer, bytesToTransfer);
+ maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
}
}
*actualFrameCount = frameCount;
- *latencyMs = Module::kLatencyMs;
+ maxLatency = std::min(maxLatency, static_cast<unsigned>(std::numeric_limits<int32_t>::max()));
+ *latencyMs = maxLatency;
return ::android::OK;
}
-::android::status_t DriverUsb::standby() {
- if (!mIsStandby) {
- std::lock_guard guard(mLock);
- mAlsaDeviceProxies.clear();
- mIsStandby = true;
- }
+::android::status_t StreamUsb::standby() {
+ mAlsaDeviceProxies.clear();
return ::android::OK;
}
-::android::status_t DriverUsb::exitStandby() {
+void StreamUsb::shutdown() {
+ mAlsaDeviceProxies.clear();
+}
+
+::android::status_t StreamUsb::start() {
std::vector<AudioDeviceAddress> connectedDevices;
{
std::lock_guard guard(mLock);
- connectedDevices = mConnectedDevices;
+ std::transform(mConnectedDevices.begin(), mConnectedDevices.end(),
+ std::back_inserter(connectedDevices),
+ [](const auto& device) { return device.address; });
+ mConnectedDevicesUpdated.store(false, std::memory_order_release);
}
- std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
+ decltype(mAlsaDeviceProxies) alsaDeviceProxies;
for (const auto& device : connectedDevices) {
alsa_device_profile profile;
profile_init(&profile, mIsInput ? PCM_IN : PCM_OUT);
@@ -163,16 +176,16 @@
return ::android::UNKNOWN_ERROR;
}
- auto proxy = std::shared_ptr<alsa_device_proxy>(new alsa_device_proxy(),
- [](alsa_device_proxy* proxy) {
- proxy_close(proxy);
- free(proxy);
- });
+ AlsaDeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
+ proxy_close(proxy);
+ free(proxy);
+ });
// Always ask for alsa configure as required since the configuration should be supported
// by the connected device. That is guaranteed by `setAudioPortConfig` and
// `setAudioPatch`.
- if (int err =
- proxy_prepare(proxy.get(), &profile, &mConfig.value(), true /*is_bit_perfect*/);
+ if (int err = proxy_prepare(proxy.get(), &profile,
+ const_cast<struct pcm_config*>(&mConfig.value()),
+ true /*is_bit_perfect*/);
err != 0) {
LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device.toString()
<< " error=" << err;
@@ -185,40 +198,13 @@
}
alsaDeviceProxies.push_back(std::move(proxy));
}
- {
- std::lock_guard guard(mLock);
- mAlsaDeviceProxies = alsaDeviceProxies;
- }
- mIsStandby = false;
+ mAlsaDeviceProxies = std::move(alsaDeviceProxies);
return ::android::OK;
}
-// static
-ndk::ScopedAStatus StreamInUsb::createInstance(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result) {
- std::shared_ptr<StreamIn> stream =
- ndk::SharedRefBase::make<StreamInUsb>(sinkMetadata, std::move(context), microphones);
- if (auto status = initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(
- sinkMetadata, std::move(context),
- [](const StreamContext& ctx) -> DriverInterface* {
- return new DriverUsb(ctx, true /*isInput*/);
- },
- [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
- // The default worker implementation is used.
- return new StreamInWorker(ctx, driver);
- },
- microphones) {}
+ : StreamUsb(sinkMetadata, std::move(context)), StreamIn(microphones) {}
ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -226,37 +212,10 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-// static
-ndk::ScopedAStatus StreamOutUsb::createInstance(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<AudioOffloadInfo>& offloadInfo,
- std::shared_ptr<StreamOut>* result) {
- if (offloadInfo.has_value()) {
- LOG(ERROR) << __func__ << ": offload is not supported";
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- }
- std::shared_ptr<StreamOut> stream =
- ndk::SharedRefBase::make<StreamOutUsb>(sourceMetadata, std::move(context), offloadInfo);
- if (auto status = initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamOut(
- sourceMetadata, std::move(context),
- [](const StreamContext& ctx) -> DriverInterface* {
- return new DriverUsb(ctx, false /*isInput*/);
- },
- [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
- // The default worker implementation is used.
- return new StreamOutWorker(ctx, driver);
- },
- offloadInfo) {
- mChannelCount = getChannelCount(mContext.getChannelLayout());
+ : StreamUsb(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {
+ mChannelCount = getChannelCount(getContext().getChannelLayout());
}
ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
@@ -265,7 +224,7 @@
}
ndk::ScopedAStatus StreamOutUsb::setHwVolume(const std::vector<float>& in_channelVolumes) {
- for (const auto& device : mConnectedDevices) {
+ for (const auto& device : getConnectedDevices()) {
if (device.address.getTag() != AudioDeviceAddress::alsa) {
LOG(DEBUG) << __func__ << ": skip as the device address is not alsa";
continue;
diff --git a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
index b5337d1..6c0c24b 100644
--- a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
+++ b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
@@ -99,16 +99,6 @@
return minValue + std::ceil((maxValue - minValue) * fValue);
}
-float volumeIntegerToFloat(int iValue, int maxValue, int minValue) {
- if (iValue > maxValue) {
- return 1.0f;
- }
- if (iValue < minValue) {
- return 0.0f;
- }
- return static_cast<float>(iValue - minValue) / (maxValue - minValue);
-}
-
} // namespace
ndk::ScopedAStatus AlsaMixer::setMasterMute(bool muted) {
@@ -146,11 +136,14 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
const int numValues = it->second->getNumValues();
+ if (numValues < 0) {
+ LOG(FATAL) << __func__ << ": negative number of values: " << numValues;
+ }
const int maxValue = it->second->getMaxValue();
const int minValue = it->second->getMinValue();
std::vector<int> values;
size_t i = 0;
- for (; i < numValues && i < values.size(); ++i) {
+ for (; i < static_cast<size_t>(numValues) && i < values.size(); ++i) {
values.emplace_back(volumeFloatToInteger(volumes[i], maxValue, minValue));
}
if (int err = it->second->setArray(values.data(), values.size()); err != 0) {
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 4e84f6b..685d07d 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -30,6 +30,7 @@
#include <android/binder_auto_utils.h>
#include <fmq/AidlMessageQueue.h>
#include <gtest/gtest.h>
+#include <system/audio_aidl_utils.h>
#include <system/audio_effects/aidl_effects_utils.h>
#include <system/audio_effects/effect_uuid.h>
@@ -51,6 +52,7 @@
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioUuid;
using aidl::android::media::audio::common::PcmType;
+using ::android::audio::utils::toString;
using ::android::hardware::EventFlag;
const AudioFormatDescription kDefaultFormatDescription = {
@@ -63,6 +65,12 @@
::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
DataMQ;
+static inline std::string getPrefix(Descriptor& descriptor) {
+ std::string prefix = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" + toString(descriptor.common.id.uuid);
+ return prefix;
+}
+
class EffectHelper {
public:
static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
@@ -71,7 +79,7 @@
auto& id = desc.common.id;
ASSERT_STATUS(status, factory->createEffect(id.uuid, &effect));
if (status == EX_NONE) {
- ASSERT_NE(effect, nullptr) << id.uuid.toString();
+ ASSERT_NE(effect, nullptr) << toString(id.uuid);
}
}
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index 72ca56f..10c2fc6 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -77,3 +77,10 @@
#define EXPECT_STATUS(expected, ret) \
EXPECT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
expected, ret)
+
+#define SKIP_TEST_IF_DATA_UNSUPPORTED(flags) \
+ ({ \
+ if ((flags).hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL || (flags).bypass) { \
+ GTEST_SKIP() << "Skip data path for offload"; \
+ } \
+ })
\ No newline at end of file
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 8828c41..1a7c3d4 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -162,10 +162,8 @@
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string echoDelay = std::to_string(std::get<PARAM_ECHO_DELAY>(info.param));
std::string mobileMode = std::get<PARAM_MOBILE_MODE>(info.param) ? "true" : "false";
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_EchoDelay_" + echoDelay +
- "_MobileMode_" + mobileMode;
+ std::string name =
+ getPrefix(descriptor) + "_EchoDelay_" + echoDelay + "_MobileMode_" + mobileMode;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index edfcdf6..65c6a8f 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -177,11 +177,9 @@
std::to_string(std::get<PARAM_MAX_COMPRESSION_GAIN>(info.param));
std::string enableLimiter = std::to_string(std::get<PARAM_ENABLE_LIMITER>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_target_peak_level_" +
- targetPeakLevel + "_max_compression_gain_" + maxCompressionGain +
- "_enable_limiter_" + enableLimiter;
+ std::string name = getPrefix(descriptor) + "_target_peak_level_" + targetPeakLevel +
+ "_max_compression_gain_" + maxCompressionGain + "_enable_limiter_" +
+ enableLimiter;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 8ba8e45..46a569e 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -183,9 +183,7 @@
std::string margin =
std::to_string(static_cast<int>(std::get<PARAM_SATURATION_MARGIN>(info.param)));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_digital_gain_" + gain +
+ std::string name = getPrefix(descriptor) + "_digital_gain_" + gain +
"_level_estimator_" + estimator + "_margin_" + margin;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index e5e06eb..f82e8e5 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -20,21 +20,27 @@
#include <unordered_set>
#include <vector>
+#define LOG_TAG "VtsHalAudioCore.Config"
+
+#include <Utils.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/core/IConfig.h>
#include <aidl/android/media/audio/common/AudioFlag.h>
#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
-#define LOG_TAG "VtsHalAudioCore.Config"
#include <android-base/logging.h>
#include "AudioHalBinderServiceUtil.h"
#include "TestUtils.h"
using namespace android;
+using aidl::android::hardware::audio::common::isDefaultAudioFormat;
using aidl::android::hardware::audio::core::IConfig;
+using aidl::android::hardware::audio::core::SurroundSoundConfig;
using aidl::android::media::audio::common::AudioAttributes;
using aidl::android::media::audio::common::AudioFlag;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioHalAttributesGroup;
using aidl::android::media::audio::common::AudioHalCapCriterion;
using aidl::android::media::audio::common::AudioHalCapCriterionType;
@@ -46,6 +52,7 @@
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioStreamType;
using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::PcmType;
class AudioCoreConfig : public testing::TestWithParam<std::string> {
public:
@@ -58,6 +65,7 @@
void RestartService() {
ASSERT_NE(mConfig, nullptr);
mEngineConfig.reset();
+ mSurroundSoundConfig.reset();
mConfig = IConfig::fromBinder(mBinderUtil.restartService());
ASSERT_NE(mConfig, nullptr);
}
@@ -70,6 +78,14 @@
}
}
+ void SetUpSurroundSoundConfig() {
+ if (mSurroundSoundConfig == nullptr) {
+ auto tempConfig = std::make_unique<SurroundSoundConfig>();
+ ASSERT_IS_OK(mConfig->getSurroundSoundConfig(tempConfig.get()));
+ mSurroundSoundConfig = std::move(tempConfig);
+ }
+ }
+
static bool IsProductStrategyTypeReservedForSystemUse(const AudioProductStrategyType& pst) {
switch (pst) {
case AudioProductStrategyType::SYS_RESERVED_NONE:
@@ -325,9 +341,41 @@
}
}
+ void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
+ EXPECT_NE(AudioFormatType::SYS_RESERVED_INVALID, format.type);
+ if (format.type == AudioFormatType::PCM) {
+ EXPECT_NE(PcmType::DEFAULT, format.pcm);
+ EXPECT_TRUE(format.encoding.empty()) << format.encoding;
+ } else {
+ EXPECT_FALSE(format.encoding.empty());
+ }
+ }
+
+ /**
+ * Verify that the surround sound configuration is not empty.
+ * Verify each of the formatFamilies has a non-empty primaryFormat.
+ * Verify that each format only appears once.
+ */
+ void ValidateSurroundSoundConfig() {
+ EXPECT_FALSE(mSurroundSoundConfig->formatFamilies.empty());
+ std::set<AudioFormatDescription> formatSet;
+ for (const SurroundSoundConfig::SurroundFormatFamily& family :
+ mSurroundSoundConfig->formatFamilies) {
+ EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
+ EXPECT_FALSE(isDefaultAudioFormat(family.primaryFormat));
+ EXPECT_TRUE(formatSet.insert(family.primaryFormat).second);
+ for (const AudioFormatDescription& subformat : family.subFormats) {
+ EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(subformat));
+ EXPECT_FALSE(isDefaultAudioFormat(subformat));
+ EXPECT_TRUE(formatSet.insert(subformat).second);
+ }
+ }
+ }
+
private:
std::shared_ptr<IConfig> mConfig;
std::unique_ptr<AudioHalEngineConfig> mEngineConfig;
+ std::unique_ptr<SurroundSoundConfig> mSurroundSoundConfig;
AudioHalBinderServiceUtil mBinderUtil;
};
@@ -344,6 +392,11 @@
EXPECT_NO_FATAL_FAILURE(ValidateAudioHalEngineConfig());
}
+TEST_P(AudioCoreConfig, GetSurroundSoundConfigIsValid) {
+ ASSERT_NO_FATAL_FAILURE(SetUpSurroundSoundConfig());
+ EXPECT_NO_FATAL_FAILURE(ValidateSurroundSoundConfig());
+}
+
INSTANTIATE_TEST_SUITE_P(AudioCoreConfigTest, AudioCoreConfig,
testing::ValuesIn(android::getAidlHalInstanceNames(IConfig::descriptor)),
android::PrintInstanceNameToString);
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 825b865..0012cd5 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -2763,6 +2763,7 @@
ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
std::vector<MicrophoneDynamicInfo> activeMics;
EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+ EXPECT_FALSE(activeMics.empty());
for (const auto& mic : activeMics) {
EXPECT_NE(micInfos.end(),
std::find_if(micInfos.begin(), micInfos.end(),
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 9cd6c22..8084a59 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -36,6 +36,11 @@
#include "EffectFactoryHelper.h"
#include "TestUtils.h"
+#include <system/audio_aidl_utils.h>
+
+using namespace android;
+using ::android::audio::utils::toString;
+
using namespace android;
using aidl::android::hardware::audio::effect::Descriptor;
@@ -93,7 +98,7 @@
std::shared_ptr<IEffect> effect;
EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(uuid, &effect));
if (expectStatus == EX_NONE) {
- EXPECT_NE(effect, nullptr) << " null effect with uuid: " << uuid.toString();
+ EXPECT_NE(effect, nullptr) << " null effect with uuid: " << toString(uuid);
effects.push_back(std::move(effect));
}
}
@@ -148,7 +153,7 @@
}
std::string msg = " missing type UUID:\n";
for (const auto& uuid : typeUuidSet) {
- msg += (uuid.toString() + "\n");
+ msg += (toString(uuid) + "\n");
}
SCOPED_TRACE(msg);
EXPECT_EQ(0UL, typeUuidSet.size());
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 436f2a3..3011a5e 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -46,6 +46,7 @@
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::Flags;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioMode;
@@ -85,6 +86,14 @@
}
};
+class AudioEffectDataPathTest : public AudioEffectTest {
+ public:
+ void SetUp() override {
+ AudioEffectTest::SetUp();
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ }
+};
+
TEST_P(AudioEffectTest, SetupAndTearDown) {
// Intentionally empty test body.
}
@@ -577,7 +586,8 @@
/// Data processing test
// Send data to effects and expect it to be consumed by checking statusMQ.
-TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataInProcessingState) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -610,7 +620,8 @@
}
// Send data to effects and expect it to be consumed after effect restart.
-TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataAfterRestart) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -649,7 +660,8 @@
}
// Send data to IDLE effects and expect it to be consumed after effect start.
-TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, SendDataAtIdleAndConsumeDataInProcessing) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -682,7 +694,8 @@
}
// Send data multiple times.
-TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ProcessDataMultipleTimes) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -721,7 +734,8 @@
}
// Send data to processing state effects, stop, and restart.
-TEST_P(AudioEffectTest, ConsumeDataAndRestart) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataAndRestart) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -762,7 +776,8 @@
}
// Send data to closed effects and expect it not be consumed.
-TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, NotConsumeDataByClosedEffect) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -788,7 +803,8 @@
}
// Send data to multiple effects.
-TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataMultipleEffects) {
std::shared_ptr<IEffect> effect1, effect2;
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
@@ -848,16 +864,27 @@
EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
[](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_TYPE_" +
- descriptor.common.id.type.toString() + "_UUID_" +
- descriptor.common.id.uuid.toString();
+ std::string name = getPrefix(descriptor);
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
});
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
+INSTANTIATE_TEST_SUITE_P(
+ SingleEffectInstanceTest, AudioEffectDataPathTest,
+ ::testing::Combine(testing::ValuesIn(
+ EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
+ [](const testing::TestParamInfo<AudioEffectDataPathTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string name = getPrefix(descriptor);
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectDataPathTest);
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 9cfdc50..afddb84 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -145,9 +145,7 @@
[](const testing::TestParamInfo<BassBoostParamTest::ParamType>& info) {
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_strength_" + strength;
+ std::string name = getPrefix(descriptor) + "_strength_" + strength;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index 5aeebde..7a2f31b 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -126,9 +126,7 @@
[](const testing::TestParamInfo<DownmixParamTest::ParamType>& info) {
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string type = std::to_string(static_cast<int>(std::get<PARAM_TYPE>(info.param)));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_type" + type;
+ std::string name = getPrefix(descriptor) + "_type" + type;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 033e3b5..5509c76 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -513,9 +513,7 @@
auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
DynamicsProcessing::EngineArchitecture cfg;
fillEngineArchConfig(cfg, info.param);
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_Cfg_" + cfg.toString();
+ std::string name = getPrefix(descriptor) + "_Cfg_" + cfg.toString();
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 05c2c5b..f2ef185 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -209,9 +209,7 @@
auto descriptor = std::get<0>(info.param).second;
std::string roomLevel = std::to_string(std::get<1>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_roomLevel" + roomLevel;
+ std::string name = getPrefix(descriptor) + "_roomLevel" + roomLevel;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 716a2c6..37e7c0a 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -209,9 +209,7 @@
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string bandLevel =
::android::internal::ToString(std::get<PARAM_BAND_LEVEL>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_preset_" +
+ std::string name = getPrefix(descriptor) + "_preset_" +
std::to_string(std::get<PARAM_PRESET>(info.param)) + "_bandLevel_" +
bandLevel;
std::replace_if(
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index 7c79d1b..54caed9 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -195,12 +195,10 @@
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
std::string maxAmplitude =
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_hapticScaleId" +
- hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
- "_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
- "_maxAmplitude" + maxAmplitude;
+ std::string name = getPrefix(descriptor) + "_hapticScaleId" + hapticScaleID +
+ "_hapticScaleVibScale" + hapticScaleVibScale + "_resonantFrequency" +
+ resonantFrequency + "_qFactor" + qFactor + "_maxAmplitude" +
+ maxAmplitude;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 96b048e..cbb80a9 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -131,9 +131,7 @@
[](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_gainMb_" + gainMb;
+ std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index 5525c80..bbb11fc 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -155,10 +155,7 @@
std::get<PARAM_LEVEL>(info.param));
std::string type = aidl::android::hardware::audio::effect::toString(
std::get<PARAM_TYPE>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_level_" + level + "_type_" +
- type;
+ std::string name = getPrefix(descriptor) + "_level_" + level + "_type_" + type;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 8fb4ebf..3056c6c 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -137,9 +137,7 @@
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string preset =
std::to_string(static_cast<int>(std::get<PARAM_PRESETS>(info.param)));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_preset" + preset;
+ std::string name = getPrefix(descriptor) + "_preset" + preset;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index 6b1da63..07a9fa4 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -141,9 +141,7 @@
[](const testing::TestParamInfo<VirtualizerParamTest::ParamType>& info) {
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_strength" + strength;
+ std::string name = getPrefix(descriptor) + "_strength" + strength;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index f41ba30..903ba69 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -195,9 +195,7 @@
std::get<PARAM_MEASUREMENT_MODE>(info.param));
std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_captureSize" + captureSize +
+ std::string name = getPrefix(descriptor) + "_captureSize" + captureSize +
"_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
"_latency" + latency;
std::replace_if(
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 90b7f37..0b5b9fc 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -149,10 +149,7 @@
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string level = std::to_string(std::get<PARAM_LEVEL>(info.param));
std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
- std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
- descriptor.common.name + "_UUID_" +
- descriptor.common.id.uuid.toString() + "_level" + level + "_mute" +
- mute;
+ std::string name = getPrefix(descriptor) + "_level" + level + "_mute" + mute;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/common/all-versions/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
index 757f8a8..c6a3963 100644
--- a/audio/common/all-versions/test/utility/Android.bp
+++ b/audio/common/all-versions/test/utility/Android.bp
@@ -62,6 +62,5 @@
"libxml2",
"liblog",
],
- static_libs: ["libgtest"],
test_suites: ["general-tests"],
}
diff --git a/audio/policy/1.0/xml/pfw_schemas/Android.bp b/audio/policy/1.0/xml/pfw_schemas/Android.bp
index 5d669c2..225c065 100644
--- a/audio/policy/1.0/xml/pfw_schemas/Android.bp
+++ b/audio/policy/1.0/xml/pfw_schemas/Android.bp
@@ -11,6 +11,7 @@
name: "audio_policy_engine_configurable_configuration_V1_0",
srcs: ["AllSchemas.xsd"],
package_name: "audio.policy.configurable.V1_0",
+ root_elements: ["ParameterFrameworkConfiguration"],
}
// Unfortunately, all rules only have a single output, thus
diff --git a/audio/policy/1.0/xml/pfw_schemas/api/current.txt b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
index c2fb6fc..2b83e60 100644
--- a/audio/policy/1.0/xml/pfw_schemas/api/current.txt
+++ b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
@@ -470,23 +470,7 @@
public class XmlParser {
ctor public XmlParser();
- method public static audio.policy.configurable.V1_0.BitParameterBlock readBitParameterBlock(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.BooleanParameter readBooleanParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ConfigurableDomainType readConfigurableDomainType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ConfigurableDomains readConfigurableDomains(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.EnumParameterType readEnumParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.FixedPointParameterType readFixedPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.FloatingPointParameterType readFloatingPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.IntegerParameterType readIntegerParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.LinearAdaptationType readLinearAdaptationType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.LogarithmicAdaptation readLogarithmicAdaptation(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static audio.policy.configurable.V1_0.ParameterFrameworkConfiguration readParameterFrameworkConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.StringParameter readStringParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SubsystemPlugins readSubsystemPlugins(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SubsystemType readSubsystemType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SystemClass readSystemClass(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
index 141efc1..62046f3 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
@@ -18,6 +18,7 @@
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
+#include <condition_variable>
#include <chrono>
#include <memory>
@@ -28,6 +29,8 @@
namespace automotive {
namespace vehicle {
+using ::android::base::ScopedLockAssertion;
+
class RecurrentTimerTest : public testing::Test {
public:
std::shared_ptr<RecurrentTimer::Callback> getCallback(size_t token) {
@@ -35,6 +38,15 @@
std::scoped_lock<std::mutex> lockGuard(mLock);
mCallbacks.push_back(token);
+ mCond.notify_all();
+ });
+ }
+
+ bool waitForCalledCallbacks(size_t count, size_t timeoutInMs) {
+ std::unique_lock<std::mutex> uniqueLock(mLock);
+ return mCond.wait_for(uniqueLock, std::chrono::milliseconds(timeoutInMs), [this, count] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mCallbacks.size() >= count;
});
}
@@ -54,6 +66,7 @@
}
private:
+ std::condition_variable mCond;
std::mutex mLock;
std::vector<size_t> mCallbacks GUARDED_BY(mLock);
};
@@ -66,12 +79,11 @@
auto action = getCallback(0);
timer.registerTimerCallback(interval, action);
- std::this_thread::sleep_for(std::chrono::seconds(1));
+ // Should only takes 1s, use 5s as timeout to be safe.
+ ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+ << "Not enough callbacks called before timeout";
timer.unregisterTimerCallback(action);
-
- // Theoretically trigger 10 times, but check for at least 9 times to be stable.
- ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
}
TEST_F(RecurrentTimerTest, testRegisterUnregisterRegister) {
@@ -92,10 +104,11 @@
timer.registerTimerCallback(interval, action);
- std::this_thread::sleep_for(std::chrono::seconds(1));
+ // Should only takes 1s, use 5s as timeout to be safe.
+ ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+ << "Not enough callbacks called before timeout";
- // Theoretically trigger 10 times, but check for at least 9 times to be stable.
- ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+ timer.unregisterTimerCallback(action);
}
TEST_F(RecurrentTimerTest, testDestroyTimerWithCallback) {
@@ -114,7 +127,9 @@
std::this_thread::sleep_for(std::chrono::milliseconds(200));
- ASSERT_TRUE(getCalledCallbacks().empty());
+ // Should be 0, but in rare cases there might be 1 events in the queue while the timer is
+ // being destroyed.
+ ASSERT_LE(getCalledCallbacks().size(), 1u);
}
TEST_F(RecurrentTimerTest, testRegisterMultipleCallbacks) {
@@ -132,7 +147,11 @@
auto action3 = getCallback(3);
timer.registerTimerCallback(interval3, action3);
- std::this_thread::sleep_for(std::chrono::seconds(1));
+ // In 1s, we should generate 10 + 20 + 33 = 63 events.
+ // Here we are waiting for more events to make sure we receive enough events for each actions.
+ // Use 5s as timeout to be safe.
+ ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 70u, /* timeoutInMs= */ 5000))
+ << "Not enough callbacks called before timeout";
timer.unregisterTimerCallback(action1);
timer.unregisterTimerCallback(action2);
@@ -152,20 +171,18 @@
action3Count++;
}
}
- // Theoretically trigger 10 times, but check for at least 9 times to be stable.
- ASSERT_GE(action1Count, static_cast<size_t>(9));
- // Theoretically trigger 20 times, but check for at least 15 times to be stable.
- ASSERT_GE(action2Count, static_cast<size_t>(15));
- // Theoretically trigger 33 times, but check for at least 25 times to be stable.
- ASSERT_GE(action3Count, static_cast<size_t>(25));
+
+ ASSERT_GE(action1Count, static_cast<size_t>(10));
+ ASSERT_GE(action2Count, static_cast<size_t>(20));
+ ASSERT_GE(action3Count, static_cast<size_t>(33));
}
TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) {
RecurrentTimer timer;
- // 0.02s
- int64_t interval1 = 20000000;
- // 0.01s
- int64_t interval2 = 10000000;
+ // 0.2s
+ int64_t interval1 = 200'000'000;
+ // 0.1s
+ int64_t interval2 = 100'000'000;
auto action = getCallback(0);
for (int i = 0; i < 10; i++) {
@@ -175,10 +192,9 @@
clearCalledCallbacks();
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
-
- // Theoretically trigger 10 times, but check for at least 9 times to be stable.
- ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+ // Should only takes 1s, use 5s as timeout to be safe.
+ ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+ << "Not enough callbacks called before timeout";
timer.unregisterTimerCallback(action);
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 876a91f..82ad917 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -7,11 +7,21 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
+filegroup {
+ name: "face-default.rc",
+ srcs: ["face-default.rc"],
+}
+
+filegroup {
+ name: "face-default.xml",
+ srcs: ["face-default.xml"],
+}
+
cc_binary {
name: "android.hardware.biometrics.face-service.example",
relative_install_path: "hw",
- init_rc: ["face-default.rc"],
- vintf_fragments: ["face-default.xml"],
+ init_rc: [":face-default.rc"],
+ vintf_fragments: [":face-default.xml"],
vendor: true,
shared_libs: [
"libbase",
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..2f39a08
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+ name: "com.android.hardware.biometrics.face.key",
+ public_key: "com.android.hardware.biometrics.face.avbpubkey",
+ private_key: "com.android.hardware.biometrics.face.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.biometrics.face.certificate",
+ certificate: "com.android.hardware.biometrics.face",
+}
+
+apex {
+ name: "com.android.hardware.biometrics.face",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.biometrics.face.key",
+ certificate: ":com.android.hardware.biometrics.face.certificate",
+ updatable: false,
+
+ vendor: true,
+ use_vndk_as_stable: true,
+
+ binaries: [
+ // hal
+ "android.hardware.biometrics.face-service.example",
+ ],
+ prebuilts: [
+ // init_rc
+ "face-default-apex.rc",
+ // vintf_fragment
+ "face-default-apex.xml",
+ // permission
+ "android.hardware.biometrics.face.prebuilt.xml",
+ ],
+
+ overrides: [
+ "android.hardware.biometrics.face-service.example",
+ ],
+}
+
+prebuilt_etc {
+ name: "face-default-apex.rc",
+ src: ":gen-face-default-apex.rc",
+ vendor: true,
+ installable: false,
+}
+
+genrule {
+ name: "gen-face-default-apex.rc",
+ srcs: [":face-default.rc"],
+ out: ["face-default-apex.rc"],
+ cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "face-default-apex.xml",
+ src: ":face-default.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ installable: false,
+}
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
new file mode 100644
index 0000000..9f358ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
new file mode 100644
index 0000000..ad8f57d
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCoZ28KVXxB9kkX
+zPhi8pVSmiMU0xchU4PkoOvFzmr9t5b7rA1zmzOLjkNWMrxt1XCUEfOgT3N50z5T
+484dpEZBrwIH31NqSOr/T8mG5frZAkNg0WqfgV+AG81mCuA+nG4a08fmDL4nEzVg
+irQvWpXzRCNIn+LEx+gG4I2KG8EGWDiFnzXwSFJG4n60rfLQNHgsejv/06BmPCnS
+gp06LhqJTO2oJKCJVQxfO0TPNUd9FSVSXdWuHcHE2gwoHM/7C/10Bdx8XXCMbAQR
+a4d3moH5oRuhh1841PtIQ0ozw/vHapCTmdMbjmgbwpXZ49DfvJl2cnz5c5G/CUO1
+9CkLDdxffsHh48jLUzH1nRgcWW2CAnSIs8nGjScyOKB+gn831ke8agJGbVHs1Cp/
+ONbMZeQIhEL0kderI1vVoufeBf38/I93rpz6PXp5NiTwOnVdEik595/W7oldr/rM
+taKvWwfnjml+Z1uzJWWDKPnS+onxBVcoBGFhiewIejPz3UjncMiHW5QAx/BzfGgh
+UmFO0vsh8qrEfAqT4AqL4uCuyVm0JmugdWKoeQISh5i4+HMmvPaudd+8yF0plr10
++pyNGkLZm4NBJxOD7V0AMjfTIpKRbmV8xnCAnWQ+xx/qWxHAZ0wfbZXXF0m6L6po
+dVwJJI7EnuQbAkbXnzMtCTQToZTSVwIDAQABAoICAAGjGJNY15kYKO3xzXWMyfXT
+gl7L9Im1TNVwP3Dpu+S7U0NSd1w12Iju35znzlwhx7/j8skOrKubaZvM9ztJ79Yb
+1CDs3PWhP6OVJeGvvHU9zkp59RexQ5Ma8hXskIroE2WJ97bQgRkfi/r9x8wKc39T
+aYv/SrTC0SPr+YRFSjMvfV35kvLC759slgwkmsH6ZWatSeyhPooJfX1kTRBi08A2
+i4lOBD+Bhtn2jG/+1eYtFyYXVaHx/E9XfU6QhSPgIhBULdujPucmj6pc4yRYnKxA
+32QxGc35u0QHEqJ9/iWAoporIMAmU/Qp7phl9g+OvxrFkloMc3cp3GSMh8k2bJUY
+nRvk0IPG1bF7jwezHbQGTwTlguJlWPl3+v+qeKJQI4pov3Cz6aNrBmBfEbjwcJrf
+RvPNCQ2X1GciZcGoJxcHRgFNKarzb+m92qNRftr6YDBZM8PlvJgGhnTRkOuFmIZB
+WPRergEwaClp1DbQsXwKlWpGfSMLznj57oKT3MJ31R4pusfMDBS39p9jUFH7uO+p
+e/Wdy+RaKei4AYBZIc+ks8LJzeIG+YWD9kN0lPVvzoza6nJYGGNVe/bxErjpESsR
+fZDs5EMNPGsCQ56Tgt+vtHEGF3x7ufGMF1XqisCMlaxH03aT2N3Wi5um8jO2pfFC
+4NEBq4ixvlyefb0TER+5AoIBAQC6nSDDzeeseLOJ8QSb1kHHkvQOGb8kdYY/KJ51
++uiwoEWOYAxKubqumo2rYaqcM0lbZKWb/9cgVK4LAzdqY4z3BINA7YRzXSUXdb8T
+rbqtg33Yj7f1KBiBqns2FMktfIZ+6JUDALb+CD7rHGpi62RDd8JaKL8wugqMBmwM
+YHBfzECVSjDosjGpbILbDJPTfiEQLyPEoJxJ48Z3Xg6l+0BSZrrH9FqGVgsvEQ7f
+zhZ6rpJIefb1cFjwIRFORS4tMqS1keu+dugyUBs83AOp5kaq6O31n5hDAOyZVFsw
+HSBu8pbWAceWJrF7R1Am23063hIztjPbU9yeN2mvhVQSgO4PAoIBAQDnBQHt3prI
+AajCYbHmk0v1WT2kDD5yEX/fZzifTU5k/+0Jvixpa0KOR2qaUXyx4ocIT6F1hR89
+VXGby2UG6SlvuwXMzwmoVf5sueQ6wshu3fCaS8BYNpJnOAfgLTnUpKIWITDm/2Hj
+4NCFYL77EfBXXhFH7lLPhiPcTWQlPDuFCXU/BJuVhJbpd+GtF1+loiNQArg9nmKb
+9Ac7ccR9UBO/XSQN1th4+yaxyGQKaiYsBqsy8SPp2ynTdGXT72LePqSUrkNsjgE7
+PkzgX0pBZw8upBXk+8ByfIaaQONRbCuMQEXj6B66szaWeR2hDfaoDOk3/w6JN93r
+yPKfk4TFNB85AoIBAGoiHVVfUOjViP7l9cIPvD+eQ3GVkRFSSfS3zE+7UQXLUWPl
+GniRYywUuIgFNvw5avowpsOvYRGBN68JuEWosq52gZO2wkK+ce8Cx5aQkwBGLZey
+PWSP1khAxmx+q+BT10ZsTvtzN6AI3ofnFFaIG/EHNqECVaKH3KHAsUjkvGSvjPeb
+R2/AkOAT1+RvJc/+Bx3mQYh99AVOJz0SYHBkEjQLOyWnwqhuXVP6dqQw2LYTfRz9
+SMhUijCgDfCfBeEs0WJ2yEX96Jdc2fDmDKtfTUe8zEGK8BUDfIzD3kzh8+VF0SWL
+w5CRFxXO/DXtVS7ayC1i7eFKs8nEKDZsNOGFNF8CggEAKXRMlFKNk7Y4gijls2pb
+Bvusg/NugSmCuKPdFTjaCGWkM0tczM3ic4V9K5PTvFfZwzQG1P++S1M5v6sPxd2x
+AcudjtLX+Mz1iq0QtzqcnMhWlFljenDQdJUpVKDI789bBn2OOOU6u5lr0YM6wfLG
+HedTUoUBdxuq860vez8DryuzTkuVX48bRWmtpVG8aAxgKctTJDt3lmSDp7cSeyoT
+YRNllNYoogzvNJew2+2QS/YmYk3DFAOvzbHlU9Jw+1BiWAutLZ2NuwPC58AxourL
+XqMzCpPiRKjzvlpGcCXo6pHd+Ld+TCI8eWPiXTQUPrOSZenuwdC0kcrNPrVJ7dkc
+gQKCAQEAmE6BTX7nn0HT859PtBlsy3rM8psihR4UYuYkTdE0+KF4hBRIP6uhMAVh
+vV6UMnt3QubKIekG14seGkwkBnEhv5reYWn/1+t3qP7qqvgndGgI2yPbzJx/cPMK
++KKhRbBAIgkjiY6hlo+DhrNS5nuBjZS2q/NnkO4NK7qBHvpIYAnRZK9qNsT4KZm6
+EO9YlCCnoZ3EB7brNgBZkxoekZG4jTlpD0E7nTxPTF1iVWedKRfmLFxAiDaSz0eo
+9tbTaRQ6ybU6jl1hMg4aINjp4xl/ScKk51veKg5ptjpPtspIh7keJRIUz3qwhuvk
+ZJpVwCxgxAOagrQtvwdedbmvChAfGA==
+-----END PRIVATE KEY-----
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8 b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
new file mode 100644
index 0000000..af0ff4e
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
new file mode 100644
index 0000000..3dc37ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF7TCCA9UCFCmJBOOYRVUgdy8vKm8OQd0ii2pPMA0GCSqGSIb3DQEBCwUAMIGx
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEtMCsGA1UEAwwkY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5mYWNlMCAXDTIzMDUyNTA2NDIw
+MFoYDzQ3NjEwNDIwMDY0MjAwWjCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJv
+aWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k
+cm9pZC5jb20xLTArBgNVBAMMJGNvbS5hbmRyb2lkLmhhcmR3YXJlLmJpb21ldHJp
+Y3MuZmFjZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPadnCNPEvKN
+HxACZt3C+tE2rga6gZ1pxfvlwGo1UY9yAxcQjL22SW93OA6R3de5uvQUbHh7b9g5
+AbNYcRnxOMiuUK2XSGWGDscxuGpQVCph4G1rXCOtbTmz1Zb42vQLCCQHHyxzI7ZE
+9Y6+rzw4p3jtEyBSiiErk13GFZTzwcDzqsQs12vDn9ovSTTn5Nyy6Csz7+O2t4SN
+qU4S/uLE6b/TiXj7196r58DcGvJgKbzbbnv/DUHGfaESrVWYLk3xoX3X8VJvP7jI
+M9XoZBbbgFLgAP5DFEvf5QWS9tR092z0YXOGr+mLHtkJM7Or9nKOohm6aFfHbuvu
+pSWyR4FWnaFANQ8wLH+fH485fiO6juJdTuRWeQpZddv0/IgguZ2Plu7z6NHCf5+L
+KYFjQ5y716wOufIqHhRLqYnpsAG2AFaMuPKzsy2KMifqoyB4KYR24EA1MCT7vwqu
+Hurp+SJrmNdkFVXbhGVUfMKf4nRZ37b9Miie0ju0OxJ9C3zY5uR5BMnqEjqq/rCX
+pQh5o1y+bWacOQVp0iQWJHfy8KkjhhQ1Pd1VeoVk9l2DsAJWm6unwMvGHviRcvzg
+BejDOVcE0x4xDj+TwAu2X2+w2hbUSY9W6lmkX4nGHlbLz211bIBFq42PzAMpRnYq
+jLxml4VpO4UnhyRp7Ipps99s7/iMFOn7AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
+AG/5t56hKYKORne0bwJpMSCWZNT6JcYjf6fEmNrvG3/gz9BCuj4osZjJHD2OSUJl
+F5yI52RgPrXK8bNqJOvX6MIc4Y2JoSI2Uz4J2vZ3QhRkPC9oqwk/Enz4GIVJ4Dnm
+/kgpBbN2SN0TjnmEooptly5tWb3IPTjqLZpaPIW1ntQeCAbgrYVHiMsvNe1BuBrn
+RNi1xqw3QGp2ZV/RfJ3MH6d49TswEL1gwiUeg3hw5eG7IDfLB/2IJBrff7kmPTQ6
+n+il4uXuXMmX70xSvJXwP/NinomJsORZ4Npbmp7xV/QJp9cNoxNAo3DJ4OHRAnA+
+L7E1KZ3+nSRxGcVlqBekmG6wH9U39NN+dh758aGdJOWqA+B+1PAGxkvFCNqLgTpm
+xNl62YiRRo4FiIAkntvs+JneMEphv/T5i824t2xFZD2lBuW8r54nWj5cpx8AU9W2
+rulR0jx7BnVdj6czn1/pPCIah8Os9pZM8q1CbF8vXD+QLAF0/NjPNomTEGd/M+V+
+sfn1OhLGF/E1kWyNeOmkvX26txQdY8k6jUdsAc5vmQqgwxdorjI38ynpYQnFwq2g
+eO4l62sx8icsSh2TRklWy8BwZpaCyO/WVv/FcjIUexYhmZ0EHpmQk/RAlD1f9wFy
+CciNa/Dm94AwJgZk9LcXye3BSvb1sKF6C7eYrW0eI95V
+-----END CERTIFICATE-----
diff --git a/biometrics/face/aidl/default/apex/file_contexts b/biometrics/face/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..4f935c1
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:hal_face_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/face/aidl/default/apex/manifest.json b/biometrics/face/aidl/default/apex/manifest.json
new file mode 100644
index 0000000..4d46896
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.biometrics.face",
+ "version": 1
+}
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 16302eb..3bb3f3a 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -11,8 +11,8 @@
name: "android.hardware.biometrics.fingerprint-service.example",
vendor: true,
relative_install_path: "hw",
- init_rc: ["fingerprint-example.rc"],
- vintf_fragments: ["fingerprint-example.xml"],
+ init_rc: [":fingerprint-example.rc"],
+ vintf_fragments: [":fingerprint-example.xml"],
local_include_dirs: ["include"],
srcs: [
"FakeLockoutTracker.cpp",
@@ -142,3 +142,13 @@
property_owner: "Vendor",
vendor: true,
}
+
+filegroup {
+ name: "fingerprint-example.rc",
+ srcs: ["fingerprint-example.rc"],
+}
+
+filegroup {
+ name: "fingerprint-example.xml",
+ srcs: ["fingerprint-example.xml"],
+}
diff --git a/biometrics/fingerprint/aidl/default/README.md b/biometrics/fingerprint/aidl/default/README.md
index 49b6c9d..823cd18 100644
--- a/biometrics/fingerprint/aidl/default/README.md
+++ b/biometrics/fingerprint/aidl/default/README.md
@@ -14,6 +14,12 @@
PRODUCT_PACKAGES_DEBUG += android.hardware.biometrics.fingerprint-service.example
```
+or add the following to include it as an apex:
+
+```
+PRODUCT_PACKAGES_DEBUG += com.android.hardware.biometrics.fingerprint.virtual
+```
+
The virtual HAL will be ignored if a real HAL is also installed on the target
device. Set the `biometric_virtual_enabled` settings and reboot the device to
switch to the virtual HAL. Unset it and reboot again to switch back.
diff --git a/biometrics/fingerprint/aidl/default/apex/Android.bp b/biometrics/fingerprint/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..ad36ae2
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/Android.bp
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+ name: "com.android.hardware.biometrics.fingerprint.virtual.key",
+ public_key: "com.android.hardware.biometrics.fingerprint.virtual.avbpubkey",
+ private_key: "com.android.hardware.biometrics.fingerprint.virtual.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.biometrics.fingerprint.virtual.certificate",
+ certificate: "com.android.hardware.biometrics.fingerprint.virtual",
+}
+
+apex {
+ name: "com.android.hardware.biometrics.fingerprint.virtual",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.biometrics.fingerprint.virtual.key",
+ certificate: ":com.android.hardware.biometrics.fingerprint.virtual.certificate",
+ updatable: false,
+ use_vndk_as_stable: true,
+ vendor: true,
+
+ binaries: [
+ "android.hardware.biometrics.fingerprint-service.example",
+ ],
+ prebuilts: [
+ // init_rc
+ "fingerprint-example-apex.rc",
+ // vintf_fragment
+ "fingerprint-example-apex.xml",
+ ],
+
+ overrides: [
+ "android.hardware.biometrics.fingerprint-service.example",
+ ],
+}
+
+genrule {
+ name: "gen-fingerprint-example-apex.rc",
+ srcs: [":fingerprint-example.rc"],
+ out: ["fingerprint-example-apex.rc"],
+ cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.fingerprint.virtual/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "fingerprint-example-apex.rc",
+ src: ":gen-fingerprint-example-apex.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "fingerprint-example-apex.xml",
+ src: ":fingerprint-example.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
new file mode 100644
index 0000000..9f2334a
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
new file mode 100644
index 0000000..14eb288
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDwo6CxzAwmX46C
+N1j8zr0qf6uy1rDkG5r1s4faDNX/ThYpd69DWbVGf22yFO3KY3B+TmqKU+B0SiqY
+MHQjXc+UcTa0BKtPtQNSYFLK13/1rW69QrlLtcGyAp/CwksXYuuJ8Uzs28nQ5A+z
+fh6Vfsla9tUWDeWtN4oehmOwZ0ZKPBAKKocB5W+YJoIkdVnzkiOnWawk8Wn7a1N0
+jN5wFDO/99De+rTzYgKvV3Xb68H2UrIei4TW4wEpMZuDRUfbPlrSkJpdf+hYKKLb
+AkotUrwA1znYR3U9t0GIHwZ5sp+OQTCkTfJMg2c+Bpmkp3TAL24LdvkYVA2LZERB
+p7xNeACH210Bb8QOAEaiLyVWuL6iapXI67TOkZ5yk7heb5zCxRcpOMA4FQ0hWYoX
+AWstem9ADWvZgKe0BFGx7lhp5YmdBCzdNv0za3Va9EATJ0wgy4qMpZu3yjDPE9bq
+gdb3BQL3kiDHdfR/LF9bCIP9QEHg+1mWOZDO1x8lXCuQrgp+gnh9bbfX5g6lA8IQ
+dTfozjLQC3mVbl0P7/PIf9rnHjcqUh3/1RJH51tkgqBO8xn7D6AIOv665hI+O319
+PU4j26vLSfEu624IjEDK/gcgacuoYl3H3LMI5a2JIWFLOtpKRo9P2qFF702o8B97
+5slGDYnxpAAnEQQADuRYgDalDlFDNQIDAQABAoICABe7k4wleydHslbeXYzlWNu5
+prXnHaAJpvFHiQT00iAxU9c4IhVq4gl3ZNq03LTitMQIONK2rgLaE7RZxwJ77I6P
+0dzUPw8H47F6pX+y3EBfH/ZTf9HbNaS4RIhhQCWo0GEU5sjPbmqHK5NAw4Rr8jDh
++icILNg2C42yJF/P96s3nD9cbV8/ARAI8DnnRv1SMuj825DzLEgrEBqFECUOoQH0
+T2nGYRVF28zuO8X6TPFdu4puqSXGUqV86oD6UrlpP2zX7Rl+lWwoadNeuPEaYUdV
+8rMFbScujSx/HtTezISroj/6HgT0yrhfz0RhbY7MvrYrwCppk8JlG6Q8BkK/rJGI
+lGw7nKIp43Tl8T2Rzw0I1dPwxCLMJuVErUclznN7lq25akG5XRwBAUQQE6nHO3GL
+jh7eFW7rEcpUBEKYTK1ZA8QrWGUW3WittDqZ6VQU/ZudVoTcgbW3YpUYq5z76O4u
+B6tqlmNtQfIi3LBh8CD19SIjV6KKVa0s++ArQEu/DWzmHWh/STZZk4b1DSdFYqm0
+zgylOVUfpcG10OxPOdvMEsA0VoXxxwl6Hx3DSEX6VxOQvBSkwhu+gw8u2keOsIYZ
+Ha2OxtG5FiEQqSa8YNN/0NDdOp1eEyqvdvT7o51cqHHPvlyhk7XL0AguErCtGggn
+TZ3rsUChlauG9GbJ4nOBAoIBAQD+ceJpOkMuw04dhIY5of3CcTTKGWdt2/9SP9PU
+ZORC6ywBhRORQBhyVZIERmxfJUGsmePHeIEQ5L8IniUDRTCKrL+J2bR8NdYZfvCJ
+9cYD2gjXmikFabKn6mkQz7JXjSr3Vamx2ueKuYqfo72aHVvhFv6Hi/ulbUPPZ15c
+gVo0iU5GRt/1XNyTksSiSKRyxXJYWqg5GD2JQ92Zbo5a5LhulC7wFF39jyfTe7K2
+mfrCI7dr+A0WtiTpbRH9EIU8CseIBgIEDTgMAxbBdUZpF8pecIAy0MLFefLA+8CK
+RN+8AI+HRHybjvuonOAfeEtQyyknzycxh20dyrd3FvBj40NBAoIBAQDyHCRuNwXA
+twETiysx1XStaoODLQkPxSqdFIBD+tfVR+E/3blVXkdrFfrTcr8NGdcgsJgQgYWr
+h9OENizcHg75gX6wdo3qYGQdZZxws/dQbNylObFYNkyFQrD1vkQzjZl5O4DaRJC7
+6YbJrrXZ44dgZoMo/M8nyNU5yaLvoOf4GV4bSiEfsx/MxWK7x6rCcpw9jpm+yQlB
+9NblSgWzfg0hmcRBn6haC3q45walBYGTVJfzTOMgn5bUmMxKqKlCXvp20BPLdclQ
+5Y14OqkqhnFeHpBSJ7iVI9BBy2nAsyk37NvYVg7mN8fGiWbCqurIrbPRGSCdohGr
+wY7zOVd1hmb1AoIBAGPhVJ0177VlmT5hDUeGXVR8l9pVipJHb7xbrc2MJUZXhpi6
+Imo8HNyU1pKzCkt3Foaoig99MDzvbkX1vlXATUPCeBWmzgCMKZUsjUO6pJZSenIX
+485qJWVg0Ql2Xm2bzqf0in50jbuZBd+QqRbcO3rqSdPvkULo11uNGi95320MERvp
+KnTolPWhAWsq1NLwyuf//lUbPNyrNUvLaDop2nQd2ycG97ZXAa00u3yOiS64UoIh
+hxHJQkgXNp5+Y66kFJtCsHvirIOams4qOQ979UaJJunLpQlby30R1gzw6FqmZbEV
+o0x1HjicDCaOVBJNDcTAvoPkw2KUdtxattafGYECggEBAPICm4/oREHdLKBCjszj
+mBv4yrkG/XXcGrql0YkiZzj0/v3+PtJMyYsLj4xpuPv5hodQvtBRCDLsNMyF8tWc
+3k8d2GvANh/AdpLEDVrDKkYka3Jldxa8QEU84vLiW/5EXtNGXYjQ3PRZfLiBgZnp
+zFraXeVMwC3+nNWE7vAloXrosJ8KvI2ZWgIwlH8sGU8BjZgiwSBqiGx7t4u/MG+5
+Yprhv8HxPDG2I9hMZuHx3RJOjw1PIAJuRDEDA8LlUTvdAPRfDkpk1PWeYIl76blu
+Zkg0uQLGXcYG5JfAI1fSPzN9+kwHyiDqRTH6CtQwUTyEFajAO1AWvx82/hO2j+wU
+izkCggEANyPfsBjEUIZjwBuaHajm/tkcQAo3F4EgIkb1XR/EnfaaJp4I9S6hJ0vv
+5/fQtASn+JHjuIRk5l7g9N7lU+W+SiPvSxm1zZv8zLkqJpbKpMh7VIxT9joZ3E3/
+rzRLL60zYJ42hdulSFLoO1qCMErifBiTIwIZu7p6qKRH4+vqappb9QTPPlyAFFT6
+3UJfs49HGqd6gTyN7TSNxaya+ZBaLgSXhmExY/OtZazQn/iJl/dYpyYvmJdzNpd+
+XELU0IUcKivJaueCqK8NfEqfHz28GHdAkwHd0CzGnciF4tn9K2Sg8+X9jISk/Usx
+qHAY4JU3ldxQzDUZCz5VCz372pgXkQ==
+-----END PRIVATE KEY-----
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8 b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
new file mode 100644
index 0000000..ab59820
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
new file mode 100644
index 0000000..6d10157
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/MCFFuIt0T1K9U92QfzZI3RpCyRp1ruMA0GCSqGSIb3DQEBCwUAMIHA
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTE8MDoGA1UEAwwzY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5maW5nZXJwcmludC52aXJ0dWFs
+MCAXDTIzMDUxMDA3MDkwMloYDzQ3NjEwNDA1MDcwOTAyWjCBwDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx
+EDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0B
+CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xPDA6BgNVBAMMM2NvbS5hbmRyb2lkLmhh
+cmR3YXJlLmJpb21ldHJpY3MuZmluZ2VycHJpbnQudmlydHVhbDCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAMKXBcAw2Cs68KUMt5Hw2LVwkgEDiwqaXkG9
+V0SBK9y/q+6JCoxs9+4NsDPAEzHB+UHpqJ2i07VW1YV9F+2V93KCy/0fUjXIWmu8
+P0ixb+t8wlHZM2zYXQe9PELUZ/ZlYjAxkVKJjDmsCM8yzpRk+g3KKswlYwzyBoat
+qukrtvAaNKlRGJmjeStEo2o4qgQQUq96NAvSt3d6PsrNdFbXxqX61JT1dT8Kgxhk
++oSAkV2/C2knQp/8ME1oJrK/D+glynXVqVkvYYplxp+GCIZUs/DOJcHyb+ZrNLJP
+f2zr4yDoB2pnV3G9VcjbdznWc661Wg+B2yZEvLVbOMiqaMRlpHzNczghowCy3xoq
+42IUmp3HLak0DUmrrUZDnJAAT/KEZxh/PwLeAcmUrQCbUiG5lN/njuZ5LjJ8gdcg
+v0RDPSIIszamrf2l+xlaI34iXS7xHf3OLTbgst2L7LhW5qmLsB1SZzAYGIUYnRWZ
+aqzaFIAWt28S0yhpOt+qS7b1l+fvMb09jiKfxzkYQh2bB0HrpbTl2x390q2GW6yE
+jmraC+nTiAVDCUnDjOVji7nXDloSmK+MDD/DaDQ47PoYE3hBqc0fsRr2aIlvMOvb
+m+4VhO85gCuJAK02XuixLPo6ZqBAEFNwQ4NDcuOHuODaaJ/amTxQBXRpNXUSnhXy
+ejpwspHrAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAGl3KGKMAWpefnRSQWs0n8kD
+eKYbzbe6mG0O5lqx5FKpJZpIki4RH1Yh5ZDR/NIeF2RNhlb/dqo99TKbCEGAoMB9
+R7EXDhyMcEXr5ATCA6iurhMKgkcLfOz6HkTI6k3wlPNuvx4iZGHD2KEvZiZGmae1
+dnK9iVtNs6ccyC0+V3y3Yt1fvjzp9SWcPpBXiO5QNf0sHxtzc32xXsBH0aLwLjDZ
+BCytwfEvq2S25v0r9m0fKquDBoFnk68cqClpNQZ9Ky0k8fGgOiQ5/jnVmgPmTheG
+mBcdPeUrhxGNs1vax/i/ysT4AVmDzIVW0uXVouhVeMQzykuy1+Ywa/Rn0jLxeNF2
+X3ooOE+EF8u9Pxf8ILRnfqok3VRuYLH6neNknTSKTx1aQAh9XbBpTUa/eCq3LDCP
+L6hSXYWjk9e5txbn0cNw9WuKMUg+Z9Qms3aVRFcvBxZQySEvf8FhgSrQbqbCbzhf
+dI0/ouW5w9iHUOh/FDvfETeZCeeTS+EOvGOqknzO8Y7PiChlgFsoMvC1GpHZ1ADy
+3xKSh15G92JCiv89CK2VvM8QDFh8ErQmSLjhMl700CLYis+AAZhCKOhAo573zj2u
+dZf29S+o3SEBhsl5snVGJW13Bu7BjxQtscCwKOv0g1cCkrqgcm2bMuNhpTK7rhMP
+i4hGSvbdGC27BtXbsiVX
+-----END CERTIFICATE-----
diff --git a/biometrics/fingerprint/aidl/default/apex/file_contexts b/biometrics/fingerprint/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..1c189fc
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.biometrics\.fingerprint-service\.example u:object_r:hal_fingerprint_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/fingerprint/aidl/default/apex/manifest.json b/biometrics/fingerprint/aidl/default/apex/manifest.json
new file mode 100644
index 0000000..bbd2c69
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.biometrics.fingerprint.virtual",
+ "version": 1
+}
diff --git a/bluetooth/1.0/default/bluetooth_address.cc b/bluetooth/1.0/default/bluetooth_address.cc
index 93a5469..df3e84a 100644
--- a/bluetooth/1.0/default/bluetooth_address.cc
+++ b/bluetooth/1.0/default/bluetooth_address.cc
@@ -67,7 +67,7 @@
const uint8_t zero_bdaddr[kBytes] = {0, 0, 0, 0, 0, 0};
if ((string_to_bytes(address, local_addr)) &&
(memcmp(local_addr, zero_bdaddr, kBytes) != 0)) {
- ALOGD("%s: Got Factory BDA %s", __func__, address);
+ ALOGD("%s: Got Factory BDA", __func__);
return true;
} else {
ALOGE("%s: Got Invalid BDA '%s' from %s", __func__, address, property);
@@ -78,12 +78,14 @@
// No BDADDR found in the file. Look for BDA in a factory property.
if (property_get(FACTORY_BDADDR_PROPERTY, property, NULL) &&
string_to_bytes(property, local_addr)) {
+ ALOGD("%s: Using FACTORY_BDADDR_PROPERTY", __func__);
return true;
}
// No factory BDADDR found. Look for a previously stored BDA.
if (property_get(PERSIST_BDADDR_PROPERTY, property, NULL) &&
string_to_bytes(property, local_addr)) {
+ ALOGD("%s: Using PERSIST_BDADDR_PROPERTY", __func__);
return true;
}
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index 869c723..a2211f4 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -33,8 +33,7 @@
class BluetoothDeathRecipient : public hidl_death_recipient {
public:
- BluetoothDeathRecipient(const sp<IBluetoothHci> hci)
- : mHci(hci), has_died_(false) {}
+ BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
virtual void serviceDied(
uint64_t /*cookie*/,
@@ -52,7 +51,7 @@
};
BluetoothHci::BluetoothHci()
- : death_recipient_(new BluetoothDeathRecipient(this)) {bt_enabled = 0;}
+ : death_recipient_(new BluetoothDeathRecipient(this)) {}
Return<void> BluetoothHci::initialize(
const ::android::sp<IBluetoothHciCallbacks>& cb) {
@@ -62,19 +61,8 @@
return Void();
}
- if (bt_enabled == 1) {
- ALOGE("initialize was called!");
- return Void();
- }
- bt_enabled = 1;
death_recipient_->setHasDied(false);
cb->linkToDeath(death_recipient_, 0);
- unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
- if (death_recipient->getHasDied())
- ALOGI("Skipping unlink call, service died.");
- else
- cb->unlinkToDeath(death_recipient);
- };
bool rc = VendorInterface::Initialize(
[cb](bool status) {
@@ -124,12 +112,6 @@
Return<void> BluetoothHci::close() {
ALOGI("BluetoothHci::close()");
-
- if (bt_enabled != 1) {
- ALOGE("should initialize first!");
- return Void();
- }
- bt_enabled = 0;
unlink_cb_(death_recipient_);
VendorInterface::Shutdown();
return Void();
@@ -152,11 +134,6 @@
void BluetoothHci::sendDataToController(const uint8_t type,
const hidl_vec<uint8_t>& data) {
- if (bt_enabled != 1) {
- ALOGE("should initialize first!");
- return;
- }
-
VendorInterface::get()->Send(type, data.data(), data.size());
}
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index 5130c87..c966990 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -48,7 +48,6 @@
void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
::android::sp<BluetoothDeathRecipient> death_recipient_;
std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
- int bt_enabled;
};
extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index c23d667..1d15dd6 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -36,8 +36,6 @@
"BLUETOOTH_VENDOR_LIB_INTERFACE";
static const int INVALID_FD = -1;
-std::mutex vendor_mutex_;
-std::mutex initcb_mutex_;
namespace {
@@ -49,25 +47,13 @@
uint16_t opcode;
} internal_command;
-enum {
- VENDOR_STATE_INIT = 1,
- VENDOR_STATE_OPENING, /* during opening */
- VENDOR_STATE_OPENED, /* open in fops_open */
- VENDOR_STATE_CLOSING, /* during closing */
- VENDOR_STATE_CLOSED, /* closed */
-
- VENDOR_STATE_MSG_NUM
-} ;
-
-uint8_t vstate = VENDOR_STATE_INIT;
-
// True when LPM is not enabled yet or wake is not asserted.
bool lpm_wake_deasserted;
uint32_t lpm_timeout_ms;
bool recent_activity_flag;
VendorInterface* g_vendor_interface = nullptr;
-static VendorInterface vendor_interface;
+std::mutex wakeup_mutex_;
HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
size_t packet_size = data.size() + sizeof(HC_BT_HDR);
@@ -181,8 +167,11 @@
InitializeCompleteCallback initialize_complete_cb,
PacketReadCallback event_cb, PacketReadCallback acl_cb,
PacketReadCallback sco_cb, PacketReadCallback iso_cb) {
- ALOGI("%s: VendorInterface::Initialize", __func__);
- g_vendor_interface = &vendor_interface;
+ if (g_vendor_interface) {
+ ALOGE("%s: No previous Shutdown()?", __func__);
+ return false;
+ }
+ g_vendor_interface = new VendorInterface();
return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
sco_cb, iso_cb);
}
@@ -190,8 +179,9 @@
void VendorInterface::Shutdown() {
LOG_ALWAYS_FATAL_IF(!g_vendor_interface, "%s: No Vendor interface!",
__func__);
- ALOGI("%s: VendorInterface::Shutdown", __func__);
g_vendor_interface->Close();
+ delete g_vendor_interface;
+ g_vendor_interface = nullptr;
}
VendorInterface* VendorInterface::get() { return g_vendor_interface; }
@@ -201,189 +191,144 @@
PacketReadCallback acl_cb,
PacketReadCallback sco_cb,
PacketReadCallback iso_cb) {
- {
- std::unique_lock<std::mutex> guard(vendor_mutex_);
- if (vstate == VENDOR_STATE_OPENED) {
- ALOGW("VendorInterface opened!");
- return true;
- }
+ initialize_complete_cb_ = initialize_complete_cb;
- if ((vstate == VENDOR_STATE_CLOSING) ||
- (vstate == VENDOR_STATE_OPENING)) {
- ALOGW("VendorInterface open/close is on-going !");
- return true;
- }
+ // Initialize vendor interface
- vstate = VENDOR_STATE_OPENING;
- ALOGI("%s: VendorInterface::Open", __func__);
+ lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
+ if (!lib_handle_) {
+ ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
+ dlerror());
+ return false;
+ }
- initialize_complete_cb_ = initialize_complete_cb;
- // Initialize vendor interface
-
- lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
- if (!lib_handle_) {
- ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
- dlerror());
- return false;
- }
-
- lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
- dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
- if (!lib_interface_) {
- ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
- VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
- return false;
- }
+ lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
+ dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
+ if (!lib_interface_) {
+ ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
+ VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
+ return false;
+ }
// Get the local BD address
- uint8_t local_bda[BluetoothAddress::kBytes] = {0, 0, 0, 0, 0, 0};
- if (!BluetoothAddress::get_local_address(local_bda)) {
- // BT driver will get BD address from NVRAM for MTK solution
- ALOGW("%s: No pre-set Bluetooth Address!", __func__);
- }
- int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
- if (status) {
- ALOGE("%s unable to initialize vendor library: %d", __func__, status);
- return false;
- }
+ uint8_t local_bda[BluetoothAddress::kBytes];
+ if (!BluetoothAddress::get_local_address(local_bda)) {
+ LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__);
+ }
+ int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
+ if (status) {
+ ALOGE("%s unable to initialize vendor library: %d", __func__, status);
+ return false;
+ }
- ALOGD("%s vendor library loaded", __func__);
+ ALOGD("%s vendor library loaded", __func__);
// Power on the controller
- int power_state = BT_VND_PWR_ON;
- lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+ int power_state = BT_VND_PWR_ON;
+ lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
// Get the UART socket(s)
- int fd_list[CH_MAX] = {0};
- int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
+ int fd_list[CH_MAX] = {0};
+ int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
- if (fd_count < 1 || fd_count > CH_MAX - 1) {
- ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
+ if (fd_count < 1 || fd_count > CH_MAX - 1) {
+ ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
+ return false;
+ }
+
+ for (int i = 0; i < fd_count; i++) {
+ if (fd_list[i] == INVALID_FD) {
+ ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
return false;
}
+ }
- for (int i = 0; i < fd_count; i++) {
- if (fd_list[i] == INVALID_FD) {
- ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
- return false;
- }
- }
+ event_cb_ = event_cb;
+ PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
+ HandleIncomingEvent(event);
+ };
- event_cb_ = event_cb;
- PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
- HandleIncomingEvent(event);
- };
-
- if (fd_count == 1) {
- hci::H4Protocol* h4_hci =
- new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
- hci_ = h4_hci;
- } else {
- hci::MctProtocol* mct_hci =
- new hci::MctProtocol(fd_list, intercept_events, acl_cb);
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[CH_ACL_IN],
- [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
- hci_ = mct_hci;
- }
+ if (fd_count == 1) {
+ hci::H4Protocol* h4_hci =
+ new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
+ hci_ = h4_hci;
+ } else {
+ hci::MctProtocol* mct_hci =
+ new hci::MctProtocol(fd_list, intercept_events, acl_cb);
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[CH_ACL_IN], [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
+ hci_ = mct_hci;
+ }
// Initially, the power management is off.
- lpm_wake_deasserted = true;
+ lpm_wake_deasserted = true;
// Start configuring the firmware
- firmware_startup_timer_ = new FirmwareStartupTimer();
- lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
+ firmware_startup_timer_ = new FirmwareStartupTimer();
+ lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
- vstate = VENDOR_STATE_OPENED;
- ALOGI("%s: VendorInterface::Open done!!!", __func__);
- } // vendor_mutex_ done
return true;
}
void VendorInterface::Close() {
// These callbacks may send HCI events (vendor-dependent), so make sure to
// StopWatching the file descriptor after this.
-
- if (vstate != VENDOR_STATE_OPENED) {
- ALOGW("VendorInterface is not allow close(%d)", vstate);
- return;
- }
- vstate = VENDOR_STATE_CLOSING;
- ALOGI("%s: VendorInterface::Close", __func__);
-
if (lib_interface_ != nullptr) {
- lib_interface_->cleanup();
bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
}
- {
- std::unique_lock<std::mutex> guard(vendor_mutex_);
+ fd_watcher_.StopWatchingFileDescriptors();
- fd_watcher_.StopWatchingFileDescriptors();
- if (hci_ != nullptr) {
- delete hci_;
- hci_ = nullptr;
- }
+ if (hci_ != nullptr) {
+ delete hci_;
+ hci_ = nullptr;
+ }
- if (lib_interface_ != nullptr) {
- lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
+ if (lib_interface_ != nullptr) {
+ lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
- int power_state = BT_VND_PWR_OFF;
- lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+ int power_state = BT_VND_PWR_OFF;
+ lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
- lib_interface_ = nullptr;
- }
+ lib_interface_->cleanup();
+ lib_interface_ = nullptr;
+ }
- if (lib_handle_ != nullptr) {
- dlclose(lib_handle_);
- lib_handle_ = nullptr;
- }
+ if (lib_handle_ != nullptr) {
+ dlclose(lib_handle_);
+ lib_handle_ = nullptr;
+ }
- if (firmware_startup_timer_ != nullptr) {
- delete firmware_startup_timer_;
- firmware_startup_timer_ = nullptr;
- }
- vstate = VENDOR_STATE_CLOSED;
- } // vendor_mutex_ done
- ALOGI("%s: VendorInterface::Close done!!!", __func__);
+ if (firmware_startup_timer_ != nullptr) {
+ delete firmware_startup_timer_;
+ firmware_startup_timer_ = nullptr;
+ }
}
size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
- {
- std::unique_lock<std::mutex> guard(vendor_mutex_);
+ std::unique_lock<std::mutex> lock(wakeup_mutex_);
+ recent_activity_flag = true;
- if (vstate != VENDOR_STATE_OPENED) {
- ALOGW("VendorInterface is not open yet(%d)!", vstate);
- return 0;
- }
- ALOGI("%s: VendorInterface::Send", __func__);
-
- if (lib_interface_ == nullptr) {
- ALOGE("lib_interface_ is null");
- return 0;
- }
- recent_activity_flag = true;
- if (lpm_wake_deasserted == true) {
- // Restart the timer.
- fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+ if (lpm_wake_deasserted == true) {
+ // Restart the timer.
+ fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
[this]() { OnTimeout(); });
- // Assert wake.
- lpm_wake_deasserted = false;
- bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
- lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
- ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
- }
+ // Assert wake.
+ lpm_wake_deasserted = false;
+ bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
+ lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
+ ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
+ }
- return hci_ ? hci_->Send(type, data, length) : 0;
- } // vendor_mutex_ done
+ return hci_->Send(type, data, length);
}
void VendorInterface::OnFirmwareConfigured(uint8_t result) {
@@ -394,36 +339,25 @@
firmware_startup_timer_ = nullptr;
}
- {
- std::unique_lock<std::mutex> guard(initcb_mutex_);
- ALOGD("%s OnFirmwareConfigured get lock", __func__);
- if (initialize_complete_cb_ != nullptr) {
- LOG_ALWAYS_FATAL_IF((result != 0),
- "%s: Failed to init firmware!", __func__);
- initialize_complete_cb_(result == 0);
- }
- } // initcb_mutex_ done
-
- if (lib_interface_ != nullptr) {
- lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
- ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
-
- bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
- lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
-
- ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
- fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
- [this]() { OnTimeout(); });
- }
- else {
- ALOGE("lib_interface_ is null");
+ if (initialize_complete_cb_ != nullptr) {
+ initialize_complete_cb_(result == 0);
+ initialize_complete_cb_ = nullptr;
}
- initialize_complete_cb_ = nullptr;
+ lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
+ ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
+
+ bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
+ lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
+
+ ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
+ fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+ [this]() { OnTimeout(); });
}
void VendorInterface::OnTimeout() {
ALOGV("%s", __func__);
+ std::unique_lock<std::mutex> lock(wakeup_mutex_);
if (recent_activity_flag == false) {
lpm_wake_deasserted = true;
bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index 2df3946..040f31a 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -22,8 +22,6 @@
#include "bt_vendor_lib.h"
#include "hci_protocol.h"
-extern std::mutex initcb_mutex_;
-
namespace android {
namespace hardware {
namespace bluetooth {
@@ -47,9 +45,10 @@
size_t Send(uint8_t type, const uint8_t* data, size_t length);
void OnFirmwareConfigured(uint8_t result);
- virtual ~VendorInterface() = default;
private:
+ virtual ~VendorInterface() = default;
+
bool Open(InitializeCompleteCallback initialize_complete_cb,
PacketReadCallback event_cb, PacketReadCallback acl_cb,
PacketReadCallback sco_cb, PacketReadCallback iso_cb);
diff --git a/bluetooth/aidl/TEST_MAPPING b/bluetooth/aidl/TEST_MAPPING
index 41a508e..18958d2 100644
--- a/bluetooth/aidl/TEST_MAPPING
+++ b/bluetooth/aidl/TEST_MAPPING
@@ -1,24 +1,12 @@
{
"presubmit" : [
{
- "name" : "VtsHalBluetoothTargetTest",
- "options": [
- {
- // TODO(b/275847929)
- "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
- }
- ]
+ "name" : "VtsHalBluetoothTargetTest"
}
],
"hwasan-presubmit" : [
{
- "name" : "VtsHalBluetoothTargetTest",
- "options": [
- {
- // TODO(b/275847929)
- "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
- }
- ]
+ "name" : "VtsHalBluetoothTargetTest"
}
]
}
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index ac2eabc..782122f 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -174,7 +174,10 @@
mFdWatcher.WatchFdForNonBlockingReads(mFd,
[this](int) { mH4->OnDataReady(); });
- send(PacketType::COMMAND, reset);
+ ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
+ if (!result.isOk()) {
+ ALOGE("Error sending reset command");
+ }
auto status = resetFuture.wait_for(std::chrono::seconds(1));
mFdWatcher.StopWatchingFileDescriptors();
if (status == std::future_status::ready) {
@@ -221,6 +224,7 @@
ALOGI("Unable to open Linux interface, trying default path.");
mFd = getFdFromDevPath();
if (mFd < 0) {
+ mState = HalState::READY;
cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
return ndk::ScopedAStatus::ok();
}
@@ -278,6 +282,7 @@
{
std::lock_guard<std::mutex> guard(mStateMutex);
if (mState != HalState::ONE_CLIENT) {
+ ASSERT(mState != HalState::INITIALIZING);
ALOGI("Already closed");
return ndk::ScopedAStatus::ok();
}
@@ -301,30 +306,35 @@
ndk::ScopedAStatus BluetoothHci::sendHciCommand(
const std::vector<uint8_t>& packet) {
- send(PacketType::COMMAND, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::COMMAND, packet);
}
ndk::ScopedAStatus BluetoothHci::sendAclData(
const std::vector<uint8_t>& packet) {
- send(PacketType::ACL_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::ACL_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendScoData(
const std::vector<uint8_t>& packet) {
- send(PacketType::SCO_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::SCO_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendIsoData(
const std::vector<uint8_t>& packet) {
- send(PacketType::ISO_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::ISO_DATA, packet);
}
-void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
+ndk::ScopedAStatus BluetoothHci::send(PacketType type,
+ const std::vector<uint8_t>& v) {
+ if (mH4 == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (v.empty()) {
+ ALOGE("Packet is empty, no data was found to be sent");
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
mH4->Send(type, v);
+ return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
index 85aafc8..477cc5c 100644
--- a/bluetooth/aidl/default/BluetoothHci.h
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -66,8 +66,9 @@
::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
int getFdFromDevPath();
- void send(::android::hardware::bluetooth::hci::PacketType type,
- const std::vector<uint8_t>& packet);
+ [[nodiscard]] ndk::ScopedAStatus send(
+ ::android::hardware::bluetooth::hci::PacketType type,
+ const std::vector<uint8_t>& packet);
std::unique_ptr<NetBluetoothMgmt> management_{};
// Send a reset command and discard all packets until a reset is received.
diff --git a/bluetooth/audio/OWNERS b/bluetooth/audio/OWNERS
index a8e9bda..f3657ca 100644
--- a/bluetooth/audio/OWNERS
+++ b/bluetooth/audio/OWNERS
@@ -1,4 +1,6 @@
+# Bug component: 27441
+
include platform/packages/modules/Bluetooth:/OWNERS
-cheneyni@google.com
aliceypkuo@google.com
+quocbaodo@google.com
diff --git a/bluetooth/audio/aidl/TEST_MAPPING b/bluetooth/audio/aidl/TEST_MAPPING
new file mode 100644
index 0000000..0c853f8
--- /dev/null
+++ b/bluetooth/audio/aidl/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalBluetoothAudioTargetTest"
+ }
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "VtsHalBluetoothAudioTargetTest"
+ }
+ ]
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index 2a88959..9c72e19 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -27,9 +27,31 @@
namespace bluetooth {
namespace audio {
+struct BluetoothAudioProviderContext {
+ SessionType session_type;
+};
+
+static void binderUnlinkedCallbackAidl(void* cookie) {
+ LOG(INFO) << __func__;
+ BluetoothAudioProviderContext* ctx =
+ static_cast<BluetoothAudioProviderContext*>(cookie);
+ delete ctx;
+}
+
+static void binderDiedCallbackAidl(void* cookie) {
+ LOG(INFO) << __func__;
+ BluetoothAudioProviderContext* ctx =
+ static_cast<BluetoothAudioProviderContext*>(cookie);
+ CHECK_NE(ctx, nullptr);
+
+ BluetoothAudioSessionReport::OnSessionEnded(ctx->session_type);
+}
+
BluetoothAudioProvider::BluetoothAudioProvider() {
death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
+ AIBinder_DeathRecipient_setOnUnlinked(death_recipient_.get(),
+ binderUnlinkedCallbackAidl);
}
ndk::ScopedAStatus BluetoothAudioProvider::startSession(
@@ -39,17 +61,21 @@
DataMQDesc* _aidl_return) {
if (host_if == nullptr) {
*_aidl_return = DataMQDesc();
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << " Illegal argument";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
latency_modes_ = latencyModes;
audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
stack_iface_ = host_if;
- is_binder_died = false;
+ BluetoothAudioProviderContext* cookie =
+ new BluetoothAudioProviderContext{session_type_};
AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
- this);
+ cookie);
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
onSessionReady(_aidl_return);
return ndk::ScopedAStatus::ok();
}
@@ -60,10 +86,8 @@
if (stack_iface_ != nullptr) {
BluetoothAudioSessionReport::OnSessionEnded(session_type_);
- if (!is_binder_died) {
- AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
- death_recipient_.get(), this);
- }
+ AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
+ death_recipient_.get(), this);
} else {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
@@ -77,10 +101,9 @@
ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
BluetoothAudioStatus status) {
- LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
- << ", status=" << toString(status);
-
if (stack_iface_ != nullptr) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status);
BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
status);
} else {
@@ -108,8 +131,6 @@
ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
const AudioConfiguration& audio_config) {
- LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
if (stack_iface_ == nullptr || audio_config_ == nullptr) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
@@ -125,13 +146,13 @@
audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
*audio_config_);
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " | audio_config=" << audio_config.toString();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed(
bool allowed) {
- LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
if (stack_iface_ == nullptr) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
@@ -143,17 +164,6 @@
return ndk::ScopedAStatus::ok();
}
-void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) {
- LOG(ERROR) << __func__ << " - BluetoothAudio Service died";
- auto provider = static_cast<BluetoothAudioProvider*>(ptr);
- if (provider == nullptr) {
- LOG(ERROR) << __func__ << ": Null AudioProvider HAL died";
- return;
- }
- provider->is_binder_died = true;
- provider->endSession();
-}
-
} // namespace audio
} // namespace bluetooth
} // namespace hardware
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index dbfff7d..b6e07a1 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -54,7 +54,6 @@
protected:
virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0;
- static void binderDiedCallbackAidl(void* cookie_ptr);
::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
@@ -62,9 +61,7 @@
std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
SessionType session_type_;
std::vector<LatencyMode> latency_modes_;
- bool is_binder_died = false;
};
-
} // namespace audio
} // namespace bluetooth
} // namespace hardware
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index e03fb58..3e6953f 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -15,16 +15,20 @@
],
tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
- shared_libs: [
+ static_libs: [
"android.hardware.audio.common-V1-ndk",
"android.hardware.bluetooth.audio-V3-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
+ "android.media.audio.common.types-V2-ndk",
+ ],
+ shared_libs: [
"libbase",
"libbinder_ndk",
"libcutils",
"libfmq",
],
+ test_config: "VtsHalBluetoothAudioTargetTest.xml",
test_suites: [
"general-tests",
"vts",
diff --git a/camera/provider/aidl/vts/AndroidTest.xml b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
similarity index 65%
rename from camera/provider/aidl/vts/AndroidTest.xml
rename to bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
index 226121d..7b02685 100644
--- a/camera/provider/aidl/vts/AndroidTest.xml
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 The Android Open Source Project
+<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,21 +13,24 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs VtsAidlHalCameraProvider_TargetTest.">
+<configuration description="Runs VtsHalBluetoothAudioTargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController">
+ <!-- Skips test module if ro.product.first_api_level < 33. -->
+ <option name="min-api-level" value="33" />
+ </object>
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="VtsAidlHalCameraProvider_TargetTest->/data/local/tmp/VtsAidlHalCameraProvider_TargetTest" />
+ <option name="push" value="VtsHalBluetoothAudioTargetTest->/data/local/tmp/VtsHalBluetoothAudioTargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsAidlHalCameraProvider_TargetTest" />
- <option name="native-test-timeout" value="1800000"/> <!-- 30 min -->
+ <option name="module-name" value="VtsHalBluetoothAudioTargetTest" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 914d2b2..2cba61e 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -93,4 +93,5 @@
srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],
package_name: "aidl.android.hardware.bluetooth.audio.setting",
api_dir: "le_audio_codec_capabilities/schema",
+ root_elements: ["leAudioOffloadSetting"],
}
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index 886350e..3cef417 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -96,15 +96,7 @@
public class XmlParser {
ctor public XmlParser();
- method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration readCodecConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList readCodecConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.Configuration readConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.ConfigurationList readConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static aidl.android.hardware.bluetooth.audio.setting.LeAudioOffloadSetting readLeAudioOffloadSetting(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.Scenario readScenario(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.ScenarioList readScenarioList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration readStrategyConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList readStrategyConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
diff --git a/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
index 51a624f..5f6d86e 100644
--- a/bluetooth/hci/h4_protocol.cc
+++ b/bluetooth/hci/h4_protocol.cc
@@ -105,15 +105,12 @@
buffer_offset += 1;
} else {
bool packet_ready = hci_packetizer_.OnDataReady(
- hci_packet_type_, input_buffer, buffer_offset);
+ hci_packet_type_, input_buffer, &buffer_offset);
if (packet_ready) {
- // Call packet callback and move offset.
- buffer_offset += OnPacketReady(hci_packetizer_.GetPacket());
+ // Call packet callback.
+ OnPacketReady(hci_packetizer_.GetPacket());
// Get ready for the next type byte.
hci_packet_type_ = PacketType::UNKNOWN;
- } else {
- // The data was consumed, but there wasn't a packet.
- buffer_offset = input_buffer.size();
}
}
}
diff --git a/bluetooth/hci/hci_packetizer.cc b/bluetooth/hci/hci_packetizer.cc
index 5b6c443..4135920 100644
--- a/bluetooth/hci/hci_packetizer.cc
+++ b/bluetooth/hci/hci_packetizer.cc
@@ -51,9 +51,10 @@
bool HciPacketizer::OnDataReady(PacketType packet_type,
const std::vector<uint8_t>& buffer,
- size_t offset) {
+ size_t* offset) {
bool packet_completed = false;
- size_t bytes_available = buffer.size() - offset;
+ size_t bytes_available = buffer.size() - *offset;
+
switch (state_) {
case HCI_HEADER: {
size_t header_size =
@@ -62,18 +63,20 @@
bytes_remaining_ = header_size;
packet_.clear();
}
+
size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
- packet_.insert(packet_.end(), buffer.begin() + offset,
- buffer.begin() + offset + bytes_to_copy);
+ packet_.insert(packet_.end(), buffer.begin() + *offset,
+ buffer.begin() + *offset + bytes_to_copy);
bytes_remaining_ -= bytes_to_copy;
bytes_available -= bytes_to_copy;
+ *offset += bytes_to_copy;
+
if (bytes_remaining_ == 0) {
bytes_remaining_ = HciGetPacketLengthForType(packet_type, packet_);
if (bytes_remaining_ > 0) {
state_ = HCI_PAYLOAD;
if (bytes_available > 0) {
- packet_completed =
- OnDataReady(packet_type, buffer, offset + bytes_to_copy);
+ packet_completed = OnDataReady(packet_type, buffer, offset);
}
} else {
packet_completed = true;
@@ -84,9 +87,10 @@
case HCI_PAYLOAD: {
size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
- packet_.insert(packet_.end(), buffer.begin() + offset,
- buffer.begin() + offset + bytes_to_copy);
+ packet_.insert(packet_.end(), buffer.begin() + *offset,
+ buffer.begin() + *offset + bytes_to_copy);
bytes_remaining_ -= bytes_to_copy;
+ *offset += bytes_to_copy;
if (bytes_remaining_ == 0) {
state_ = HCI_HEADER;
packet_completed = true;
@@ -94,6 +98,7 @@
break;
}
}
+
return packet_completed;
}
diff --git a/bluetooth/hci/hci_packetizer.h b/bluetooth/hci/hci_packetizer.h
index ba3e841..0d9319f 100644
--- a/bluetooth/hci/hci_packetizer.h
+++ b/bluetooth/hci/hci_packetizer.h
@@ -28,7 +28,7 @@
public:
HciPacketizer() = default;
bool OnDataReady(PacketType packet_type, const std::vector<uint8_t>& data,
- size_t offset);
+ size_t* offset);
const std::vector<uint8_t>& GetPacket() const;
protected:
diff --git a/bluetooth/hci/test/h4_protocol_unittest.cc b/bluetooth/hci/test/h4_protocol_unittest.cc
index d3fab61..f0c49b5 100644
--- a/bluetooth/hci/test/h4_protocol_unittest.cc
+++ b/bluetooth/hci/test/h4_protocol_unittest.cc
@@ -31,7 +31,6 @@
#include <vector>
#include "async_fd_watcher.h"
-#include "log/log.h"
using android::hardware::bluetooth::async::AsyncFdWatcher;
using namespace android::hardware::bluetooth::hci;
@@ -49,6 +48,7 @@
static char event_data[100] = "The edges of a surface are lines.";
static char iso_data[100] =
"A plane angle is the inclination to one another of two lines in a ...";
+static char short_payload[10] = "12345";
// 5 seconds. Just don't hang.
static constexpr size_t kTimeoutMs = 5000;
@@ -225,6 +225,49 @@
CallDataReady();
}
+ void WriteAndExpectManyAclDataPacketsDifferentOffsetsShort() {
+ std::promise<void> last_packet_promise;
+ size_t kNumPackets = 30;
+ // h4 type[1] + handle[2] + size[2]
+ char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
+ 0};
+ int length = strlen(short_payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = 0;
+
+ EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, kAclHeaderSize,
+ short_payload)))
+ .Times(kNumPackets);
+ ExpectInboundEvent(event_data, &last_packet_promise);
+
+ char all_packets[kNumPackets * 10];
+ size_t total_bytes = 0;
+
+ for (size_t packet = 0; packet < kNumPackets; packet++) {
+ for (size_t i = 0; i < sizeof(preamble); i++) {
+ all_packets[total_bytes++] = preamble[i];
+ }
+ for (size_t i = 0; i < length; i++) {
+ all_packets[total_bytes++] = short_payload[i];
+ }
+ }
+
+ size_t written_bytes = 0;
+ size_t partial_size = 1;
+ while (written_bytes < total_bytes) {
+ size_t to_write = std::min(partial_size, total_bytes - written_bytes);
+ TEMP_FAILURE_RETRY(
+ write(chip_uart_fd_, all_packets + written_bytes, to_write));
+ written_bytes += to_write;
+ CallDataReady();
+ partial_size++;
+ partial_size = partial_size % 5 + 1;
+ }
+ WriteInboundEvent(event_data);
+ CallDataReady();
+ WaitForTimeout(&last_packet_promise);
+ }
+
testing::MockFunction<void(const std::vector<uint8_t>&)> cmd_cb_;
testing::MockFunction<void(const std::vector<uint8_t>&)> event_cb_;
testing::MockFunction<void(const std::vector<uint8_t>&)> acl_cb_;
@@ -276,6 +319,10 @@
WriteAndExpectManyInboundAclDataPackets(sco_data);
}
+TEST_F(H4ProtocolTest, TestMultipleWritesPacketsShortWrites) {
+ WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
TEST_F(H4ProtocolTest, TestDisconnect) {
EXPECT_CALL(disconnect_cb_, Call());
close(chip_uart_fd_);
@@ -332,10 +379,8 @@
void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
- void CallDataReady() override {
- // The Async test can't call data ready.
- FAIL();
- }
+ // Calling CallDataReady() has no effect in the AsyncTest
+ void CallDataReady() override {}
void SendAndReadUartOutbound(PacketType type, char* data) {
ALOGD("%s sending", __func__);
@@ -434,6 +479,10 @@
WriteAndExpectManyInboundAclDataPackets(sco_data);
}
+TEST_F(H4ProtocolAsyncTest, TestMultipleWritesPacketsShortWrites) {
+ WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
TEST_F(H4ProtocolAsyncTest, TestDisconnect) {
std::promise<void> promise;
EXPECT_CALL(disconnect_cb_, Call()).WillOnce(Notify(&promise));
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
index 4fc7437..04db7f3 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
@@ -18,15 +18,16 @@
//#define LOG_NDEBUG 0
#include <log/log.h>
-#include <regex>
-#include <sys/inotify.h>
+#include <cutils/properties.h>
#include <errno.h>
#include <linux/videodev2.h>
-#include <cutils/properties.h>
-#include "ExternalCameraProviderImpl_2_4.h"
+#include <sys/inotify.h>
+#include <regex>
+#include <string>
#include "ExternalCameraDevice_3_4.h"
#include "ExternalCameraDevice_3_5.h"
#include "ExternalCameraDevice_3_6.h"
+#include "ExternalCameraProviderImpl_2_4.h"
namespace android {
namespace hardware {
@@ -41,10 +42,10 @@
// "device@<version>/external/<id>"
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
const int kMaxDevicePathLen = 256;
-const char* kDevicePath = "/dev/";
-constexpr char kPrefix[] = "video";
-constexpr int kPrefixLen = sizeof(kPrefix) - 1;
-constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+constexpr const char* kDevicePath = "/dev/";
+constexpr const char* kPrefix = "video";
+constexpr int kPrefixLen = std::char_traits<char>::length(kPrefix);
+constexpr int kDevicePrefixLen = std::char_traits<char>::length(kDevicePath) + kPrefixLen;
bool matchDeviceName(int cameraIdOffset,
const hidl_string& deviceName, std::string* deviceVersion,
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
index b63e3bb..62ce074 100644
--- a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
@@ -23,6 +23,7 @@
#include <linux/videodev2.h>
#include <sys/inotify.h>
#include <regex>
+#include <string>
#include "ExternalCameraDevice_3_4.h"
#include "ExternalCameraDevice_3_5.h"
#include "ExternalCameraDevice_3_6.h"
@@ -39,10 +40,10 @@
// "device@<version>/external/<id>"
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
const int kMaxDevicePathLen = 256;
-const char* kDevicePath = "/dev/";
-constexpr char kPrefix[] = "video";
-constexpr int kPrefixLen = sizeof(kPrefix) - 1;
-constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+constexpr const char* kDevicePath = "/dev/";
+constexpr const char* kPrefix = "video";
+constexpr int kPrefixLen = std::char_traits<char>::length(kPrefix);
+constexpr int kDevicePrefixLen = std::char_traits<char>::length(kDevicePath) + kPrefixLen;
bool matchDeviceName(int cameraIdOffset, const hidl_string& deviceName, std::string* deviceVersion,
std::string* cameraDevicePath) {
diff --git a/camera/provider/aidl/vts/Android.bp b/camera/provider/aidl/vts/Android.bp
index 8429b21..59f6c66 100644
--- a/camera/provider/aidl/vts/Android.bp
+++ b/camera/provider/aidl/vts/Android.bp
@@ -68,6 +68,16 @@
"libgralloctypes",
"libaidlcommonsupport",
],
+
+ require_root: true,
+ test_options: {
+ test_runner_options: [
+ {
+ name: "native-test-timeout",
+ value: "1800000",
+ },
+ ],
+ },
test_suites: [
"general-tests",
"vts",
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 93b5380..b3ca293 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -82,3 +82,15 @@
"kernel_config_u_6.1",
],
}
+
+vintf_compatibility_matrix {
+ name: "framework_compatibility_matrix.9.xml",
+ stem: "compatibility_matrix.9.xml",
+ srcs: [
+ "compatibility_matrix.9.xml",
+ ],
+ kernel_configs: [
+ "kernel_config_v_5.15",
+ "kernel_config_v_6.1",
+ ],
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6e4c419..a82a421 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -103,6 +103,7 @@
framework_compatibility_matrix.6.xml \
framework_compatibility_matrix.7.xml \
framework_compatibility_matrix.8.xml \
+ framework_compatibility_matrix.9.xml \
framework_compatibility_matrix.device.xml \
my_framework_matrix_deps += \
diff --git a/compatibility_matrices/bump.py b/compatibility_matrices/bump.py
new file mode 100755
index 0000000..88b7a42
--- /dev/null
+++ b/compatibility_matrices/bump.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""
+Creates the next compatibility matrix.
+
+Requires libvintf Level.h to be updated before executing this script.
+"""
+
+import argparse
+import os
+import pathlib
+import shutil
+import subprocess
+import textwrap
+
+
+def check_call(*args, **kwargs):
+ print(args)
+ subprocess.check_call(*args, **kwargs)
+
+
+def check_output(*args, **kwargs):
+ print(args)
+ return subprocess.check_output(*args, **kwargs)
+
+
+class Bump(object):
+
+ def __init__(self, cmdline_args):
+ self.top = pathlib.Path(os.environ["ANDROID_BUILD_TOP"])
+ self.interfaces_dir = self.top / "hardware/interfaces"
+
+ self.current_level = cmdline_args.current
+ self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
+ self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
+
+ self.next_level = cmdline_args.next
+ self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml"
+ self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml"
+
+ self.level_to_letter = self.get_level_to_letter_mapping()
+ print("Found level mapping in libvintf Level.h:", self.level_to_letter)
+
+ def run(self):
+ self.bump_kernel_configs()
+ self.copy_matrix()
+ self.edit_android_bp()
+ self.edit_android_mk()
+
+ def get_level_to_letter_mapping(self):
+ levels_file = self.top / "system/libvintf/include/vintf/Level.h"
+ with open(levels_file) as f:
+ lines = f.readlines()
+ pairs = [
+ line.split("=", maxsplit=2) for line in lines if "=" in line
+ ]
+ return {
+ level.strip().removesuffix(","): letter.strip()
+ for letter, level in pairs
+ }
+
+ def bump_kernel_configs(self):
+ check_call([
+ self.top / "kernel/configs/tools/bump.py",
+ self.level_to_letter[self.current_level].lower(),
+ self.level_to_letter[self.next_level].lower(),
+ ])
+
+ def copy_matrix(self):
+ shutil.copyfile(self.current_xml, self.next_xml)
+
+ def edit_android_bp(self):
+ android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp"
+
+ with open(android_bp, "r+") as f:
+ if self.next_module_name not in f.read():
+ f.seek(0, 2) # end of file
+ f.write("\n")
+ f.write(
+ textwrap.dedent(f"""\
+ vintf_compatibility_matrix {{
+ name: "{self.next_module_name}",
+ }}
+ """))
+
+ next_kernel_configs = check_output(
+ """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""",
+ cwd=self.top / "kernel/configs" /
+ self.level_to_letter[self.next_level].lower(),
+ text=True,
+ shell=True,
+ ).splitlines()
+ print(next_kernel_configs)
+
+ check_call([
+ "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem",
+ "-str", self.next_xml.name, android_bp
+ ])
+
+ check_call([
+ "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs",
+ "-a",
+ self.next_xml.relative_to(android_bp.parent), android_bp
+ ])
+
+ check_call([
+ "bpmodify", "-w", "-m", self.next_module_name, "-property",
+ "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp
+ ])
+
+ def edit_android_mk(self):
+ android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk"
+ with open(android_mk) as f:
+ if self.next_module_name in f.read():
+ return
+ f.seek(0)
+ lines = f.readlines()
+ current_module_line_number = None
+ for line_number, line in enumerate(lines):
+ if self.current_module_name in line:
+ current_module_line_number = line_number
+ break
+ assert current_module_line_number is not None
+ lines.insert(current_module_line_number + 1,
+ f" {self.next_module_name} \\\n")
+ with open(android_mk, "w") as f:
+ f.write("".join(lines))
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("current",
+ type=str,
+ help="VINTF level of the current version (e.g. 9)")
+ parser.add_argument("next",
+ type=str,
+ help="VINTF level of the next version (e.g. 10)")
+ cmdline_args = parser.parse_args()
+
+ Bump(cmdline_args).run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index c04a499..4aa832b 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -114,7 +114,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.face</name>
<version>3</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 188746d..6bbf440 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -1,4 +1,3 @@
-<!-- WARNING: This file is unused in the Android 14 branch. -->
<compatibility-matrix version="1.0" type="framework" level="9">
<hal format="hidl" optional="true">
<name>android.hardware.audio</name>
@@ -115,7 +114,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.face</name>
<version>3</version>
<interface>
@@ -123,7 +122,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>3</version>
<interface>
@@ -132,14 +131,6 @@
<instance>virtual</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.bluetooth</name>
- <version>1.0-1</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.bluetooth</name>
<interface>
@@ -366,6 +357,15 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <interface>
+ <name>IComponentStore</name>
+ <regex-instance>default[0-9]*</regex-instance>
+ <regex-instance>vendor[0-9]*_software</regex-instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.memtrack</name>
<version>1</version>
<interface>
@@ -493,16 +493,6 @@
</interface>
</hal>
<hal format="aidl" optional="true">
- <name>android.hardware.radio.satellite</name>
- <version>1</version>
- <interface>
- <name>IRadioSatellite</name>
- <instance>slot1</instance>
- <instance>slot2</instance>
- <instance>slot3</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
<name>android.hardware.radio.ims.media</name>
<version>1</version>
<interface>
@@ -510,14 +500,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.renderscript</name>
- <version>1.0</version>
- <interface>
- <name>IDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.rebootescrow</name>
<version>1</version>
@@ -560,14 +542,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.soundtrigger</name>
- <version>2.3</version>
- <interface>
- <name>ISoundTriggerHw</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.soundtrigger3</name>
<version>1</version>
@@ -576,22 +550,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tetheroffload.config</name>
- <version>1.0</version>
- <interface>
- <name>IOffloadConfig</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tetheroffload.control</name>
- <version>1.1</version>
- <interface>
- <name>IOffloadControl</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.tetheroffload</name>
<version>1</version>
@@ -727,4 +685,12 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.threadnetwork</name>
+ <version>1</version>
+ <interface>
+ <name>IThreadChip</name>
+ <regex-instance>chip[0-9]+</regex-instance>
+ </interface>
+ </hal>
</compatibility-matrix>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 3bc1786..f3374c3 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -103,10 +103,6 @@
"android.hardware.thermal@1.0",
"android.hardware.thermal@1.1",
"android.hardware.wifi.offload@1.0",
-
- // Under hardware/interfaces/staging, still in development
- // AIDL
- "android.hardware.media.c2",
};
auto package_has_prefix = [&](const std::string& prefix) {
diff --git a/contexthub/aidl/Android.bp b/contexthub/aidl/Android.bp
index 814bf3b..a0315d0 100644
--- a/contexthub/aidl/Android.bp
+++ b/contexthub/aidl/Android.bp
@@ -34,6 +34,9 @@
ndk: {
apps_enabled: false,
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/drm/1.3/vts/OWNERS b/drm/1.3/vts/OWNERS
index 3a0672e..744827c 100644
--- a/drm/1.3/vts/OWNERS
+++ b/drm/1.3/vts/OWNERS
@@ -1,9 +1,11 @@
+# Bug component: 49079
conglin@google.com
-edwinwong@google.com
fredgc@google.com
-jtinker@google.com
juce@google.com
+kelzhan@google.com
kylealexander@google.com
+mattfedd@google.com
rfrias@google.com
robertshih@google.com
sigquit@google.com
+vickymin@google.com
\ No newline at end of file
diff --git a/gnss/aidl/OWNERS b/gnss/aidl/OWNERS
index b7b4a2e..e5b585e 100644
--- a/gnss/aidl/OWNERS
+++ b/gnss/aidl/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 393449
+
gomo@google.com
smalkos@google.com
wyattriley@google.com
diff --git a/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
index 50aa2b7..7194ebe 100644
--- a/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
+++ b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
@@ -23,7 +23,14 @@
@VintfStability
parcelable BufferDescriptorInfo {
/**
- * The name of the buffer in ASCII. Useful for debugging/tracing.
+ * The name of the buffer in null-terminated ASCII. Useful for debugging/tracing.
+ *
+ * NOTE: While a well behaved client will ensure it passes a null-terminated string
+ * within the 128-byte limit, the IAllocator service implementation should be
+ * be defensive against malformed input. As such, it is recommended that
+ * IAllocator implementations proactively do `name[127] = 0` upon receiving
+ * an allocation request to enusre that the string is definitely
+ * null-terminated regardless of what the client sent.
*/
byte[128] name;
diff --git a/graphics/composer/2.4/vts/functional/TEST_MAPPING b/graphics/composer/2.4/vts/functional/TEST_MAPPING
new file mode 100644
index 0000000..aedac5b
--- /dev/null
+++ b/graphics/composer/2.4/vts/functional/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalGraphicsComposerV2_4TargetTest"
+ }
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "VtsHalGraphicsComposerV2_4TargetTest"
+ }
+ ]
+}
+
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index e4a84e1..03d9041 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -677,7 +677,7 @@
const native_handle_t* clonedBufferHandle;
ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
- error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+ error = mGralloc->getMapper()->freeBuffer(const_cast<native_handle_t*>(clonedBufferHandle));
EXPECT_EQ(Error::BAD_BUFFER, error)
<< "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 2c06353..b329de2 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -1371,6 +1371,28 @@
EXPECT_EQ(buffer->info().usage, *value);
}
+TEST_P(GraphicsMapperStableCTests, GetUsage64) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::FRONT_BUFFER | BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE,
+ .reservedSize = 0,
+ };
+ if (!isSupported(info)) {
+ GTEST_SKIP();
+ }
+ auto buffer = allocate(info);
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ using T = std::underlying_type_t<BufferUsage>;
+ EXPECT_EQ(static_cast<T>(buffer->info().usage), static_cast<T>(*value));
+}
+
TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
auto buffer = allocateGeneric();
auto bufferHandle = buffer->import();
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index f401643..1d8cc13 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -272,7 +272,11 @@
{
std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
- callbacks_.emplace_back(LinkedCallback::Make(ref<Health>(), callback));
+ auto linked_callback_result = LinkedCallback::Make(ref<Health>(), callback);
+ if (!linked_callback_result.ok()) {
+ return ndk::ScopedAStatus::fromStatus(-linked_callback_result.error().code());
+ }
+ callbacks_.emplace_back(std::move(*linked_callback_result));
// unlock
}
diff --git a/health/aidl/default/LinkedCallback.cpp b/health/aidl/default/LinkedCallback.cpp
index 2985ffe..26e99f9 100644
--- a/health/aidl/default/LinkedCallback.cpp
+++ b/health/aidl/default/LinkedCallback.cpp
@@ -24,7 +24,7 @@
namespace aidl::android::hardware::health {
-std::unique_ptr<LinkedCallback> LinkedCallback::Make(
+::android::base::Result<std::unique_ptr<LinkedCallback>> LinkedCallback::Make(
std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback) {
std::unique_ptr<LinkedCallback> ret(new LinkedCallback());
binder_status_t linkRet =
@@ -32,7 +32,7 @@
reinterpret_cast<void*>(ret.get()));
if (linkRet != ::STATUS_OK) {
LOG(WARNING) << __func__ << "Cannot link to death: " << linkRet;
- return nullptr;
+ return ::android::base::Error(-linkRet);
}
ret->service_ = service;
ret->callback_ = std::move(callback);
diff --git a/health/aidl/default/LinkedCallback.h b/health/aidl/default/LinkedCallback.h
index 82490a7..da494c9 100644
--- a/health/aidl/default/LinkedCallback.h
+++ b/health/aidl/default/LinkedCallback.h
@@ -20,6 +20,7 @@
#include <aidl/android/hardware/health/IHealthInfoCallback.h>
#include <android-base/macros.h>
+#include <android-base/result.h>
#include <android/binder_auto_utils.h>
#include <health-impl/Health.h>
@@ -34,8 +35,8 @@
// service->death_reciepient() should be from CreateDeathRecipient().
// Not using a strong reference to |service| to avoid circular reference. The lifetime
// of |service| must be longer than this LinkedCallback object.
- static std::unique_ptr<LinkedCallback> Make(std::shared_ptr<Health> service,
- std::shared_ptr<IHealthInfoCallback> callback);
+ static ::android::base::Result<std::unique_ptr<LinkedCallback>> Make(
+ std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback);
// Automatically unlinkToDeath upon destruction. So, it is always safe to reinterpret_cast
// the cookie back to the LinkedCallback object.
diff --git a/health/storage/aidl/vts/functional/OWNERS b/health/storage/aidl/vts/functional/OWNERS
new file mode 100644
index 0000000..a15ed7c
--- /dev/null
+++ b/health/storage/aidl/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+file:platform/hardware/interfaces:/health/aidl/OWNERS
\ No newline at end of file
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 3096fe5..d62d055 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -22,15 +22,8 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_library {
- name: "android.hardware.identity-support-lib",
- vendor_available: true,
- srcs: [
- "src/IdentityCredentialSupport.cpp",
- ],
- export_include_dirs: [
- "include",
- ],
+cc_defaults {
+ name: "android.hardware.identity-support-lib-deps",
shared_libs: [
"android.hardware.keymaster@4.0",
"libcrypto",
@@ -47,19 +40,36 @@
],
}
+cc_library {
+ name: "android.hardware.identity-support-lib",
+ vendor_available: true,
+ defaults: [
+ "android.hardware.identity-support-lib-deps",
+ ],
+ srcs: [
+ "src/IdentityCredentialSupport.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+}
+
cc_test {
name: "android.hardware.identity-support-lib-test",
srcs: [
"tests/IdentityCredentialSupportTest.cpp",
],
+ defaults: [
+ "android.hardware.identity-support-lib-deps",
+ ],
shared_libs: [
- "android.hardware.identity-support-lib",
"libcrypto",
"libbase",
"libhidlbase",
"libhardware",
],
static_libs: [
+ "android.hardware.identity-support-lib",
"libcppbor_external",
"libgmock",
],
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 554afe7..65b3dfa 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2617,10 +2617,11 @@
EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
- size_t modulus_len = BN_num_bytes(rsa->n);
+ const BIGNUM* n = RSA_get0_n(rsa.get());
+ size_t modulus_len = BN_num_bytes(n);
ASSERT_EQ(1024U / 8, modulus_len);
std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n, modulus_buf.get());
// The modulus is too big to encrypt.
string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2632,10 +2633,12 @@
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
// One smaller than the modulus is okay.
- BN_sub(rsa->n, rsa->n, BN_value_one());
- modulus_len = BN_num_bytes(rsa->n);
+ BIGNUM_Ptr n_minus_1(BN_new());
+ ASSERT_TRUE(n_minus_1);
+ ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+ modulus_len = BN_num_bytes(n_minus_1.get());
ASSERT_EQ(1024U / 8, modulus_len);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n_minus_1.get(), modulus_buf.get());
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index b709904..96580c0 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2449,10 +2449,11 @@
EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
- size_t modulus_len = BN_num_bytes(rsa->n);
+ const BIGNUM* n = RSA_get0_n(rsa.get());
+ size_t modulus_len = BN_num_bytes(n);
ASSERT_EQ(2048U / 8, modulus_len);
std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n, modulus_buf.get());
// The modulus is too big to encrypt.
string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2464,10 +2465,12 @@
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
// One smaller than the modulus is okay.
- BN_sub(rsa->n, rsa->n, BN_value_one());
- modulus_len = BN_num_bytes(rsa->n);
+ BIGNUM_Ptr n_minus_1(BN_new());
+ ASSERT_TRUE(n_minus_1);
+ ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+ modulus_len = BN_num_bytes(n_minus_1.get());
ASSERT_EQ(2048U / 8, modulus_len);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n_minus_1.get(), modulus_buf.get());
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/keymaster/TEST_MAPPING b/keymaster/TEST_MAPPING
new file mode 100644
index 0000000..8cbf3e1
--- /dev/null
+++ b/keymaster/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalKeymasterV3_0TargetTest"
+ },
+ {
+ "name": "VtsHalKeymasterV4_0TargetTest"
+ },
+ {
+ "name": "VtsHalKeymasterV4_1TargetTest"
+ }
+ ]
+}
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index c11934f..c9fba95 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -18,6 +18,9 @@
java: {
sdk_version: "module_current",
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/light/aidl/aidl_api/android.hardware.light/2/.hash b/light/aidl/aidl_api/android.hardware.light/2/.hash
index d27f4ad..2d4e7f0 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/.hash
+++ b/light/aidl/aidl_api/android.hardware.light/2/.hash
@@ -1 +1,2 @@
c8b1e8ebb88c57dcb2c350a8d9b722e77dd864c8
+c7d3d941d303c70d1c22759a0b09e41930c1cddb
diff --git a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
index 25a2dce..5ac2a34 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
@@ -32,7 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLight {
int id;
int ordinal;
diff --git a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
index 40e520b..2878ce2 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
@@ -32,7 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLightState {
int color;
android.hardware.light.FlashMode flashMode;
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
index 25a2dce..5ac2a34 100644
--- a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
@@ -32,7 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLight {
int id;
int ordinal;
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
index 40e520b..2878ce2 100644
--- a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
@@ -32,7 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLightState {
int color;
android.hardware.light.FlashMode flashMode;
diff --git a/light/aidl/android/hardware/light/HwLight.aidl b/light/aidl/android/hardware/light/HwLight.aidl
index 43fdb4b..8db32cc 100644
--- a/light/aidl/android/hardware/light/HwLight.aidl
+++ b/light/aidl/android/hardware/light/HwLight.aidl
@@ -22,7 +22,7 @@
* A description of a single light. Multiple lights can map to the same physical
* LED. Separate physical LEDs are always represented by separate instances.
*/
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLight {
/**
* Integer ID used for controlling this light
diff --git a/light/aidl/android/hardware/light/HwLightState.aidl b/light/aidl/android/hardware/light/HwLightState.aidl
index 24d3250..3ba6c78 100644
--- a/light/aidl/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/android/hardware/light/HwLightState.aidl
@@ -25,7 +25,7 @@
* Not all lights must support all parameters. If you
* can do something backward-compatible, do it.
*/
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
parcelable HwLightState {
/**
* The color of the LED in ARGB.
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
index 7920503..285329e 100644
--- a/light/aidl/default/Android.bp
+++ b/light/aidl/default/Android.bp
@@ -7,19 +7,17 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_binary {
+rust_binary {
name: "android.hardware.lights-service.example",
relative_install_path: "hw",
init_rc: ["lights-default.rc"],
vintf_fragments: ["lights-default.xml"],
vendor: true,
- shared_libs: [
- "libbase",
- "libbinder_ndk",
- "android.hardware.light-V2-ndk",
+ rustlibs: [
+ "liblogger",
+ "liblog_rust",
+ "libbinder_rs",
+ "android.hardware.light-V2-rust",
],
- srcs: [
- "Lights.cpp",
- "main.cpp",
- ],
+ srcs: [ "main.rs" ],
}
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
deleted file mode 100644
index 9bf3b20..0000000
--- a/light/aidl/default/Lights.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lights.h"
-
-#include <android-base/logging.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-static constexpr int kNumDefaultLights = 3;
-
-ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
- LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
- if (id <= 0 || id > kNumDefaultLights) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
- } else {
- return ndk::ScopedAStatus::ok();
- }
-}
-
-ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* lights) {
- for (int i = 1; i <= kNumDefaultLights; i++) {
- lights->push_back({i, i});
- }
- LOG(INFO) << "Lights reporting supported lights";
- return ndk::ScopedAStatus::ok();
-}
-
-} // namespace light
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
deleted file mode 100644
index cba147f..0000000
--- a/light/aidl/default/Lights.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/light/BnLights.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-// Default implementation that reports a few placeholder lights.
-class Lights : public BnLights {
- ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
- ndk::ScopedAStatus getLights(std::vector<HwLight>* lights) override;
-};
-
-} // namespace light
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/light/aidl/default/lights.rs b/light/aidl/default/lights.rs
new file mode 100644
index 0000000..6c8aa3f
--- /dev/null
+++ b/light/aidl/default/lights.rs
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//! This module implements the ILights AIDL interface.
+
+use std::collections::HashMap;
+use std::sync::Mutex;
+
+use log::info;
+
+use android_hardware_light::aidl::android::hardware::light::{
+ HwLight::HwLight, HwLightState::HwLightState, ILights::ILights, LightType::LightType,
+};
+
+use binder::{ExceptionCode, Interface, Status};
+
+struct Light {
+ hw_light: HwLight,
+ state: HwLightState,
+}
+
+const NUM_DEFAULT_LIGHTS: i32 = 3;
+
+/// Defined so we can implement the ILights AIDL interface.
+pub struct LightsService {
+ lights: Mutex<HashMap<i32, Light>>,
+}
+
+impl Interface for LightsService {}
+
+impl LightsService {
+ fn new(hw_lights: impl IntoIterator<Item = HwLight>) -> Self {
+ let mut lights_map = HashMap::new();
+
+ for hw_light in hw_lights {
+ lights_map.insert(hw_light.id, Light { hw_light, state: Default::default() });
+ }
+
+ Self { lights: Mutex::new(lights_map) }
+ }
+}
+
+impl Default for LightsService {
+ fn default() -> Self {
+ let id_mapping_closure =
+ |light_id| HwLight { id: light_id, ordinal: light_id, r#type: LightType::BACKLIGHT };
+
+ Self::new((1..=NUM_DEFAULT_LIGHTS).map(id_mapping_closure))
+ }
+}
+
+impl ILights for LightsService {
+ fn setLightState(&self, id: i32, state: &HwLightState) -> binder::Result<()> {
+ info!("Lights setting state for id={} to color {:x}", id, state.color);
+
+ if let Some(light) = self.lights.lock().unwrap().get_mut(&id) {
+ light.state = *state;
+ Ok(())
+ } else {
+ Err(Status::new_exception(ExceptionCode::UNSUPPORTED_OPERATION, None))
+ }
+ }
+
+ fn getLights(&self) -> binder::Result<Vec<HwLight>> {
+ info!("Lights reporting supported lights");
+ Ok(self.lights.lock().unwrap().values().map(|light| light.hw_light).collect())
+ }
+}
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
deleted file mode 100644
index 54e1316..0000000
--- a/light/aidl/default/main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lights.h"
-
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-using ::aidl::android::hardware::light::Lights;
-
-int main() {
- ABinderProcess_setThreadPoolMaxThreadCount(0);
- std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
-
- const std::string instance = std::string() + Lights::descriptor + "/default";
- binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
- CHECK_EQ(status, STATUS_OK);
-
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // should not reached
-}
diff --git a/light/aidl/default/main.rs b/light/aidl/default/main.rs
new file mode 100644
index 0000000..8f32470
--- /dev/null
+++ b/light/aidl/default/main.rs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//! This implements the Lights Example Service.
+
+use android_hardware_light::aidl::android::hardware::light::ILights::{BnLights, ILights};
+use binder::BinderFeatures;
+
+mod lights;
+use lights::LightsService;
+
+const LOG_TAG: &str = "lights_service_example_rust";
+
+use log::Level;
+
+fn main() {
+ let logger_success = logger::init(
+ logger::Config::default().with_tag_on_device(LOG_TAG).with_min_level(Level::Trace),
+ );
+ if !logger_success {
+ panic!("{LOG_TAG}: Failed to start logger.");
+ }
+
+ binder::ProcessState::set_thread_pool_max_thread_count(0);
+
+ let lights_service = LightsService::default();
+ let lights_service_binder = BnLights::new_binder(lights_service, BinderFeatures::default());
+
+ let service_name = format!("{}/default", LightsService::get_descriptor());
+ binder::add_service(&service_name, lights_service_binder.as_binder())
+ .expect("Failed to register service");
+
+ binder::ProcessState::join_thread_pool()
+}
diff --git a/staging/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
similarity index 93%
rename from staging/c2/aidl/Android.bp
rename to media/c2/aidl/Android.bp
index b9da7ad..75d74ac 100644
--- a/staging/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -13,15 +13,15 @@
name: "android.hardware.media.c2",
vendor_available: true,
double_loadable: true,
- unstable: true,
srcs: ["android/hardware/media/c2/*.aidl"],
include_dirs: [
- "frameworks/native/aidl/gui",
+ "frameworks/base/core/java",
],
imports: [
"android.hardware.common-V2",
"android.hardware.media.bufferpool2-V1",
],
+ stability: "vintf",
backend: {
cpp: {
enabled: false,
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..460ff97
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+union BaseBlock {
+ android.hardware.common.NativeHandle nativeBlock;
+ android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..7b3005e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Block {
+ int index;
+ android.hardware.media.c2.Params meta;
+ android.hardware.common.NativeHandle fence;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..b632932
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Buffer {
+ android.hardware.media.c2.Params info;
+ android.hardware.media.c2.Block[] blocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..909476c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldDescriptor {
+ android.hardware.media.c2.FieldId fieldId;
+ android.hardware.media.c2.FieldDescriptor.Type type;
+ int structIndex;
+ int extent;
+ String name;
+ android.hardware.media.c2.FieldDescriptor.NamedValue[] namedValues;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ NO_INIT = 0,
+ INT32,
+ UINT32,
+ CNTR32,
+ INT64,
+ UINT64,
+ CNTR64,
+ FLOAT,
+ STRING = 0x100,
+ BLOB,
+ STRUCT = 0x20000,
+ }
+ @VintfStability
+ parcelable NamedValue {
+ String name;
+ long value;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..935b85d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldId {
+ int offset;
+ int sizeBytes;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..69060be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.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.media.c2;
+@VintfStability
+union FieldSupportedValues {
+ boolean empty;
+ android.hardware.media.c2.ValueRange range;
+ long[] values;
+ long[] flags;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..6a5fbe2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+ android.hardware.media.c2.ParamField field;
+ android.hardware.media.c2.FieldSupportedValuesQuery.Type type;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ POSSIBLE = 0,
+ CURRENT,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..187e3eb
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+ android.hardware.media.c2.Status status;
+ android.hardware.media.c2.FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..07bfb72
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FrameData {
+ int flags;
+ android.hardware.media.c2.WorkOrdinal ordinal;
+ android.hardware.media.c2.Buffer[] buffers;
+ android.hardware.media.c2.Params configUpdate;
+ android.hardware.media.c2.InfoBuffer[] infoBuffers;
+ const int DROP_FRAME = (1 << 0) /* 1 */;
+ const int END_OF_STREAM = (1 << 1) /* 2 */;
+ const int DISCARD_FRAME = (1 << 2) /* 4 */;
+ const int FLAG_INCOMPLETE = (1 << 3) /* 8 */;
+ const int CODEC_CONFIG = (1 << 31) /* -2147483648 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..1af66d0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.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.media.c2;
+@VintfStability
+interface IComponent {
+ android.hardware.common.NativeHandle configureVideoTunnel(in int avSyncHwId);
+ android.hardware.media.c2.IComponent.BlockPool createBlockPool(in int allocatorId);
+ void destroyBlockPool(in long blockPoolId);
+ void drain(in boolean withEos);
+ android.hardware.media.c2.WorkBundle flush();
+ android.hardware.media.c2.IComponentInterface getInterface();
+ void queue(in android.hardware.media.c2.WorkBundle workBundle);
+ void release();
+ void reset();
+ void setDecoderOutputAllocator(in android.hardware.media.c2.IGraphicBufferAllocator allocator);
+ void start();
+ void stop();
+ parcelable BlockPool {
+ long blockPoolId;
+ android.hardware.media.c2.IConfigurable configurable;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..2350dae
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IComponentInterface {
+ android.hardware.media.c2.IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..f6f2a63
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.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.media.c2;
+@VintfStability
+interface IComponentListener {
+ oneway void onError(in android.hardware.media.c2.Status status, in int errorCode);
+ oneway void onFramesRendered(in android.hardware.media.c2.IComponentListener.RenderedFrame[] renderedFrames);
+ oneway void onInputBuffersReleased(in android.hardware.media.c2.IComponentListener.InputBuffer[] inputBuffers);
+ oneway void onTripped(in android.hardware.media.c2.SettingResult[] settingResults);
+ oneway void onWorkDone(in android.hardware.media.c2.WorkBundle workBundle);
+ @VintfStability
+ parcelable InputBuffer {
+ long frameIndex;
+ int arrayIndex;
+ }
+ @VintfStability
+ parcelable RenderedFrame {
+ long bufferQueueId;
+ int slotId;
+ long timestampNs;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..d1b5915
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IComponentStore {
+ void copyBuffer(in android.hardware.media.c2.Buffer src, in android.hardware.media.c2.Buffer dst);
+ android.hardware.media.c2.IComponent createComponent(in String name, in android.hardware.media.c2.IComponentListener listener, in android.hardware.media.bufferpool2.IClientManager pool);
+ android.hardware.media.c2.IComponentInterface createInterface(in String name);
+ android.hardware.media.c2.IConfigurable getConfigurable();
+ android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+ android.hardware.media.c2.StructDescriptor[] getStructDescriptors(in int[] indices);
+ android.hardware.media.c2.IComponentStore.ComponentTraits[] listComponents();
+ @VintfStability
+ parcelable ComponentTraits {
+ String name;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Domain domain;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Kind kind;
+ int rank;
+ String mediaType;
+ String[] aliases;
+ @Backing(type="int") @VintfStability
+ enum Kind {
+ OTHER = 0,
+ DECODER,
+ ENCODER,
+ }
+ @Backing(type="int") @VintfStability
+ enum Domain {
+ OTHER = 0,
+ VIDEO,
+ AUDIO,
+ IMAGE,
+ }
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..32f5abd
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+interface IConfigurable {
+ android.hardware.media.c2.IConfigurable.ConfigResult config(in android.hardware.media.c2.Params inParams, in boolean mayBlock);
+ int getId();
+ String getName();
+ android.hardware.media.c2.Params query(in int[] indices, in boolean mayBlock);
+ android.hardware.media.c2.ParamDescriptor[] querySupportedParams(in int start, in int count);
+ android.hardware.media.c2.FieldSupportedValuesQueryResult[] querySupportedValues(in android.hardware.media.c2.FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+ @VintfStability
+ parcelable ConfigResult {
+ android.hardware.media.c2.Params params;
+ android.hardware.media.c2.SettingResult[] failures;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
new file mode 100644
index 0000000..da3d5ff
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+interface IGraphicBufferAllocator {
+ android.hardware.media.c2.IGraphicBufferAllocator.Allocation allocate(in android.hardware.media.c2.IGraphicBufferAllocator.Description desc);
+ boolean deallocate(in long id);
+ android.hardware.media.c2.IGraphicBufferAllocator.WaitableFds getWaitableFds();
+ parcelable Allocation {
+ android.hardware.HardwareBuffer buffer;
+ ParcelFileDescriptor fence;
+ }
+ parcelable Description {
+ int width;
+ int height;
+ int format;
+ long usage;
+ }
+ parcelable WaitableFds {
+ ParcelFileDescriptor allocEvent;
+ ParcelFileDescriptor statusEvent;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..94cd77d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable InfoBuffer {
+ int index;
+ android.hardware.media.c2.Buffer buffer;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..6f0ac50
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable ParamDescriptor {
+ int index;
+ int attrib;
+ String name;
+ int[] dependencies;
+ const int ATTRIBUTE_REQUIRED = (1 << 0) /* 1 */;
+ const int ATTRIBUTE_PERSISTENT = (1 << 1) /* 2 */;
+ const int ATTRIBUTE_STRICT = (1 << 2) /* 4 */;
+ const int ATTRIBUTE_READ_ONLY = (1 << 3) /* 8 */;
+ const int ATTRIBUTE_HIDDEN = (1 << 4) /* 16 */;
+ const int ATTRIBUTE_INTERNAL = (1 << 5) /* 32 */;
+ const int ATTRIBUTE_CONST = (1 << 6) /* 64 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..13d2522
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamField {
+ int index;
+ android.hardware.media.c2.FieldId fieldId;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..5a2821c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamFieldValues {
+ android.hardware.media.c2.ParamField paramOrField;
+ android.hardware.media.c2.FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..7d363c0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Params {
+ byte[] params;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..07fc1f3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.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.media.c2;
+@VintfStability
+parcelable SettingResult {
+ android.hardware.media.c2.SettingResult.Failure failure;
+ android.hardware.media.c2.ParamFieldValues field;
+ android.hardware.media.c2.ParamFieldValues[] conflicts;
+ @Backing(type="int") @VintfStability
+ enum Failure {
+ BAD_TYPE,
+ BAD_PORT,
+ BAD_INDEX,
+ READ_ONLY,
+ MISMATCH,
+ BAD_VALUE,
+ CONFLICT,
+ UNSUPPORTED,
+ INFO_BAD_VALUE,
+ INFO_CONFLICT,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..8b430d2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Status {
+ int status;
+ const int OK = 0;
+ const int BAD_VALUE = (-22) /* -22 */;
+ const int BAD_INDEX = (-75) /* -75 */;
+ const int CANNOT_DO = (-2147483646) /* -2147483646 */;
+ const int DUPLICATE = (-17) /* -17 */;
+ const int NOT_FOUND = (-2) /* -2 */;
+ const int BAD_STATE = (-38) /* -38 */;
+ const int BLOCKING = (-9930) /* -9930 */;
+ const int NO_MEMORY = (-12) /* -12 */;
+ const int REFUSED = (-1) /* -1 */;
+ const int TIMED_OUT = (-110) /* -110 */;
+ const int OMITTED = (-74) /* -74 */;
+ const int CORRUPTED = (-2147483648) /* -2147483648 */;
+ const int NO_INIT = (-19) /* -19 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..58268e0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable StructDescriptor {
+ int type;
+ android.hardware.media.c2.FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..db71ce0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ValueRange {
+ long min;
+ long max;
+ long step;
+ long num;
+ long denom;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..a534348
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Work {
+ byte[] chainInfo;
+ android.hardware.media.c2.FrameData input;
+ android.hardware.media.c2.Worklet[] worklets;
+ int workletsProcessed;
+ android.hardware.media.c2.Status result;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..84708a8
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable WorkBundle {
+ android.hardware.media.c2.Work[] works;
+ android.hardware.media.c2.BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..2833df3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable WorkOrdinal {
+ long timestampUs;
+ long frameIndex;
+ long customOrdinal;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..a79abf2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.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.media.c2;
+@VintfStability
+parcelable Worklet {
+ int componentId;
+ byte[] tunings;
+ android.hardware.media.c2.SettingResult[] failures;
+ android.hardware.media.c2.FrameData output;
+}
diff --git a/staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
rename to media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
index 16e7653..8b8b8e0 100644
--- a/staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
@@ -25,6 +25,7 @@
* decoded data, codec-specific data, and other codec-related data are all sent
* in the form of BaseBlocks.
*/
+@VintfStability
union BaseBlock {
/**
* #nativeBlock is the opaque representation of a buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Block.aidl b/media/c2/aidl/android/hardware/media/c2/Block.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Block.aidl
rename to media/c2/aidl/android/hardware/media/c2/Block.aidl
index 4da8490..34aa7b1 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Block.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Block.aidl
@@ -26,6 +26,7 @@
* attributes may differ among `Block` objects that refer to the same
* `BaseBlock` in the same `WorkBundle`.
*/
+@VintfStability
parcelable Block {
/**
* Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
diff --git a/staging/c2/aidl/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Buffer.aidl
rename to media/c2/aidl/android/hardware/media/c2/Buffer.aidl
index fe01b64..d2dcf2d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Buffer.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
@@ -24,6 +24,7 @@
*
* This is a part of @ref FrameData.
*/
+@VintfStability
parcelable Buffer {
/**
* Metadata associated with the buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
similarity index 97%
rename from staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
index 3dd14cd..a2774ec 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
@@ -21,10 +21,12 @@
/**
* Description of a field inside a C2Param structure.
*/
+@VintfStability
parcelable FieldDescriptor {
/**
* Possible types of the field.
*/
+ @VintfStability
@Backing(type="int")
enum Type {
NO_INIT = 0,
@@ -53,6 +55,7 @@
* Named value type. This is used for defining an enum value for a numeric
* type.
*/
+ @VintfStability
parcelable NamedValue {
/**
* Name of the enum value. This must be unique for each enum value in
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldId.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldId.aidl
index c53f7a5..68bf058 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldId.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
@@ -22,6 +22,7 @@
* Within a given C2Param structure, each field is uniquely identified by @ref
* FieldId.
*/
+@VintfStability
parcelable FieldId {
/**
* Offset of the field in bytes.
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
index 5f4ad2a..6c2033b 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -26,6 +26,7 @@
* The intended type of values must be made clear in the context where
* `FieldSupportedValues` is used.
*/
+@VintfStability
union FieldSupportedValues {
/**
* No supported values
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
similarity index 97%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
index 33a8170..bdaaef6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -22,7 +22,9 @@
* Query information for supported values of a field. This is used as input to
* IConfigurable::querySupportedValues().
*/
+@VintfStability
parcelable FieldSupportedValuesQuery {
+ @VintfStability
@Backing(type="int")
enum Type {
/**
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
index 133712a..b5c28c6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -23,6 +23,7 @@
* This structure is used to hold the result from
* IConfigurable::querySupportedValues().
*/
+@VintfStability
parcelable FieldSupportedValuesQueryResult {
/**
* Result of the query. Possible values are
diff --git a/staging/c2/aidl/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/FrameData.aidl
rename to media/c2/aidl/android/hardware/media/c2/FrameData.aidl
index 81c76be..15c1b6d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FrameData.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
@@ -31,6 +31,7 @@
* @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
* standard.
*/
+@VintfStability
parcelable FrameData {
/** List of frame flags */
/**
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
similarity index 94%
rename from staging/c2/aidl/android/hardware/media/c2/IComponent.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponent.aidl
index bea4b70..a9fddbb 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponent.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
@@ -17,12 +17,10 @@
package android.hardware.media.c2;
import android.hardware.common.NativeHandle;
-import android.view.Surface;
-
import android.hardware.media.c2.IComponentInterface;
import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.IGraphicBufferAllocator;
import android.hardware.media.c2.WorkBundle;
-import android.hardware.media.c2.SurfaceSyncObj;
/**
* Interface for an AIDL Codec2 component.
@@ -32,6 +30,7 @@
* All methods in `IComponent` must not block. If a method call cannot be
* completed in a timely manner, it must throw `Status::TIMED_OUT`.
*/
+@VintfStability
interface IComponent {
/**
* The reference object from framwork to HAL C2BlockPool.
@@ -233,23 +232,15 @@
void reset();
/**
- * Starts using a surface for output with a synchronization object
+ * Specify an allocator for decoder output buffer from HAL.
*
- * This method must not block.
- *
- * @param blockPoolId Id of the `C2BlockPool` to be associated with the
- * output surface.
- * @param surface Output surface.
- * @param syncObject synchronization object for buffer allocation between
- * Framework and Component.
- * @throws ServiceSpecificException with one of the following values:
- * - `Status::CANNOT_DO` - The component does not support an output surface.
- * - `Status::REFUSED` - The output surface cannot be accessed.
- * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * The method will be used once during the life-cycle of a codec instance.
+ * @param allocator Decoder output buffer allocator from the client
+ * @throws ServiceSpecificException with one of the following values
+ * - `Status::CANNOT_DO` - The component does not support allocating from the client.
* - `Status::CORRUPTED` - Some unknown error occurred.
*/
- void setOutputSurface(in long blockPoolId, in Surface surface,
- in SurfaceSyncObj syncObject);
+ void setDecoderOutputAllocator(in IGraphicBufferAllocator allocator);
/**
* Starts the component.
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
index 4589115..9db81e6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
@@ -26,6 +26,7 @@
*
* An actual component exposes this interface via IComponent::getInterface().
*/
+@VintfStability
interface IComponentInterface {
/**
* Returns the @ref IConfigurable instance associated to this component
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
index 786c8f1..75500b7 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
@@ -23,11 +23,13 @@
/**
* Callback interface for handling notifications from @ref IComponent.
*/
+@VintfStability
oneway interface IComponentListener {
/**
* Identifying information for an input buffer previously queued to the
* component via IComponent::queue().
*/
+ @VintfStability
parcelable InputBuffer {
/**
* This value comes from `Work::input.ordinal.frameIndex` in a `Work`
@@ -43,6 +45,7 @@
/**
* Information about rendering of a frame to a `Surface`.
*/
+ @VintfStability
parcelable RenderedFrame {
/**
* Id of the `BufferQueue` containing the rendered buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
index d332bd3..1435a7e 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
@@ -34,17 +34,21 @@
* @note This is an extension of version 1.1 of `IComponentStore`. The purpose
* of the extension is to add support for blocking output buffer allocator.
*/
+@VintfStability
interface IComponentStore {
/**
* Component traits.
*/
+ @VintfStability
parcelable ComponentTraits {
+ @VintfStability
@Backing(type="int")
enum Kind {
OTHER = 0,
DECODER,
ENCODER,
}
+ @VintfStability
@Backing(type="int")
enum Domain {
OTHER = 0,
diff --git a/staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
rename to media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
index 9f79576..7fdb825 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
@@ -28,6 +28,7 @@
* This interface must be supported in all states of the owning object, and must
* not change the state of the owning object.
*/
+@VintfStability
interface IConfigurable {
/**
* Return parcelable for config() interface.
@@ -35,6 +36,7 @@
* This includes the successful config settings along with the failure reasons of
* the specified setting.
*/
+ @VintfStability
parcelable ConfigResult {
Params params;
SettingResult[] failures;
diff --git a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
new file mode 100644
index 0000000..1c97214
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.HardwareBuffer;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface for decoder output buffer allocator for HAL process
+ *
+ * A graphic buffer for decoder output is allocated by the interface.
+ */
+@VintfStability
+interface IGraphicBufferAllocator {
+ /**
+ * A graphic buffer allocation.
+ *
+ * buffer is in android.hardware.HardwareBuffer.
+ * fence is provided in order to signal readiness of the buffer I/O inside
+ * underlying Graphics subsystem. This is called a sync fence throughout Android framework.
+ */
+ parcelable Allocation {
+ HardwareBuffer buffer;
+ ParcelFileDescriptor fence;
+ }
+
+ /**
+ * Parameters for a graphic buffer allocation.
+ *
+ * Refer to AHardwareBuffer_Desc(libnativewindow) for details.
+ */
+ parcelable Description {
+ int width;
+ int height;
+ int format;
+ long usage;
+ }
+
+ /**
+ * Allocate a graphic buffer.
+ *
+ * @param desc Allocation parameters.
+ * @return an android.hardware.HardwareBuffer which is basically same to
+ * AHardwareBuffer. If underlying grpahics system is blocked, c2::Status::Blocked
+ * will be returned. In this case getWaitableFds() will return file descriptors which
+ * can be used to construct a waitable object. The waitable object will be notified
+ * when underlying graphics system is unblocked
+ * @throws ServiceSpecificException with one of the following values:
+ * - `c2::Status::BAD_STATE` - The client is not in running states.
+ * - `c2::Status::BLOCKED` - Underlying graphics system is blocked.
+ * - `c2::Status::CORRUPTED` - Some unknown error occurred.
+ */
+ Allocation allocate(in Description desc);
+
+ /**
+ * De-allocate a graphic buffer by graphic buffer's unique id.
+ *
+ * @param id graphic buffer's unique id. See also AHardwareBuffer_getId().
+ * @return {@code true} when de-allocate happened, {@code false} otherwise.
+ */
+ boolean deallocate(in long id);
+
+ /**
+ * Fds for waitable object events.
+ *
+ * Fds are created by eventfd() with semaphore mode.
+ * For allocEvent, An integer counter regarding dequeuable buffer count is maintained
+ * by client using read()/write() to the fd. The fd can be checked whether it is
+ * readable via poll(). When in readable status, the specified counter is positive
+ * so allocate/dequeue can happen.
+ *
+ * For statusEvent, the client can notify further allocation is not feasible.
+ * e.g.) life-cycle of the underlying allocator is ended.
+ *
+ * C2Fence object should be implemented based on this Fds. Thus, C2Fence can return
+ * either by allocation being ready or allocation being infeasible by the client status
+ * change.
+ */
+ parcelable WaitableFds {
+ ParcelFileDescriptor allocEvent;
+ ParcelFileDescriptor statusEvent;
+ }
+
+ /**
+ * Gets waiable file descriptors.
+ *
+ * Use this method once and cache it in order not to create unnecessary duplicated fds.
+ * The returned array will have two fds.
+ *
+ * If many waitable objects based on the same fd are competing, all watiable objects will be
+ * notified. After being notified, they should invoke allocate(). At least one of them can
+ * successfully allocate. Others not having an Allocation will have c2::Status::BLOCKED
+ * as return value. They should wait again via waitable objects based on the fds which are
+ * already returned from this interface.
+ *
+ * @return an fd array which will be wrapped to C2Fence and will be waited for
+ * until allocating is unblocked.
+ */
+ WaitableFds getWaitableFds();
+}
diff --git a/staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
rename to media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
index 7cfabcb..207c4d0 100644
--- a/staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
@@ -23,6 +23,7 @@
*
* This is a part of @ref FrameData.
*/
+@VintfStability
parcelable InfoBuffer {
/**
* A C2Param structure index.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
index 716c07e..84c6acc 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
@@ -21,6 +21,7 @@
*
* @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
*/
+@VintfStability
parcelable ParamDescriptor {
/** The list of bit flags for attrib */
/**
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamField.aidl
index 94f737d..64a46bb 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
@@ -21,6 +21,7 @@
/**
* Reference to a field in a C2Param structure.
*/
+@VintfStability
parcelable ParamField {
/**
* Index of the C2Param structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
index 4bb9a91..7b74c0e 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
@@ -26,6 +26,7 @@
* values object. This structure is used when reporting parameter configuration
* failures and conflicts.
*/
+@VintfStability
parcelable ParamFieldValues {
/**
* Reference to a field or a C2Param structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Params.aidl b/media/c2/aidl/android/hardware/media/c2/Params.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Params.aidl
rename to media/c2/aidl/android/hardware/media/c2/Params.aidl
index 3c1a321..53b512c 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Params.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Params.aidl
@@ -30,6 +30,7 @@
* - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
* - (size - 8) bytes: data of the C2Param object.
*/
+@VintfStability
parcelable Params {
byte[] params;
}
diff --git a/staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl
rename to media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
index a270146..c2b9574 100644
--- a/staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
@@ -22,10 +22,12 @@
* Information describing the reason the parameter settings may fail, or may be
* overridden.
*/
+@VintfStability
parcelable SettingResult {
/**
* Failure code
*/
+ @VintfStability
@Backing(type="int")
enum Failure {
/**
diff --git a/staging/c2/aidl/android/hardware/media/c2/Status.aidl b/media/c2/aidl/android/hardware/media/c2/Status.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Status.aidl
rename to media/c2/aidl/android/hardware/media/c2/Status.aidl
index 660db57..58a2404 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Status.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Status.aidl
@@ -19,6 +19,7 @@
/**
* Common return values for Codec2 operations.
*/
+@VintfStability
parcelable Status {
/**
* Operation completed successfully.
diff --git a/staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
index 5d6d2eb..00359041 100644
--- a/staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
@@ -22,6 +22,7 @@
* Description of a C2Param structure. It consists of an index and a list of
* `FieldDescriptor`s.
*/
+@VintfStability
parcelable StructDescriptor {
/**
* Index of the structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl
rename to media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
index 6707a25..9abcb7d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
@@ -38,6 +38,7 @@
* The division in the formula may truncate the result if the data type of
* these values is an integral type.
*/
+@VintfStability
parcelable ValueRange {
/**
* Lower end of the range (inclusive).
diff --git a/staging/c2/aidl/android/hardware/media/c2/Work.aidl b/media/c2/aidl/android/hardware/media/c2/Work.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/Work.aidl
rename to media/c2/aidl/android/hardware/media/c2/Work.aidl
index 0732479..4b8d696 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Work.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Work.aidl
@@ -34,6 +34,7 @@
*
* `Work` is a part of @ref WorkBundle.
*/
+@VintfStability
parcelable Work {
/**
* Additional work chain info not part of this work.
diff --git a/staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
rename to media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
index 79b4cdb..2125fda 100644
--- a/staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
@@ -35,6 +35,7 @@
* Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
* data transferred over an IPC.
*/
+@VintfStability
parcelable WorkBundle {
/**
* A list of Work items.
diff --git a/staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
rename to media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
index eb8b244..5708a90 100644
--- a/staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
@@ -31,6 +31,7 @@
* @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
* Codec 2.0 standard.
*/
+@VintfStability
parcelable WorkOrdinal {
/**
* Timestamp in microseconds.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Worklet.aidl
rename to media/c2/aidl/android/hardware/media/c2/Worklet.aidl
index 04c59c1..6b3ceac 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Worklet.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
@@ -28,6 +28,7 @@
* a @ref Work object for each expected output before calling
* IComponent::queue().
*/
+@VintfStability
parcelable Worklet {
/**
* Component id. (Input)
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 7bc65ff..8b7af11 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -23,4 +23,8 @@
"android.hidl.base@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index 772e5e6..b93c80c 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -21,4 +21,8 @@
"android.hidl.base@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 2b83d39..63e0f61 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -28,4 +28,8 @@
"android.hidl.safe_union@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index aa8fc39..c343802 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -29,4 +29,8 @@
"android.hidl.safe_union@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 82c8a0d..a4fab55 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -126,8 +126,8 @@
*
* o The HMAC field must validate correctly.
*
- * o The challenge field in the auth token must contain the challenge value contained in the
- * BeginResult returned from IKeyMintDevice::begin().
+ * o The challenge field in the timestamp token must contain the challenge value contained in
+ * the BeginResult returned from IKeyMintDevice::begin().
*
* The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
* auth token to be valid, all of the following has to be true:
@@ -139,9 +139,6 @@
*
* o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
*
- * o The challenge field in the auth token must contain the challenge value contained in the
- * BeginResult returned from IKeyMintDevice::begin().
- *
* o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
* than the provided secure timestamp.
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index a4d0302..0568ae6 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,12 +1,12 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.security.keymint</name>
- <version>2</version>
+ <version>3</version>
<fqname>IKeyMintDevice/default</fqname>
</hal>
<hal format="aidl">
<name>android.hardware.security.keymint</name>
- <version>2</version>
+ <version>3</version>
<fqname>IRemotelyProvisionedComponent/default</fqname>
</hal>
</manifest>
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 6d289ec..0499079 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -82,7 +82,7 @@
string imei = ::android::base::Trim(out[0]);
if (imei.compare("null") == 0) {
- LOG(ERROR) << "Error in getting IMEI from Telephony service: value is null. Cmd: " << cmd;
+ LOG(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: " << cmd;
return "";
}
@@ -120,6 +120,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
ASSERT_GT(attest_key_cert_chain.size(), 0);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -141,8 +142,7 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
-
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -174,8 +174,7 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
-
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -207,6 +206,7 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ KeyBlobDeleter attested_deleter3(keymint_, attested_key_blob);
// The returned key characteristics will include CREATION_DATETIME (checked below)
// in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
@@ -214,9 +214,6 @@
// any SecurityLevel::KEYSTORE characteristics).
CheckCharacteristics(attested_key_blob, attested_key_characteristics);
- CheckedDeleteKey(&attested_key_blob);
- CheckedDeleteKey(&attest_key.keyBlob);
-
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -308,6 +305,7 @@
if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
EXPECT_GT(attest_key_cert_chain.size(), 1);
verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -344,9 +342,7 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
-
- CheckedDeleteKey(&attested_key_blob);
- CheckedDeleteKey(&attest_key.keyBlob);
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -376,6 +372,7 @@
const int chain_size = 6;
vector<vector<uint8_t>> key_blob_list(chain_size);
vector<vector<Certificate>> cert_chain_list(chain_size);
+ vector<KeyBlobDeleter> deleters;
for (int i = 0; i < chain_size; i++) {
string sub = "attest key chaining ";
@@ -412,6 +409,7 @@
if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
}
ASSERT_EQ(ErrorCode::OK, result);
+ deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -437,10 +435,6 @@
EXPECT_GT(cert_chain_list[i].size(), i + 1);
verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
}
-
- for (int i = 0; i < chain_size; i++) {
- CheckedDeleteKey(&key_blob_list[i]);
- }
}
/*
@@ -453,6 +447,7 @@
const int chain_size = 6;
vector<vector<uint8_t>> key_blob_list(chain_size);
vector<vector<Certificate>> cert_chain_list(chain_size);
+ vector<KeyBlobDeleter> deleters;
for (int i = 0; i < chain_size; i++) {
string sub = "Ec attest key chaining ";
@@ -489,6 +484,7 @@
if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
}
ASSERT_EQ(ErrorCode::OK, result);
+ deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -514,10 +510,6 @@
EXPECT_GT(cert_chain_list[i].size(), i + 1);
verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
}
-
- for (int i = 0; i < chain_size; i++) {
- CheckedDeleteKey(&key_blob_list[i]);
- }
}
/*
@@ -557,6 +549,7 @@
const int chain_size = 6;
vector<vector<uint8_t>> key_blob_list(chain_size);
vector<vector<Certificate>> cert_chain_list(chain_size);
+ vector<KeyBlobDeleter> deleters;
for (int i = 0; i < chain_size; i++) {
string sub = "Alt attest key chaining ";
@@ -607,6 +600,7 @@
if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
}
ASSERT_EQ(ErrorCode::OK, result);
+ deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -632,10 +626,6 @@
EXPECT_GT(cert_chain_list[i].size(), i + 1);
verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
}
-
- for (int i = 0; i < chain_size; i++) {
- CheckedDeleteKey(&key_blob_list[i]);
- }
}
TEST_P(AttestKeyTest, MissingChallenge) {
@@ -653,6 +643,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain)) << "Failed on size " << size;
@@ -681,8 +672,6 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
-
- CheckedDeleteKey(&attest_key.keyBlob);
}
}
@@ -700,6 +689,7 @@
AuthorizationSetBuilder().EcdsaKey(curve).AttestKey().SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
ASSERT_GT(attest_key_cert_chain.size(), 0);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -721,9 +711,9 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
ASSERT_GT(attested_key_cert_chain.size(), 0);
- CheckedDeleteKey(&attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -752,10 +742,9 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
ASSERT_GT(attested_key_cert_chain.size(), 0);
- CheckedDeleteKey(&attested_key_blob);
- CheckedDeleteKey(&attest_key.keyBlob);
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -825,6 +814,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
ASSERT_GT(attest_key_cert_chain.size(), 0);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -891,8 +881,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
-
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -906,7 +895,6 @@
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
}
- CheckedDeleteKey(&attest_key.keyBlob);
}
TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
@@ -921,6 +909,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
ASSERT_GT(attest_key_cert_chain.size(), 0);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -963,7 +952,6 @@
&attested_key_characteristics, &attested_key_cert_chain);
device_id_attestation_check_acceptable_error(invalid_tag.tag, result);
}
- CheckedDeleteKey(&attest_key.keyBlob);
}
TEST_P(AttestKeyTest, SecondIMEIAttestationIDSuccess) {
@@ -994,6 +982,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
EXPECT_EQ(attest_key_cert_chain.size(), 1);
EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
@@ -1022,8 +1011,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
-
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -1038,8 +1026,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
-
- CheckedDeleteKey(&attest_key.keyBlob);
}
TEST_P(AttestKeyTest, MultipleIMEIAttestationIDSuccess) {
@@ -1076,6 +1062,7 @@
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
+ KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
EXPECT_EQ(attest_key_cert_chain.size(), 1);
EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
@@ -1101,8 +1088,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
-
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -1120,8 +1106,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
-
- CheckedDeleteKey(&attest_key.keyBlob);
}
INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
index 78c88f4..290e8fc 100644
--- a/security/keymint/aidl/vts/functional/AuthTest.cpp
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -93,17 +93,21 @@
void TearDown() {
if (gk_ == nullptr) return;
gk_->deleteUser(uid_);
+ if (alt_uid_ != 0) {
+ gk_->deleteUser(alt_uid_);
+ }
}
bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
- std::optional<GatekeeperEnrollResponse> doEnroll(const std::vector<uint8_t>& newPwd,
+ std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid,
+ const std::vector<uint8_t>& newPwd,
const std::vector<uint8_t>& curHandle = {},
const std::vector<uint8_t>& curPwd = {}) {
if (gk_ != nullptr) {
while (true) {
GatekeeperEnrollResponse rsp;
- Status status = gk_->enroll(uid_, curHandle, curPwd, newPwd, &rsp);
+ Status status = gk_->enroll(uid, curHandle, curPwd, newPwd, &rsp);
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
sleep(1);
@@ -120,7 +124,7 @@
while (true) {
HidlGatekeeperResponse rsp;
auto status = hidl_gk_->enroll(
- uid_, curHandle, curPwd, newPwd,
+ uid, curHandle, curPwd, newPwd,
[&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
if (!status.isOk()) {
GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
@@ -155,20 +159,23 @@
}
}
- std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd,
+ std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid, const string& newPwd,
const std::vector<uint8_t>& curHandle = {},
const string& curPwd = {}) {
- return doEnroll(std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
+ return doEnroll(uid, std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
}
+ std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd) {
+ return doEnroll(uid_, newPwd);
+ }
- std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
+ std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
const std::vector<uint8_t>& handle,
const std::vector<uint8_t>& pwd) {
if (gk_ != nullptr) {
while (true) {
GatekeeperVerifyResponse rsp;
- Status status = gk_->verify(uid_, challenge, handle, pwd, &rsp);
+ Status status = gk_->verify(uid, challenge, handle, pwd, &rsp);
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
sleep(1);
@@ -185,7 +192,7 @@
while (true) {
HidlGatekeeperResponse rsp;
auto status = hidl_gk_->verify(
- uid_, challenge, handle, pwd,
+ uid, challenge, handle, pwd,
[&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
if (!status.isOk()) {
GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
@@ -220,10 +227,15 @@
return std::nullopt;
}
}
+ std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
+ const std::vector<uint8_t>& handle,
+ const string& pwd) {
+ return doVerify(uid, challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+ }
std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
const std::vector<uint8_t>& handle,
const string& pwd) {
- return doVerify(challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+ return doVerify(uid_, challenge, handle, pwd);
}
// Variants of the base class methods but with authentication information included.
@@ -268,6 +280,13 @@
return plaintext;
}
+ string SignMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params,
+ const HardwareAuthToken& hat) {
+ SCOPED_TRACE("SignMessage");
+ return ProcessMessage(key_blob, KeyPurpose::SIGN, message, in_params, out_params, hat);
+ }
+
protected:
std::shared_ptr<IGatekeeper> gk_;
sp<IHidlGatekeeper> hidl_gk_;
@@ -275,6 +294,8 @@
string password_;
uint32_t uid_;
int64_t sid_;
+ uint32_t alt_uid_;
+ int64_t alt_sid_;
std::vector<uint8_t> handle_;
};
@@ -347,6 +368,116 @@
}
}
+// Test use of a key that requires user-authentication within recent history, but where
+// the `TimestampToken` provided to the device is unrelated to the in-progress operation.
+TEST_P(AuthTest, TimeoutAuthenticationIncorrectTimestampToken) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+ if (!timestamp_token_required_) {
+ GTEST_SKIP() << "Test only applies to devices with no secure clock";
+ }
+ if (clock_ == nullptr) {
+ GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+ }
+
+ // Create an AES key that requires authentication within the last 3 seconds.
+ const uint32_t timeout_secs = 3;
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
+ .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Verify to get a HAT, arbitrary challenge.
+ const uint64_t challenge = 42;
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ // KeyMint implementation has no clock, so only detects timeout via timestamp token provided
+ // on update()/finish(). However, for this test we ensure that that the timestamp token has a
+ // *different* challenge value.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
+
+ secureclock::TimeStampToken time_token;
+ EXPECT_EQ(ErrorCode::OK,
+ GetReturnErrorCode(clock_->generateTimeStamp(challenge_ + 1, &time_token)));
+ string output;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &output, hat, time_token));
+}
+
+// Test use of a key with multiple USER_SECURE_ID values. For variety, use an EC signing key
+// generated with attestation.
+TEST_P(AuthTest, TimeoutAuthenticationMultiSid) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+ if (timestamp_token_required_ && clock_ == nullptr) {
+ GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+ }
+
+ // Enroll a password for a second user.
+ alt_uid_ = 20001;
+ const string alt_password = "correcthorsebatterystaple2";
+ std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+ ASSERT_TRUE(rsp.has_value());
+ alt_sid_ = rsp->secureUserId;
+ const std::vector<uint8_t> alt_handle = rsp->data;
+
+ // Create an attested EC key that requires authentication within the last 3 seconds from either
+ // secure ID. Also allow any authenticator type.
+ const uint32_t timeout_secs = 3;
+ auto builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity()
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("app_id")
+ .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY)
+ .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Verify first user to get a HAT that should work.
+ const uint64_t challenge = 42;
+ const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ AuthorizationSet out_params;
+ const string signature = SignMessage(keyblob, message, params, &out_params, hat.value());
+
+ // Verify second user to get a HAT that should work.
+ const uint64_t alt_challenge = 43;
+ const std::optional<HardwareAuthToken> alt_hat =
+ doVerify(alt_uid_, alt_challenge, alt_handle, alt_password);
+ ASSERT_TRUE(alt_hat.has_value());
+ EXPECT_EQ(alt_hat->userId, alt_sid_);
+
+ const string alt_signature =
+ SignMessage(keyblob, message, params, &out_params, alt_hat.value());
+}
+
// Test use of a key that requires an auth token for each action on the operation, with
// a per-operation challenge value included.
TEST_P(AuthTest, AuthPerOperation) {
@@ -407,6 +538,93 @@
Finish(message, {} /* signature */, &ciphertext, hat.value()));
}
+// Test use of a key that requires an auth token for each action on the operation, with
+// a per-operation challenge value included, with multiple secure IDs allowed.
+TEST_P(AuthTest, AuthPerOperationMultiSid) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+
+ // Enroll a password for a second user.
+ alt_uid_ = 20001;
+ const string alt_password = "correcthorsebatterystaple2";
+ std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+ ASSERT_TRUE(rsp.has_value());
+ alt_sid_ = rsp->secureUserId;
+ const std::vector<uint8_t> alt_handle = rsp->data;
+
+ // Create an AES key that requires authentication per-action.
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Get a HAT for first user with the challenge from an in-progress operation.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge_, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
+
+ // Get a HAT for second user with the challenge from an in-progress operation.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> alt_hat =
+ doVerify(alt_uid_, challenge_, alt_handle, alt_password);
+ ASSERT_TRUE(alt_hat.has_value());
+ EXPECT_EQ(alt_hat->userId, alt_sid_);
+ string alt_ciphertext;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, alt_hat.value()));
+}
+
+// Test use of a key that requires an auth token for each action on the operation, but
+// which gets passed a HAT of the wrong type
+TEST_P(AuthTest, AuthPerOperationWrongAuthType) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+
+ // Create an AES key that requires authentication per-action, but with no valid authenticator
+ // types.
+ auto builder =
+ AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::FINGERPRINT);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Get a HAT with the challenge from an in-progress operation.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ // Should fail because auth type doesn't (can't) match.
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &ciphertext, hat.value()));
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(AuthTest);
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
index 6892442..7ccd246 100644
--- a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
@@ -36,11 +36,14 @@
//
// adb push keymint-blobs /data/local/tmp/keymint-blobs
//
-// 5) Run the "*After*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
-// pointing to the directory with the keyblobs:
+// 5) Run the "*After*" subset of these tests, with the following command-line arguments
+// `--keyblob_dir <dir>`: pointing to the directory with the keyblobs.
+// `--expect_upgrade {yes|no}` (Optional): To specify if users expect an upgrade on the keyBlobs,
+// will be "yes" by default.
//
// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*After*" \
-// --keyblob_dir /data/local/tmp/keymint-blobs
+// --keyblob_dir /data/local/tmp/keymint-blobs \
+// --expect_upgrade {yes|no}
//
// (Note that this skips the `CreateKeyBlobs` test, which would otherwise replace the saved
// keyblobs with freshly generated ones.).
@@ -71,6 +74,9 @@
namespace {
+// Names for individual key types to create and use. Note that some the names
+// induce specific behaviour, as indicated by the functions below.
+
std::vector<std::string> keyblob_names_tee = {
"aes-key", "aes-key-rr", "des-key", "hmac-key",
"rsa-key", "p256-key", "ed25519-key", "x25519-key",
@@ -84,6 +90,11 @@
"hmac-key", "rsa-key", "p256-key",
"rsa-attest-key", "p256-attest-key"};
+// Helper functions to detect particular key types based on the name.
+bool requires_attest_key(const std::string& name) {
+ return name.find("-attest-key") != std::string::npos;
+}
+
bool requires_rr(const std::string& name) {
return name.find("-rr") != std::string::npos;
}
@@ -207,6 +218,11 @@
}
for (std::string name : keyblob_names()) {
+ if (requires_attest_key(name) && shouldSkipAttestKeyTest()) {
+ std::cerr << "Skipping variant '" << name
+ << "' which requires ATTEST_KEY support that has been waivered\n";
+ continue;
+ }
for (bool with_hidden : {false, true}) {
std::string app_id;
std::string app_data;
@@ -355,6 +371,11 @@
}};
for (std::string name : keyblob_names()) {
+ if (requires_attest_key(name) && shouldSkipAttestKeyTest()) {
+ std::cerr << "Skipping variant '" << name
+ << "' which requires ATTEST_KEY support that has been waivered\n";
+ continue;
+ }
auto entry = keys_info.find(name);
ASSERT_NE(entry, keys_info.end()) << "no builder for " << name;
auto builder = entry->second;
@@ -408,12 +429,18 @@
//
// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UpgradeKeyBlobsAfter*" \
// --keyblob_dir /data/local/tmp/keymint-blobs
+// --expect_upgrade {yes|no}
//
// - this replaces the keyblob contents in that directory; if needed, save the upgraded keyblobs
// with:
// adb pull /data/local/tmp/keymint-blobs/
TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsAfter) {
- UpgradeKeyBlobs(/* expectUpgrade= */ true);
+ bool expectUpgrade = true; // this test expects upgrade to happen by default
+ if (expect_upgrade.has_value() && expect_upgrade == false) {
+ std::cout << "Not expecting key upgrade due to --expect_upgrade no\n";
+ expectUpgrade = false;
+ }
+ UpgradeKeyBlobs(expectUpgrade);
}
// To run this test:
@@ -432,6 +459,11 @@
}
for (std::string name : keyblob_names()) {
+ if (requires_attest_key(name) && shouldSkipAttestKeyTest()) {
+ std::cerr << "Skipping variant '" << name
+ << "' which requires ATTEST_KEY support that has been waivered\n";
+ continue;
+ }
for (bool with_hidden : {false, true}) {
auto builder = AuthorizationSetBuilder();
if (with_hidden) {
@@ -531,7 +563,7 @@
// Both ways round should agree.
EXPECT_EQ(keymint_data, local_data);
- } else if (name.find("-attest-key") != std::string::npos) {
+ } else if (requires_attest_key(name)) {
// Covers rsa-attest-key, p256-attest-key, ed25519-attest-key.
// Use attestation key to sign RSA signing key
@@ -551,7 +583,7 @@
.SetDefaultValidity(),
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
- CheckedDeleteKey(&attested_key_blob);
+ KeyBlobDeleter(keymint_, attested_key_blob);
} else {
FAIL() << "Unexpected name: " << name;
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index a8b1d06..9f8593c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -71,6 +71,11 @@
// additional overhead, for the digest algorithmIdentifier required by PKCS#1.
const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
+size_t count_tag_invalid_entries(const std::vector<KeyParameter>& authorizations) {
+ return std::count_if(authorizations.begin(), authorizations.end(),
+ [](const KeyParameter& e) -> bool { return e.tag == Tag::INVALID; });
+}
+
typedef KeyMintAidlTestBase::KeyData KeyData;
// Predicate for testing basic characteristics validity in generation or import.
bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
@@ -84,6 +89,8 @@
return false;
}
+ EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+
// Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
@@ -174,6 +181,18 @@
bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
bool KeyMintAidlTestBase::dump_Attestations = false;
std::string KeyMintAidlTestBase::keyblob_dir;
+std::optional<bool> KeyMintAidlTestBase::expect_upgrade = std::nullopt;
+
+KeyBlobDeleter::~KeyBlobDeleter() {
+ if (key_blob_.empty()) {
+ return;
+ }
+ Status result = keymint_->deleteKey(key_blob_);
+ key_blob_.clear();
+ EXPECT_TRUE(result.isOk()) << result.getServiceSpecificError() << "\n";
+ ErrorCode rc = GetReturnErrorCode(result);
+ EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED) << result << "\n";
+}
uint32_t KeyMintAidlTestBase::boot_patch_level(
const vector<KeyCharacteristics>& key_characteristics) {
@@ -228,16 +247,6 @@
return version >= 2;
}
-ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
- if (result.isOk()) return ErrorCode::OK;
-
- if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
- return static_cast<ErrorCode>(result.getServiceSpecificError());
- }
-
- return ErrorCode::UNKNOWN_ERROR;
-}
-
void KeyMintAidlTestBase::InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint) {
ASSERT_NE(keyMint, nullptr);
keymint_ = std::move(keyMint);
@@ -512,13 +521,9 @@
return GetReturnErrorCode(result);
}
-void KeyMintAidlTestBase::CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
- ErrorCode result = DeleteKey(key_blob, keep_key_blob);
- EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
-}
-
void KeyMintAidlTestBase::CheckedDeleteKey() {
- CheckedDeleteKey(&key_blob_);
+ ErrorCode result = DeleteKey(&key_blob_, /* keep_key_blob = */ false);
+ EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
}
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
@@ -1605,7 +1610,8 @@
auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr);
if (res <= 0) return false;
- const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"};
+ const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P",
+ "SM4450", "SM7450", "SM6450"};
for (const string model : allowed_soc_models) {
if (model.compare(buffer.data()) == 0) {
@@ -1617,17 +1623,39 @@
return false;
}
-// Skip the test if all the following conditions hold:
-// 1. ATTEST_KEY feature is disabled
-// 2. STRONGBOX is enabled
-// 3. The device is running one of the chipsets that have received a waiver
-// allowing it to be launched with Android S (or later) with Keymaster 4.0
+// Indicate whether a test that involves use of the ATTEST_KEY feature should be
+// skipped.
+//
+// In general, every KeyMint implementation should support ATTEST_KEY;
+// however, there is a waiver for some specific devices that ship with a
+// combination of Keymaster/StrongBox and KeyMint/TEE. On these devices, the
+// ATTEST_KEY feature is disabled in the KeyMint/TEE implementation so that
+// the device has consistent ATTEST_KEY behavior (ie. UNIMPLEMENTED) across both
+// HAL implementations.
+//
+// This means that a test involving ATTEST_KEY test should be skipped if all of
+// the following conditions hold:
+// 1. The device is running one of the chipsets that have received a waiver
+// allowing it to be launched with Android S or T with Keymaster 4.0
// in StrongBox
-void KeyMintAidlTestBase::skipAttestKeyTest(void) const {
+// 2. The device has a STRONGBOX implementation present.
+// 3. ATTEST_KEY feature is advertised as disabled.
+//
+// Note that in this scenario, ATTEST_KEY tests should be skipped for both
+// the StrongBox implementation (which is Keymaster, therefore not tested here)
+// and for the TEE implementation (which is adjusted to return UNIMPLEMENTED
+// specifically for this waiver).
+bool KeyMintAidlTestBase::shouldSkipAttestKeyTest(void) const {
// Check the chipset first as that doesn't require a round-trip to Package Manager.
- if (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() &&
- is_attest_key_feature_disabled()) {
- GTEST_SKIP() << "Test is not applicable";
+ return (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() &&
+ is_attest_key_feature_disabled());
+}
+
+// Skip a test that involves use of the ATTEST_KEY feature in specific configurations
+// where ATTEST_KEY is not supported (for either StrongBox or TEE).
+void KeyMintAidlTestBase::skipAttestKeyTest(void) const {
+ if (shouldSkipAttestKeyTest()) {
+ GTEST_SKIP() << "Test using ATTEST_KEY is not applicable on waivered device";
}
}
@@ -1984,6 +2012,16 @@
return AssertionSuccess();
}
+ErrorCode GetReturnErrorCode(const Status& result) {
+ if (result.isOk()) return ErrorCode::OK;
+
+ if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ return static_cast<ErrorCode>(result.getServiceSpecificError());
+ }
+
+ return ErrorCode::UNKNOWN_ERROR;
+}
+
X509_Ptr parse_cert_blob(const vector<uint8_t>& blob) {
const uint8_t* p = blob.data();
return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
@@ -2033,6 +2071,27 @@
return retval;
}
+void assert_mgf_digests_present_in_key_characteristics(
+ const vector<KeyCharacteristics>& key_characteristics,
+ std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests) {
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ for (auto digest : expected_mgf_digests) {
+ ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+ }
+}
+
+bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
+ android::hardware::security::keymint::Digest expected_mgf_digest) {
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ return auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, expected_mgf_digest);
+}
+
namespace {
void check_cose_key(const vector<uint8_t>& data, bool testMode) {
@@ -2155,30 +2214,26 @@
// Check the error code from an attempt to perform device ID attestation with an invalid value.
void device_id_attestation_check_acceptable_error(Tag tag, const ErrorCode& result) {
- // Standard/default error code for ID mismatch.
if (result == ErrorCode::CANNOT_ATTEST_IDS) {
- return;
- }
-
- // Depending on the situation, other error codes may be acceptable. First, allow older
- // implementations to use INVALID_TAG.
- if (result == ErrorCode::INVALID_TAG) {
+ // Standard/default error code for ID mismatch.
+ } else if (result == ErrorCode::INVALID_TAG) {
+ // Depending on the situation, other error codes may be acceptable. First, allow older
+ // implementations to use INVALID_TAG.
ASSERT_FALSE(get_vsr_api_level() > __ANDROID_API_T__)
<< "It is a specification violation for INVALID_TAG to be returned due to ID "
<< "mismatch in a Device ID Attestation call. INVALID_TAG is only intended to "
<< "be used for a case where updateAad() is called after update(). As of "
<< "VSR-14, this is now enforced as an error.";
- }
-
- // If the device is not a phone, it will not have IMEI/MEID values available. Allow
- // ATTESTATION_IDS_NOT_PROVISIONED in this case.
- if (result == ErrorCode::ATTESTATION_IDS_NOT_PROVISIONED) {
+ } else if (result == ErrorCode::ATTESTATION_IDS_NOT_PROVISIONED) {
+ // If the device is not a phone, it will not have IMEI/MEID values available. Allow
+ // ATTESTATION_IDS_NOT_PROVISIONED in this case.
ASSERT_TRUE((tag == TAG_ATTESTATION_ID_IMEI || tag == TAG_ATTESTATION_ID_MEID ||
tag == TAG_ATTESTATION_ID_SECOND_IMEI))
<< "incorrect error code on attestation ID mismatch";
+ } else {
+ ADD_FAILURE() << "Error code " << result
+ << " returned on attestation ID mismatch, should be CANNOT_ATTEST_IDS";
}
- ADD_FAILURE() << "Error code " << result
- << " returned on attestation ID mismatch, should be CANNOT_ATTEST_IDS";
}
// Check whether the given named feature is available.
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 6318514..8934a57 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -57,6 +57,18 @@
const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key";
const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
+// RAII class to ensure that a keyblob is deleted regardless of how a test exits.
+class KeyBlobDeleter {
+ public:
+ KeyBlobDeleter(const shared_ptr<IKeyMintDevice>& keymint, const vector<uint8_t>& key_blob)
+ : keymint_(keymint), key_blob_(key_blob) {}
+ ~KeyBlobDeleter();
+
+ private:
+ shared_ptr<IKeyMintDevice> keymint_;
+ vector<uint8_t> key_blob_;
+};
+
class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
public:
struct KeyData {
@@ -70,6 +82,8 @@
// Directory to store/retrieve keyblobs, using subdirectories named for the
// KeyMint instance in question (e.g. "./default/", "./strongbox/").
static std::string keyblob_dir;
+ // To specify if users expect an upgrade on the keyBlobs.
+ static std::optional<bool> expect_upgrade;
void SetUp() override;
void TearDown() override {
@@ -92,8 +106,6 @@
bool Curve25519Supported();
- ErrorCode GetReturnErrorCode(const Status& result);
-
ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
vector<KeyCharacteristics>* key_characteristics) {
return GenerateKey(key_desc, std::nullopt /* attest_key */, key_blob, key_characteristics,
@@ -157,7 +169,6 @@
ErrorCode DestroyAttestationIds();
- void CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
void CheckedDeleteKey();
ErrorCode Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
@@ -359,6 +370,7 @@
bool is_attest_key_feature_disabled(void) const;
bool is_strongbox_enabled(void) const;
bool is_chipset_allowed_km4_strongbox(void) const;
+ bool shouldSkipAttestKeyTest(void) const;
void skipAttestKeyTest(void) const;
protected:
@@ -418,6 +430,11 @@
X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
vector<uint8_t> make_name_from_str(const string& name);
+void assert_mgf_digests_present_in_key_characteristics(
+ const vector<KeyCharacteristics>& key_characteristics,
+ std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests);
+bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
+ android::hardware::security::keymint::Digest expected_mgf_digest);
void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
vector<uint8_t>* payload_value);
void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
@@ -429,6 +446,8 @@
::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
bool strict_issuer_check = true);
+ErrorCode GetReturnErrorCode(const Status& result);
+
#define INSTANTIATE_KEYMINT_AIDL_TEST(name) \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(KeyMintAidlTestBase::build_params()), \
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index e99149b..1e61a18 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -693,6 +693,7 @@
builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
}
ASSERT_EQ(ErrorCode::OK, GenerateKey(builder, &key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
@@ -703,8 +704,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::AES));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
}
@@ -877,6 +876,7 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
@@ -887,8 +887,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::TRIPLE_DES));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
}
@@ -924,6 +922,7 @@
.AttestationApplicationId(app_id)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
@@ -934,8 +933,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::TRIPLE_DES));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
}
@@ -1003,6 +1000,7 @@
.Padding(PaddingMode::NONE)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1014,8 +1012,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1139,6 +1135,7 @@
}
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1159,8 +1156,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1214,6 +1209,7 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.SetDefaultValidity(),
attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1240,8 +1236,6 @@
ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
<< "Verification of attested certificate failed "
<< "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1294,6 +1288,7 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.SetDefaultValidity(),
attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1318,8 +1313,6 @@
ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
<< "Verification of attested certificate failed "
<< "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1365,6 +1358,7 @@
}
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
AuthorizationSet auths;
@@ -1405,8 +1399,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
/*
@@ -1437,6 +1429,7 @@
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1452,8 +1445,6 @@
ASSERT_EQ(cert_chain_.size(), 1);
verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1518,6 +1509,7 @@
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1534,8 +1526,6 @@
verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
ASSERT_EQ(cert_chain_.size(), 1);
-
- CheckedDeleteKey(&key_blob);
}
/*
@@ -1556,6 +1546,7 @@
.Authorization(TAG_USAGE_COUNT_LIMIT, 1)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1575,8 +1566,6 @@
}
EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
<< "key usage count limit " << 1U << " missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1625,6 +1614,7 @@
}
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1655,8 +1645,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1726,6 +1714,7 @@
.Digest(Digest::NONE)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1734,8 +1723,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1759,6 +1746,8 @@
.SetDefaultValidity(),
&key_blob, &key_characteristics);
ASSERT_EQ(result, ErrorCode::OK);
+ KeyBlobDeleter deleter(keymint_, key_blob);
+
ASSERT_GT(key_blob.size(), 0U);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -1771,8 +1760,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
-
- CheckedDeleteKey(&key_blob);
}
/*
@@ -1879,6 +1866,7 @@
}
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1897,8 +1885,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -1936,6 +1922,7 @@
.SetDefaultValidity(),
&key_blob, &key_characteristics);
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1954,8 +1941,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
/*
@@ -2024,6 +2009,7 @@
}
}
ASSERT_EQ(result, ErrorCode::OK);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2043,8 +2029,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
// Collection of invalid attestation ID tags.
@@ -2086,7 +2070,8 @@
builder, &key_blob, &key_characteristics);
}
}
- ASSERT_EQ(error, ErrorCode::CANNOT_ATTEST_IDS);
+
+ device_id_attestation_check_acceptable_error(tag.tag, error);
}
}
@@ -2170,6 +2155,7 @@
continue;
}
ASSERT_EQ(result, ErrorCode::OK);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2189,8 +2175,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2345,6 +2329,7 @@
}
}
ASSERT_EQ(result, ErrorCode::OK);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2364,8 +2349,6 @@
ASSERT_EQ(std::search(cert_chain_[0].encodedCertificate.begin(),
cert_chain_[0].encodedCertificate.end(), needle.begin(), needle.end()),
cert_chain_[0].encodedCertificate.end());
-
- CheckedDeleteKey(&key_blob);
}
/*
@@ -2393,6 +2376,7 @@
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -2408,8 +2392,6 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2463,6 +2445,7 @@
.AttestationApplicationId(app_id)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -2478,8 +2461,6 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2521,6 +2502,7 @@
}
}
ASSERT_EQ(ErrorCode::OK, result);
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -2538,8 +2520,6 @@
EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2560,6 +2540,7 @@
.Authorization(TAG_USAGE_COUNT_LIMIT, 1)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -2577,8 +2558,6 @@
}
EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
<< "key usage count limit " << 1U << " missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2710,6 +2689,7 @@
AuthorizationSetBuilder().HmacKey(key_size).Digest(digest).Authorization(
TAG_MIN_MAC_LENGTH, 128),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -2719,8 +2699,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2746,6 +2724,7 @@
.AttestationApplicationId(app_id)
.Authorization(TAG_MIN_MAC_LENGTH, 128),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
ASSERT_EQ(cert_chain_.size(), 0);
@@ -2756,8 +2735,6 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -2779,6 +2756,7 @@
.Authorization(TAG_MIN_MAC_LENGTH, 128)
.Authorization(TAG_USAGE_COUNT_LIMIT, 1),
&key_blob, &key_characteristics));
+ KeyBlobDeleter deleter(keymint_, key_blob);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -2796,8 +2774,6 @@
}
EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
<< "key usage count limit " << 1U << " missing";
-
- CheckedDeleteKey(&key_blob);
}
}
@@ -3119,7 +3095,7 @@
*/
TEST_P(SigningOperationsTest, NoUserConfirmation) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(1024, 65537)
+ .RsaSigningKey(2048, 65537)
.Digest(Digest::NONE)
.Padding(PaddingMode::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -3455,7 +3431,6 @@
* Verifies ECDSA signature/verification for all digests and required curves.
*/
TEST_P(SigningOperationsTest, EcdsaAllDigestsAndCurves) {
-
string message = "1234567890";
string corrupt_message = "2234567890";
for (auto curve : ValidCurves()) {
@@ -3891,6 +3866,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 160),
KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+ KeyBlobDeleter sign_deleter(keymint_, signing_key);
EXPECT_EQ(ErrorCode::OK,
ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -3899,6 +3875,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 160),
KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+ KeyBlobDeleter verify_deleter(keymint_, verification_key);
string message = "This is a message.";
string signature = SignMessage(
@@ -3914,9 +3891,6 @@
// Verification key should work.
VerifyMessage(verification_key, message, signature,
AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
-
- CheckedDeleteKey(&signing_key);
- CheckedDeleteKey(&verification_key);
}
/*
@@ -3937,6 +3911,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 160),
KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+ KeyBlobDeleter sign_deleter(keymint_, signing_key);
EXPECT_EQ(ErrorCode::OK,
ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -3945,6 +3920,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 160),
KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+ KeyBlobDeleter verify_deleter(keymint_, verification_key);
string message = "This is a message.";
string signature = SignMessage(
@@ -3966,9 +3942,6 @@
signature[0] += 1; // Corrupt a signature
EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, signature, &output));
-
- CheckedDeleteKey(&signing_key);
- CheckedDeleteKey(&verification_key);
}
INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
@@ -4754,6 +4727,102 @@
}
}
+/*
+ * ImportKeyTest.RsaOaepMGFDigestSuccess
+ *
+ * Include MGF-Digest explicitly in import key authorization list.
+ * Test should import RSA key with OAEP padding and mgf-digests and verify that imported key
+ * should have the correct characteristics.
+ */
+TEST_P(ImportKeyTest, RsaOaepMGFDigestSuccess) {
+ auto mgf_digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+ size_t key_size = 2048;
+
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .OaepMGFDigest(mgf_digests)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(key_size, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, rsa_2048_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+ CheckCryptoParam(TAG_KEY_SIZE, key_size);
+ CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
+ CheckOrigin();
+
+ // Make sure explicitly specified mgf-digests exist in key characteristics.
+ assert_mgf_digests_present_in_key_characteristics(key_characteristics_, mgf_digests);
+
+ string message = "Hello";
+
+ for (auto digest : mgf_digests) {
+ SCOPED_TRACE(testing::Message() << "digest-" << digest);
+ auto params = AuthorizationSetBuilder()
+ .Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP);
+ string ciphertext1 = LocalRsaEncryptMessage(message, params);
+ if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+ EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+ string ciphertext2 = LocalRsaEncryptMessage(message, params);
+ if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+ EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+ // OAEP randomizes padding so every result should be different (with astronomically high
+ // probability).
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ string plaintext1 = DecryptMessage(ciphertext1, params);
+ EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
+ string plaintext2 = DecryptMessage(ciphertext2, params);
+ EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;
+
+ // Decrypting corrupted ciphertext should fail.
+ size_t offset_to_corrupt = ciphertext1.size() - 1;
+ char corrupt_byte = ~ciphertext1[offset_to_corrupt];
+ ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string result;
+ EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+ EXPECT_EQ(0U, result.size());
+ }
+}
+
+/*
+ * ImportKeyTest.RsaOaepMGFDigestDefaultSuccess
+ *
+ * Don't specify MGF-Digest explicitly in import key authorization list.
+ * Test should import RSA key with OAEP padding and default mgf-digest (SHA1) and
+ * verify that imported key should have the correct characteristics. Default
+ * mgf-digest shouldn't be included in key charecteristics.
+ */
+TEST_P(ImportKeyTest, RsaOaepMGFDigestDefaultSuccess) {
+ size_t key_size = 2048;
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(key_size, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, rsa_2048_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+ CheckCryptoParam(TAG_KEY_SIZE, key_size);
+ CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
+ CheckOrigin();
+
+ // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
+ ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
auto wrapped_key = hex2str(
@@ -5179,16 +5248,19 @@
*/
TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+ auto mgf_digest = Digest::SHA1;
size_t key_size = 2048; // Need largish key for SHA-512 test.
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaEncryptionKey(key_size, 65537)
- .Padding(PaddingMode::RSA_OAEP)
- .Digest(digests)
- .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA1)
- .SetDefaultValidity()));
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(digests)
+ .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+ .SetDefaultValidity()));
+
+ // Make sure explicitly specified mgf-digest exist in key characteristics.
+ ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
string message = "Hello";
@@ -5314,6 +5386,20 @@
.Digest(Digest::SHA_2_256)
.SetDefaultValidity()));
+ std::vector<Digest> mgf1DigestsInAuths;
+ mgf1DigestsInAuths.reserve(digests.size());
+ const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
+ std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
+ if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
+ KeyParameterValue value = param.value;
+ mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
+ }
+ });
+
+ std::sort(digests.begin(), digests.end());
+ std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
+ EXPECT_EQ(digests, mgf1DigestsInAuths);
+
string message = "Hello";
for (auto digest : digests) {
@@ -5368,6 +5454,9 @@
.Digest(Digest::SHA_2_256)
.SetDefaultValidity()));
+ // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
+ ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+
// Do local RSA encryption using the default MGF digest of SHA-1.
string message = "Hello";
auto params =
@@ -5402,14 +5491,19 @@
*/
TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultFail) {
size_t key_size = 2048;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
- .RsaEncryptionKey(key_size, 65537)
- .Padding(PaddingMode::RSA_OAEP)
- .Digest(Digest::SHA_2_256)
- .SetDefaultValidity()));
+ auto mgf_digest = Digest::SHA_2_256;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity()));
+
+ // Make sure explicitly specified mgf-digest exist in key characteristics.
+ ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+ // Make sure default mgf-digest is not included in key characteristics.
+ ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
// Do local RSA encryption using the default MGF digest of SHA-1.
string message = "Hello";
@@ -5433,14 +5527,17 @@
* with incompatible MGF digest.
*/
TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaEncryptionKey(2048, 65537)
- .Padding(PaddingMode::RSA_OAEP)
- .Digest(Digest::SHA_2_256)
- .SetDefaultValidity()));
+ auto mgf_digest = Digest::SHA_2_256;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity()));
+ // Make sure explicitly specified mgf-digest exist in key characteristics.
+ ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+
string message = "Hello World!";
auto params = AuthorizationSetBuilder()
@@ -5457,14 +5554,17 @@
* with unsupported MGF digest.
*/
TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaEncryptionKey(2048, 65537)
- .Padding(PaddingMode::RSA_OAEP)
- .Digest(Digest::SHA_2_256)
- .SetDefaultValidity()));
+ auto mgf_digest = Digest::SHA_2_256;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity()));
+ // Make sure explicitly specified mgf-digest exist in key characteristics.
+ ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+
string message = "Hello World!";
auto params = AuthorizationSetBuilder()
@@ -8497,16 +8597,16 @@
// Early boot keys can be created after early boot.
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+ KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+ KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+ KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+ KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
ASSERT_GT(keyData.blob.size(), 0U);
AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
}
- CheckedDeleteKey(&aesKeyData.blob);
- CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
}
/*
@@ -8520,6 +8620,10 @@
builder->AttestationChallenge("challenge");
builder->AttestationApplicationId("app_id");
});
+ KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+ KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+ KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+ KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
// Strongbox may not support factory attestation. Key creation might fail with
@@ -8531,14 +8635,6 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
}
- CheckedDeleteKey(&aesKeyData.blob);
- CheckedDeleteKey(&hmacKeyData.blob);
- if (rsaKeyData.blob.size() != 0U) {
- CheckedDeleteKey(&rsaKeyData.blob);
- }
- if (ecdsaKeyData.blob.size() != 0U) {
- CheckedDeleteKey(&ecdsaKeyData.blob);
- }
}
/*
@@ -8583,6 +8679,11 @@
TEST_P(EarlyBootKeyTest, DISABLED_FullTest) {
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+ KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+ KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+ KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+ KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
+
// TAG_EARLY_BOOT_ONLY should be in hw-enforced.
EXPECT_TRUE(HwEnforcedAuthorizations(aesKeyData.characteristics).Contains(TAG_EARLY_BOOT_ONLY));
EXPECT_TRUE(
@@ -8607,19 +8708,13 @@
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseEcdsaKey(ecdsaKeyData.blob));
- CheckedDeleteKey(&aesKeyData.blob);
- CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
-
// Should not be able to create new keys
- std::tie(aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData) =
+ auto [aesKeyData2, hmacKeyData2, rsaKeyData2, ecdsaKeyData2] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
-
- CheckedDeleteKey(&aesKeyData.blob);
- CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
+ KeyBlobDeleter aes_deleter2(keymint_, aesKeyData2.blob);
+ KeyBlobDeleter hmac_deleter2(keymint_, hmacKeyData2.blob);
+ KeyBlobDeleter rsa_deleter2(keymint_, rsaKeyData2.blob);
+ KeyBlobDeleter ecdsa_deleter2(keymint_, ecdsaKeyData2.blob);
}
INSTANTIATE_KEYMINT_AIDL_TEST(EarlyBootKeyTest);
@@ -8637,6 +8732,10 @@
TEST_P(UnlockedDeviceRequiredTest, DISABLED_KeysBecomeUnusable) {
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_UNLOCKED_DEVICE_REQUIRED, ErrorCode::OK);
+ KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+ KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+ KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+ KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
@@ -8650,11 +8749,6 @@
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseHmacKey(hmacKeyData.blob));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseEcdsaKey(ecdsaKeyData.blob));
-
- CheckedDeleteKey(&aesKeyData.blob);
- CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
}
INSTANTIATE_KEYMINT_AIDL_TEST(UnlockedDeviceRequiredTest);
@@ -8718,6 +8812,19 @@
std::string(argv[i + 1]);
++i;
}
+ if (std::string(argv[i]) == "--expect_upgrade") {
+ if (i + 1 >= argc) {
+ std::cerr << "Missing argument for --expect_upgrade\n";
+ return 1;
+ }
+ std::string arg = argv[i + 1];
+ aidl::android::hardware::security::keymint::test::KeyMintAidlTestBase::
+ expect_upgrade =
+ arg == "yes"
+ ? true
+ : (arg == "no" ? false : std::optional<bool>(std::nullopt));
+ ++i;
+ }
}
}
return RUN_ALL_TESTS();
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 3cb783c..c9c3e4d 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -115,6 +115,36 @@
return std::make_tuple(std::move(pubX), std::move(pubY));
}
+ErrMsgOr<bytevec> getRawPublicKey(const EVP_PKEY_Ptr& pubKey) {
+ if (pubKey.get() == nullptr) {
+ return "pkey is null.";
+ }
+ int keyType = EVP_PKEY_base_id(pubKey.get());
+ switch (keyType) {
+ case EVP_PKEY_EC: {
+ auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pubKey.get()));
+ if (ecKey.get() == nullptr) {
+ return "Failed to get ec key";
+ }
+ return ecKeyGetPublicKey(ecKey.get());
+ }
+ case EVP_PKEY_ED25519: {
+ bytevec rawPubKey;
+ size_t rawKeySize = 0;
+ if (!EVP_PKEY_get_raw_public_key(pubKey.get(), NULL, &rawKeySize)) {
+ return "Failed to get raw public key.";
+ }
+ rawPubKey.resize(rawKeySize);
+ if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey.data(), &rawKeySize)) {
+ return "Failed to get raw public key.";
+ }
+ return rawPubKey;
+ }
+ default:
+ return "Unknown key type.";
+ }
+}
+
ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
auto ec_key = EC_KEY_Ptr(EC_KEY_new());
if (ec_key.get() == nullptr) {
@@ -706,11 +736,10 @@
// Validates the certificate chain and returns the leaf public key.
ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
- uint8_t rawPubKey[64];
- size_t rawPubKeySize = sizeof(rawPubKey);
+ bytevec rawPubKey;
for (size_t i = 0; i < chain.size(); ++i) {
// Root must be self-signed.
- size_t signingCertIndex = (i > 1) ? i - 1 : i;
+ size_t signingCertIndex = (i > 0) ? i - 1 : i;
auto& keyCertItem = chain[i];
auto& signingCertItem = chain[signingCertIndex];
if (!keyCertItem || !keyCertItem->asBstr()) {
@@ -724,7 +753,7 @@
if (!keyCert) {
return keyCert.message();
}
- auto signingCert = parseX509Cert(keyCertItem->asBstr()->value());
+ auto signingCert = parseX509Cert(signingCertItem->asBstr()->value());
if (!signingCert) {
return signingCert.message();
}
@@ -749,17 +778,16 @@
return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
signerSubj + " Issuer subject is " + certIssuer;
}
-
- rawPubKeySize = sizeof(rawPubKey);
- if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey, &rawPubKeySize)) {
- return "Failed to get raw public key.";
+ if (i == chain.size() - 1) {
+ auto key = getRawPublicKey(pubKey);
+ if (!key) key.moveMessage();
+ rawPubKey = key.moveValue();
}
}
-
- return bytevec(rawPubKey, rawPubKey + rawPubKeySize);
+ return rawPubKey;
}
-std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsPub) {
+std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsCoseKeyBytes) {
for (const auto& [signerName, udsCertChain] : udsCerts) {
if (!signerName || !signerName->asTstr()) {
return "Signer Name must be a Tstr.";
@@ -775,8 +803,31 @@
if (!leafPubKey) {
return leafPubKey.message();
}
+ auto coseKey = CoseKey::parse(udsCoseKeyBytes);
+ if (!coseKey) return coseKey.moveMessage();
+
+ auto curve = coseKey->getIntValue(CoseKey::CURVE);
+ if (!curve) {
+ return "CoseKey must contain curve.";
+ }
+ bytevec udsPub;
+ if (curve == CoseKeyCurve::P256 || curve == CoseKeyCurve::P384) {
+ auto pubKey = coseKey->getEcPublicKey();
+ if (!pubKey) return pubKey.moveMessage();
+ // convert public key to uncompressed form by prepending 0x04 at begin.
+ pubKey->insert(pubKey->begin(), 0x04);
+ udsPub = pubKey.moveValue();
+ } else if (curve == CoseKeyCurve::ED25519) {
+ auto& pubkey = coseKey->getMap().get(cppcose::CoseKey::PUBKEY_X);
+ if (!pubkey || !pubkey->asBstr()) {
+ return "Invalid public key.";
+ }
+ udsPub = pubkey->asBstr()->value();
+ } else {
+ return "Unknown curve.";
+ }
if (*leafPubKey != udsPub) {
- return "Leaf public key in UDS certificat chain doesn't match UDS public key.";
+ return "Leaf public key in UDS certificate chain doesn't match UDS public key.";
}
}
return "";
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 7477f80..f8e1d5e 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -3,7 +3,7 @@
## Objective
Design a HAL to support over-the-air provisioning of certificates for asymmetric
-keys. The HAL must interact effectively with Keystore (and other daemons) and
+keys. The HAL must interact effectively with Keystore (and other services) and
protect device privacy and security.
Note that this API was originally designed for KeyMint, with the intention that
@@ -20,125 +20,52 @@
To more securely and reliably get keys and certificates to Android devices, we
need to create a system where no party outside of the device's secure components
is responsible for managing private keys. The strategy we've chosen is to
-deliver certificates over the air, using an asymmetric key pair created
-on-device in the factory as a root of trust to create an authenticated, secure
-channel. In this document we refer to this device-unique asymmetric key pair as
-Device Key (DK), its public half DK\_pub, its private half DK\_priv and a Device
-Key Certificate containing DK\_pub is denoted DKC.
+deliver certificates over the air, using an asymmetric key pair derived from a
+unique device secret (UDS) as a root of trust for authenticated requests from
+the secure components. We refer to the public half of this asymmetric key pair
+as UDS\_pub.
-In order for the provisioning service to use DK (or a key authenticated by DK),
-it must know whether a given DK\_pub is known and trusted. To prove trust, we
-ask device OEMs to use one of two mechanisms:
+In order for the provisioning service to trust UDS\_pub we ask device OEMs to
+use one of two mechanisms:
-1. (Preferred, recommended) The device OEM extracts DK\_pub from each device it
- manufactures and uploads the public keys to a backend server.
+1. (Preferred, recommended) The device OEM extracts the UDS\_pub from each
+ device they manufacture and uploads the public keys to a backend server.
-1. The device OEM signs the DK\_pub to produce DKC and stores it on the device.
- This has the advantage that they don't need to upload a DK\_pub for every
- device immediately, but the disadvantage that they have to manage their
- private signing keys, which means they have to have HSMs, configure and
- secure them correctly, etc. Some backend providers may also require that the
- OEM passes a factory security audit, and additionally promises to upload the
- keys eventually as well.
+1. The device OEM signs the UDS\_pub and stores the certificates on the device
+ rather than uploading a UDS\_pub for every device immediately. However,
+ there are many disadvantages and costs associated with this option as the
+ OEM will need to pass a security audit of their factory's physical security,
+ CA and HSM configuration, and incident response processes before the OEM's
+ public key is registered with the provisioning server.
-Note that in the full elaboration of this plan, DK\_pub is not the key used to
-establish a secure channel. Instead, DK\_pub is just the first public key in a
-chain of public keys which ends with the KeyMint public key, KM\_pub. All keys
-in the chain are device-unique and are joined in a certificate chain called the
-_Boot Certificate Chain_ (BCC), because in phases 2 and 3 of the remote
-provisioning project it is a chain of certificates corresponding to boot phases.
-We speak of the BCC even for phase 1, though in phase 1 it contains only a
-single self-signed DKC. This is described in more depth in the Phases section
-below.
-
-The BCC is authenticated by DK\_pub. To authenticate DK\_pub, we may have
-additional DKCs, from the SoC vendor, the device OEM, or both. Those are not
-part of the BCC but included as optional fields in the certificate request
-structure.
-
-The format of the the DK and BCC is specified within [Open Profile for DICE]
-(https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md). To
-map phrases within this document to their equivalent terminology in the DICE
-specification, read the terms as follows: the DK corresponds to the UDS-derived
-key pair, DKC corresponds to the UDS certificate, and the BCC entries between
-DK\_pub and KM\_pub correspond to a chain of CDI certificates.
-
-Note: In addition to allowing 32 byte hash values for fields in the BCC payload,
-this spec additionally constrains some of the choices allowed in open-DICE.
-Specifically, these include which entries are required and which are optional in
-the BCC payload, and which algorithms are acceptable for use.
+Note that in the full elaboration of this plan, UDS\_pub is not the key used to
+sign certificate requests. Instead, UDS\_pub is just the first public key in a
+chain of public keys that end the KeyMint public key. All keys in the chain are
+transitively derived from the UDS and joined in a certificate chain following
+the specification of the [Android Profile for DICE](#android-profile-for-dice).
### Phases
-RKP will be deployed in three phases, in terms of managing the root of trust
+RKP will be deployed with phased management of the root of trust
binding between the device and the backend. To briefly describe them:
-* Phase 1: In phase 1 there is only one entry in the BCC; DK_pub and KM_pub are
- the same key and the certificate is self-signed.
-* Phase 2: This is identical to phase 1, except it leverages the hardware root
- of trust process described by DICE. Instead of trust being rooted in the TEE,
- it is now rooted in the ROM by key material blown into fuses which are only
- accessible to the ROM code.
-* Phase 3: This is identical to Phase 2, except the SoC vendor also does the
- public key extraction or certification in their facilities, along with the OEM
- doing it in the factory. This tightens up the "supply chain" and aims to make
- key upload management more secure.
+* Degenerate DICE (Phase 1): A TEE root of trust key pair is used to sign
+ certificate requests; a single self-signed certificate signifies this phase.
+* DICE (Phase 2): A hardware root of trust key pair is only accessible to ROM
+ code; the boot process follows the [Android Profile for
+ DICE](#android-profile-for-dice).
+* SoC vendor certified DICE (Phase 3): This is identical to Phase 2, except the
+ SoC vendor also does the UDS\_pub extraction or certification in their
+ facilities, along with the OEM doing it in the factory. This tightens up the
+ "supply chain" and aims to make key upload management more secure.
### Privacy considerations
-Because DK and the DKCs are unique, immutable, unspoofable hardware-bound
-identifiers for the device, we must limit access to them to the absolute minimum
-possible. We do this in two ways:
-
-1. We require KeyMint (which knows the BCC and either knows or at least has the
-ability to use KM\_priv) to refuse to ever divulge the BCC or additional
-signatures in plaintext. Instead, KeyMint requires the caller to provide an
-_Endpoint Encryption Key_ (EEK), with which it will encrypt the data before
-returning it. When provisioning production keys, the EEK must be signed by an
-approved authority whose public key is embedded in KeyMint. When certifying test
-keys, KeyMint will accept any EEK without checking the signature, but will
-encrypt and return a test BCC, rather than the real one. The result is that
-only an entity in possession of an Trusted EEK (TEEK) private key can discover
-the plaintext of the production BCC.
-1. Having thus limited access to the public keys to the trusted party only, we
-need to prevent the entity from abusing this unique device identifier. The
-approach and mechanisms for doing that are beyond the scope of this document
-(they must be addressed in the server design), but generally involve taking care
-to ensure that we do not create any links between user IDs, IP addresses or
-issued certificates and the device pubkey.
-
-Although the details of the mechanisms for preventing the entity from abusing
-the BCC are, as stated, beyond the scope of this document, there is a subtle
-design decision here made specifically to enable abuse prevention. Specifically
-the `CertificateRequest` message sent to the server is (in
-[CDDL](https://tools.ietf.org/html/rfc8610)):
-
-```
-cddl
-CertificateRequest = [
- DeviceInfo,
- challenge : bstr,
- ProtectedData,
- MacedKeysToSign
-]
-```
-
-The public keys to be attested by the server are in `MacedKeysToSign`, which is
-a COSE\_Mac0 structure, MACed with a key that is found in `ProtectedData`. The
-MAC key is signed by DK\_pub.
-
-This structure allows the backend component that has access to EEK\_priv to
-decrypt `ProtectedData`, validate that the request is from an authorized device,
-check that the request is fresh and verify and extract the MAC key. That backend
-component never sees any data related to the keys to be signed, but can provide
-the MAC key to another backend component that can verify `MacedKeysToSign` and
-proceed to generate the certificates.
-
-In this way, we can partition the provisioning server into one component that
-knows the device identity, as represented by DK\_pub, but never sees the keys to
-be certified or certificates generated, and another component that sees the keys
-to be certified and certificates generated but does not know the device
-identity.
+Because the UDS, CDIs and derived values are unique, immutable, unspoofable
+hardware-bound identifiers for the device, we must limit access to them. We
+require that the values are never exposed in public APIs and are only available
+to the minimum set of system components that require access to them to function
+correctly.
### Key and cryptographic message formatting
@@ -195,24 +122,6 @@
choice for algorithm implies the implementor should also choose the P256 public
key group further down in the COSE structure.
-### Testability
-
-It's critical that the remote provisioning implementation be testable, to
-minimize the probability that broken devices are sold to end users. To support
-testing, the remote provisioning HAL methods take a `testMode` argument. Keys
-created in test mode are tagged to indicate this. The provisioning server will
-check for the test mode tag and issue test certificates that do not chain back
-to a trusted public key. In test mode, any EEK will be accepted, enabling
-testing tools to use EEKs for which they have the private key so they can
-validate the content of certificate requests. The BCC included in the
-`CertificateRequest` must contain freshly-generated keys, not the real BCC keys.
-
-Keystore (or similar) will need to be able to handle both testMode keys and
-production keys and keep them distinct, generating test certificate requests
-when asked with a test EEK and production certificate requests when asked with a
-production EEK. Likewise, the interface used to instruct Keystore to create keys
-will need to be able to specify whether test or production keys are desired.
-
## Design
### Certificate provisioning flow
@@ -220,25 +129,20 @@
TODO(jbires): Replace this with a `.png` containing a sequence diagram. The
provisioning flow looks something like this:
-Provisioner -> Keystore: Prepare N keys
-Keystore -> KeyMint: generateKeyPair
-KeyMint -> KeyMint: Generate key pair
-KeyMint --> Keystore: key\_blob,pubkey
-Keystore -> Keystore: Store key\_blob,pubkey
-Provisioner -> Server: Get TEEK
-Server --> Provisioner: TEEK
-Provisioner -> Keystore: genCertReq(N, TEEK)
-Keystore -> KeyMint: genCertReq(pubkeys, TEEK)
-KeyMint -> KeyMint: Sign pubkeys & encrypt BCC
-KeyMint --> Keystore: signature, encrypted BCC
-Keystore -> Keystore: Construct cert\_request
-Keystore --> Provisioner: cert\_request
-Provisioner --> Server: cert\_request
-Server -> Server: Validate cert\_request
+rkpd -> KeyMint: generateKeyPair
+KeyMint -> KeyMint: Generate key pair
+KeyMint --> rkpd: key\_blob,pubkey
+rkpd -> rkpd: Store key\_blob,pubkey
+rkpd -> Server: Get challenge
+Server --> rkpd: challenge
+rkpd -> KeyMint: genCertReq(pubkeys, challenge)
+KeyMint -> KeyMint: Sign CSR
+KeyMint --> rkpd: signed CSR
+rkpd --> Server: CSR
+Server -> Server: Validate CSR
Server -> Server: Generate certificates
-Server --> Provisioner: certificates
-Provisioner -> Keystore: certificates
-Keystore -> Keystore: Store certificates
+Server --> rkpd: certificates
+rkpd -> rkpd: Store certificates
The actors in the above diagram are:
@@ -246,10 +150,12 @@
the uploaded device public keys and is responsible for providing encryption
keys, decrypting and validating requests, and generating certificates in
response to requests.
-* **Provisioner** is an application that is responsible for communicating with
- the server and all of the system components that require key certificates
- from the server. It also implements the policy that defines how many key
- pairs each client should keep in their pool.
+* **rkpd** is, optionally, a modular system component that is responsible for
+ communicating with the server and all of the system components that require
+ key certificates from the server. It also implements the policy that defines
+ how many key pairs each client should keep in their pool. When a system
+ ships with rkpd as a modular component, it may be updated independently from
+ the rest of the system.
* **Keystore** is the [Android keystore
daemon](https://developer.android.com/training/articles/keystore) (or, more
generally, whatever system component manages communications with a
@@ -257,63 +163,50 @@
* **KeyMint** is the secure area component that manages cryptographic keys and
performs attestations (or perhaps some other secure area component).
-### `BCC`
+### Android Profile for DICE
-The _Boot Certificate Chain_ (BCC) is the chain of certificates that contains
-DK\_pub as well as other often device-unique certificates. The BCC is
-represented as a COSE\_Key containing DK\_pub followed by an array of
-COSE\_Sign1 "certificates" containing public keys and optional additional
-information, ordered from root to leaf, with each certificate signing the next.
-The first certificate in the array is signed by DK\_pub, the last certificate
-has the KeyMint (or whatever) signing key's public key, KM\_pub. In phase 1
-there is only one entry; DK\_pub and KM\_pub are the same key and the
-certificate is self-signed.
+The Android Profile for DICE is based on the [Open Profile for
+DICE](https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md),
+with additional constraints for details that the Open Profile for DICE leaves
+intentionally underspecified. This section describes the differences from the
+Open Profile for DICE.
-Each COSE\_Sign1 certificate is a CBOR Web Token (CWT) as described in [RFC
-8392](https://tools.ietf.org/html/rfc8392) with additional fields as described
-in the Open Profile for DICE. Of these additional fields, only the
-_subjectPublicKey_ and _keyUsage_ fields are expected to be present for the
-KM\_pub entry (that is, the last entry) in a BCC, but all fields required by the
-Open Profile for DICE are expected for other entries (each of which corresponds
-to a particular firmware component or boot stage). The CWT fields _iss_ and
-_sub_ identify the issuer and subject of the certificate and are consistent
-along the BCC entries; the issuer of a given entry matches the subject of the
-previous entry.
+#### Algorithms
-The BCC is designed to be constructed using the Open Profile for DICE. In this
-case the DK key pair is derived from the UDS as described by that profile and
-all BCC entries before the leaf are CBOR CDI certificates chained from DK\_pub.
-The KM key pair is not part of the derived DICE chain. It is generated (not
-derived) by the KeyMint module, certified by the last key in the DICE chain, and
-added as the leaf BCC entry. The key usage field in this leaf certificate must
-indicate the key is not used to sign certificates. If a UDS certificate is
-available on the device it should appear in the certificate request as the leaf
-of a DKCertChain in AdditionalDKSignatures (see
-[CertificateRequest](#certificaterequest)).
+The choice of algorithm must remain consistent with a given certificate e.g. if
+SHA-256 is used for the code hash then the authority hash, config hash, etc.
+must also use SHA-256.
+
+* UDS and CDI key pairs:
+ * Ed25519 / P-256 / P-384
+* Hash algorithms (digests can be encoded with their natural size and do not
+ need to be the 64-bytes specified by the Open Profile for DICE):
+ * SHA-256 / SHA-384 / SHA-512
+* HKDF with a supported message digest for all key derivation
#### Mode
-The Open Profile for DICE specifies four possible modes with the most important
-mode being `normal`. A certificate must only set the mode to `normal` when all
-of the following conditions are met when loading and verifying the software
-component that is being described by the certificate:
+A certificate must only set the mode to `normal` when all of the following
+conditions are met when loading and verifying the software component that is
+being described by the certificate:
-* verified boot with anti-rollback protection is enabled
-* only the verified boot authorities for production images are enabled
-* debug ports, fuses or other debug facilities are disabled
-* device booted software from the normal primary source e.g. internal flash
+* verified boot with anti-rollback protection is enabled
+* only the verified boot authorities for production images are enabled
+* debug ports, fuses, or other debug facilities are disabled
+* device booted software from the normal primary source e.g. internal flash
-If any of these conditions are not met then it is recommended to explicitly
-acknowledge this fact by using the `debug` mode. The mode should never be `not
-configured`.
+The mode should never be `not configured`.
+
+Every certificate in the DICE chain will need to be have the `normal` mode in
+order to be provisioned with production certificates by RKP.
#### Configuration descriptor
-The Open Profile for DICE allows for an arbitrary configuration descriptor. For
-BCC entries, this configuration descriptor is a CBOR map with the following
-optional fields. If no fields are relevant, an empty map should be encoded.
-Additional implementation-specific fields may be added using key values not in
-the range \[-70000, -70999\] (these are reserved for future additions here).
+The configuration descriptor is a CBOR map with the following optional fields.
+If no fields are relevant, an empty map should be encoded. The key value range
+\[-70000, -70999\] is reserved for the Android Profile for DICE.
+Implementation-specific fields may be added using key values outside of the
+reserved range.
```
| Name | Key | Value type | Meaning |
@@ -324,44 +217,13 @@
: : : : boot stage :
| Resettable | -70004 | null | If present, key changes on factory|
: : : : reset :
+| Security version | -70005 | uint | Machine-comparable, monotonically |
+: : : : increasing version of the firmware:
+: : : : component / boot stage where a :
+: : : : greater value indicates a newer :
+: : : : version :
```
-Please see
-[ProtectedData.aidl](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl)
-for a full CDDL definition of the BCC.
-
-### `CertificateRequest`
-
-The full CBOR message that will be sent to the server to request certificates
-is:
-
-```cddl
-CertificateRequest = [
- DeviceInfo,
- challenge : bstr, // Provided by the server
- ProtectedData, // See ProtectedData.aidl
- MacedKeysToSign // See IRemotelyProvisionedComponent.aidl
-]
-
-DeviceInfo = [
- VerifiedDeviceInfo, // See DeviceInfo.aidl
- UnverifiedDeviceInfo
-]
-
-// Unverified info is anything provided by the HLOS. Subject to change out of
-// step with the HAL.
-UnverifiedDeviceInfo = {
- ? "fingerprint" : tstr,
-}
-
-```
-
-It will be the responsibility of Keystore and the Provisioner to construct the
-`CertificateRequest`. The HAL provides a method to generate the elements that
-need to be constructed on the secure side, which are the tag field of
-`MacedKeysToSign`, `VerifiedDeviceInfo`, and the ciphertext field of
-`ProtectedData`.
-
### HAL
The remote provisioning HAL provides a simple interface that can be implemented
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 2a4cba1..b231dae 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -422,11 +422,12 @@
* ; described above.
* -4670545 : bstr, ; Code Hash
* ? -4670546 : bstr, ; Code Descriptor
- * ? -4670547 : bstr, ; Configuration Hash
+ * -4670547 : bstr, ; Configuration Hash
* -4670548 : bstr .cbor { ; Configuration Descriptor
* ? -70002 : tstr, ; Component name
* ? -70003 : int / tstr, ; Component version
* ? -70004 : null, ; Resettable
+ * ? -70005 : uint, ; Security version
* },
* -4670549 : bstr, ; Authority Hash
* ? -4670550 : bstr, ; Authority Descriptor
diff --git a/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl b/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
deleted file mode 100644
index 2e7330e..0000000
--- a/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.media.c2;
-
-import android.hardware.common.NativeHandle;
-/**
- * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
- * output buffers. This keeps # of dequeued buffers from Surface less than
- * configured max # of dequeued buffers all the time.
- */
-parcelable SurfaceSyncObj {
- /**
- * ASharedMemory for synchronization data. Layout is below
- *
- * |lock(futex) 4bytes|
- * |conditional_variable(futex) 4bytes|
- * |# of max dequeable buffer 4bytes|
- * |# of dequeued buffer 4bytes|
- * |Status of the surface 4bytes|
- * INIT = 0, Configuring surface is not finished.
- * ACTIVE = 1, Surface is ready to allocate(dequeue).
- * SWITCHING = 2, Switching to the new surface. It is blocked
- * to allocate(dequeue) a buffer until switching
- * completes.
- */
- NativeHandle syncMemory;
- /**
- * BufferQueue id.
- */
- long bqId;
- /**
- * Generation id.
- */
- int generationId;
- /**
- * Consumer usage flags. See +ndk
- * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
- */
- long consumerUsage;
-}
diff --git a/staging/threadnetwork/OWNERS b/staging/threadnetwork/OWNERS
deleted file mode 100644
index 037215d..0000000
--- a/staging/threadnetwork/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 1203089
-
-wgtdkp@google.com
-xyk@google.com
-zhanglongxia@google.com
diff --git a/staging/threadnetwork/README.md b/staging/threadnetwork/README.md
deleted file mode 100644
index 12104e5..0000000
--- a/staging/threadnetwork/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Staging threadnetwork HAL interface
-
-The directory includes the unstable/unreleased version of `hardware/interfaces/threadnetwork`
-code which should **NOT** be used in production. But vendors may start verifying their hardware
-with the HAL interface.
-
-This directory will be cleaned up when the stable Thread HAL interface is added in
-`hardware/interfaces/threadnetwork` by version `V` or later.
-
-More information about _Thread_:
-- https://www.threadgroup.org
-- https://openthread.io
diff --git a/staging/threadnetwork/aidl/Android.bp b/staging/threadnetwork/aidl/Android.bp
deleted file mode 100644
index b59d6da..0000000
--- a/staging/threadnetwork/aidl/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-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.threadnetwork",
- host_supported: true,
- vendor_available: true,
-
- srcs: [
- "android/hardware/threadnetwork/*.aidl",
- ],
-
- unstable: true,
-
- backend: {
- ndk: {
- enabled: true,
- },
- },
-}
diff --git a/staging/threadnetwork/aidl/default/Android.bp b/staging/threadnetwork/aidl/default/Android.bp
deleted file mode 100644
index 8fc22ad..0000000
--- a/staging/threadnetwork/aidl/default/Android.bp
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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 {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_defaults {
- name: "threadnetwork_service_default",
- vendor: true,
- relative_install_path: "hw",
-
- shared_libs: [
- "android.hardware.threadnetwork-ndk",
- "libbase",
- "libbinder_ndk",
- "libcutils",
- "liblog",
- "libutils",
- ],
-
- static_libs: [
- "openthread-common",
- "openthread-hdlc",
- "openthread-platform",
- "openthread-posix",
- "openthread-url",
- ],
-
- srcs: [
- "main.cpp",
- "service.cpp",
- "thread_chip.cpp",
- "utils.cpp",
- ],
-}
-
-cc_binary {
- name: "android.hardware.threadnetwork-service.sim",
- defaults: ["threadnetwork_service_default"],
- init_rc: ["android.hardware.threadnetwork-service.sim.rc"],
-}
-
-cc_binary {
- name: "android.hardware.threadnetwork-service",
- defaults: ["threadnetwork_service_default"],
-}
diff --git a/staging/threadnetwork/aidl/default/main.cpp b/staging/threadnetwork/aidl/default/main.cpp
deleted file mode 100644
index b6c8bbb..0000000
--- a/staging/threadnetwork/aidl/default/main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#include <android-base/logging.h>
-#include <utils/Log.h>
-
-#include "service.hpp"
-
-int main(int argc, char* argv[]) {
- CHECK_GT(argc, 1);
- aidl::android::hardware::threadnetwork::Service service(&argv[1], argc - 1);
-
- ALOGI("Thread Network HAL is running");
-
- service.startLoop();
- return EXIT_FAILURE; // should not reach
-}
diff --git a/staging/threadnetwork/aidl/default/utils.cpp b/staging/threadnetwork/aidl/default/utils.cpp
deleted file mode 100644
index d3b4062..0000000
--- a/staging/threadnetwork/aidl/default/utils.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-#include <openthread/logging.h>
-#include <utils/Log.h>
-
-void otLogCritPlat(const char* format, ...) {
- va_list args;
-
- va_start(args, format);
- __android_log_vprint(ANDROID_LOG_FATAL, LOG_TAG, format, args);
- va_end(args);
-}
-
-void otLogWarnPlat(const char* format, ...) {
- va_list args;
-
- va_start(args, format);
- __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, args);
- va_end(args);
-}
diff --git a/tetheroffload/control/1.1/Android.bp b/tetheroffload/control/1.1/Android.bp
index 7871c2c..0daa90e 100644
--- a/tetheroffload/control/1.1/Android.bp
+++ b/tetheroffload/control/1.1/Android.bp
@@ -22,7 +22,7 @@
"android.hidl.base@1.0",
],
apex_available: [
- "//apex_available:platform", // Used by InProcessTethering
+ "//apex_available:platform",
"com.android.tethering",
],
gen_java: true,
diff --git a/threadnetwork/aidl/Android.bp b/threadnetwork/aidl/Android.bp
new file mode 100644
index 0000000..480ac0f
--- /dev/null
+++ b/threadnetwork/aidl/Android.bp
@@ -0,0 +1,22 @@
+aidl_interface {
+ name: "android.hardware.threadnetwork",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/threadnetwork/*.aidl",
+ ],
+
+ stability: "vintf",
+
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ ndk: {
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.threadnetwork",
+ ],
+ min_sdk_version: "33",
+ },
+ },
+}
diff --git a/threadnetwork/aidl/OWNERS b/threadnetwork/aidl/OWNERS
new file mode 100644
index 0000000..e3111c8
--- /dev/null
+++ b/threadnetwork/aidl/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1288834
+zhanglongxia@google.com
+xyk@google.com
diff --git a/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl
new file mode 100644
index 0000000..607ceb3
--- /dev/null
+++ b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChip.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.threadnetwork;
+@VintfStability
+interface IThreadChip {
+ void open(in android.hardware.threadnetwork.IThreadChipCallback callback);
+ void close();
+ void hardwareReset();
+ void sendSpinelFrame(in byte[] frame);
+ const int ERROR_FAILED = 1;
+ const int ERROR_NO_BUFS = 2;
+ const int ERROR_BUSY = 3;
+}
diff --git a/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChipCallback.aidl b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChipCallback.aidl
new file mode 100644
index 0000000..e86b3ec
--- /dev/null
+++ b/threadnetwork/aidl/aidl_api/android.hardware.threadnetwork/current/android/hardware/threadnetwork/IThreadChipCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.threadnetwork;
+@VintfStability
+interface IThreadChipCallback {
+ oneway void onReceiveSpinelFrame(in byte[] frame);
+}
diff --git a/staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
similarity index 87%
rename from staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
rename to threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
index 3c57149..e695623 100644
--- a/staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
+++ b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChip.aidl
@@ -22,6 +22,7 @@
* Controls a Thread radio chip on the device.
*/
+@VintfStability
interface IThreadChip {
/**
* The operation failed for the internal error.
@@ -43,10 +44,10 @@
* successfully, then the Thread HAL instance is ready to accept spinel
* messages through sendSpinelFrame() API.
*
- * @param callback A IThreadChipCallback callback instance. If multiple
- * callbacks are passed in, the open() will return ERROR_BUSY.
+ * @param callback A IThreadChipCallback callback instance.
*
* @throws EX_ILLEGAL_ARGUMENT if the callback handle is invalid (for example, it is null).
+ *
* @throws ServiceSpecificException with one of the following values:
* - ERROR_FAILED The interface cannot be opened due to an internal error.
* - ERROR_BUSY This interface is in use.
@@ -55,18 +56,18 @@
/**
* Close the Thread HAL instance. Must free all resources.
- *
- * @throws EX_ILLEGAL_STATE if the Thread HAL instance is not opened.
- *
*/
void close();
/**
- * This method resets the Thread HAL internal state. The callback registered by
- * `open()` won’t be reset and the resource allocated by `open()` won’t be free.
+ * This method hardware resets the Thread radio chip via the physical reset pin.
+ * The callback registered by `open()` won’t be reset and the resource allocated
+ * by `open()` won’t be free.
+ *
+ * @throws EX_UNSUPPORTED_OPERATION if the Thread radio chip doesn't support the hardware reset.
*
*/
- void reset();
+ void hardwareReset();
/**
* This method sends a spinel frame to the Thread HAL.
diff --git a/staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl
similarity index 98%
rename from staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl
rename to threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl
index a0fe88c..046edc3 100644
--- a/staging/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl
+++ b/threadnetwork/aidl/android/hardware/threadnetwork/IThreadChipCallback.aidl
@@ -16,6 +16,7 @@
package android.hardware.threadnetwork;
+@VintfStability
interface IThreadChipCallback {
/**
* This method is called when a spinel frame is received. Thread network
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
new file mode 100644
index 0000000..bcd5704
--- /dev/null
+++ b/threadnetwork/aidl/default/Android.bp
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2022 Google LLC.
+// All rights reserved.
+//
+// This document is the property of Google LLC, Inc. It is
+// considered proprietary and confidential information.
+//
+// This document may not be reproduced or transmitted in any form,
+// in whole or in part, without the express written permission of
+// Google LLC.
+
+cc_defaults {
+ name: "threadnetwork_service_default",
+ vintf_fragments: ["threadnetwork-default.xml"],
+ vendor: true,
+ relative_install_path: "hw",
+
+ shared_libs: [
+ "android.hardware.threadnetwork-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+
+ static_libs: [
+ "openthread-common",
+ "openthread-hdlc",
+ "openthread-platform",
+ "openthread-posix",
+ "openthread-spi",
+ "openthread-url",
+ ],
+
+ srcs: [
+ "main.cpp",
+ "service.cpp",
+ "thread_chip.cpp",
+ "utils.cpp",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.threadnetwork-service.sim",
+ defaults: ["threadnetwork_service_default"],
+ init_rc: ["android.hardware.threadnetwork-service.sim.rc"],
+ required: ["ot-rcp"],
+}
+
+cc_binary {
+ name: "android.hardware.threadnetwork-service",
+ defaults: ["threadnetwork_service_default"],
+}
+
+cc_fuzz {
+ name: "android.hardware.threadnetwork-service.fuzzer",
+
+ defaults:["service_fuzzer_defaults"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+
+ static_libs: [
+ "android.hardware.threadnetwork-V1-ndk",
+ "libbase",
+ "liblog",
+ "openthread-common",
+ "openthread-hdlc",
+ "openthread-platform",
+ "openthread-posix",
+ "openthread-spi",
+ "openthread-url",
+ ],
+
+ srcs: [
+ "thread_chip.cpp",
+ "utils.cpp",
+ "fuzzer.cpp",
+ ],
+
+ fuzz_config: {
+ cc: [
+ "zhanglongxia@google.com",
+ ],
+ },
+}
diff --git a/staging/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc b/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
similarity index 100%
rename from staging/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
rename to threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
diff --git a/threadnetwork/aidl/default/fuzzer.cpp b/threadnetwork/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..fb6e548
--- /dev/null
+++ b/threadnetwork/aidl/default/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "thread_chip.hpp"
+
+using aidl::android::hardware::threadnetwork::ThreadChip;
+using android::fuzzService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ char url[] = "spinel+hdlc+null:///dev/null";
+ auto service = ndk::SharedRefBase::make<ThreadChip>(url);
+
+ fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
+
diff --git a/threadnetwork/aidl/default/main.cpp b/threadnetwork/aidl/default/main.cpp
new file mode 100644
index 0000000..8419041
--- /dev/null
+++ b/threadnetwork/aidl/default/main.cpp
@@ -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.
+ */
+
+#include <aidl/android/hardware/threadnetwork/IThreadChip.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+#include "service.hpp"
+#include "thread_chip.hpp"
+
+using aidl::android::hardware::threadnetwork::IThreadChip;
+using aidl::android::hardware::threadnetwork::ThreadChip;
+
+int main(int argc, char* argv[]) {
+ CHECK_GT(argc, 1);
+ std::vector<std::shared_ptr<ThreadChip>> threadChips;
+ aidl::android::hardware::threadnetwork::Service service;
+
+ for (int id = 0; id < argc - 1; id++) {
+ binder_status_t status;
+ const std::string serviceName(std::string() + IThreadChip::descriptor + "/chip" +
+ std::to_string(id));
+ auto threadChip = ndk::SharedRefBase::make<ThreadChip>(argv[id + 1]);
+
+ CHECK_NE(threadChip, nullptr);
+
+ status = AServiceManager_addService(threadChip->asBinder().get(), serviceName.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ALOGI("ServiceName: %s, Url: %s", serviceName.c_str(), argv[id + 1]);
+ threadChips.push_back(std::move(threadChip));
+ }
+
+ ALOGI("Thread Network HAL is running");
+
+ service.startLoop();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/staging/threadnetwork/aidl/default/service.cpp b/threadnetwork/aidl/default/service.cpp
similarity index 75%
rename from staging/threadnetwork/aidl/default/service.cpp
rename to threadnetwork/aidl/default/service.cpp
index 8047214..7f583f4 100644
--- a/staging/threadnetwork/aidl/default/service.cpp
+++ b/threadnetwork/aidl/default/service.cpp
@@ -20,38 +20,24 @@
#include <android/binder_process.h>
#include <utils/Log.h>
-#include "thread_chip.hpp"
-
namespace aidl {
namespace android {
namespace hardware {
namespace threadnetwork {
-Service::Service(char* urls[], int numUrls) : mBinderFd(-1) {
- int fd;
-
- CHECK_NE(urls, nullptr);
- CHECK_GT(numUrls, 0);
-
- for (int i = 0; i < numUrls; i++) {
- auto threadChip = ndk::SharedRefBase::make<ThreadChip>(i, urls[i]);
- CHECK_NE(threadChip, nullptr);
- mThreadChips.push_back(std::move(threadChip));
- }
-
- binder_status_t status = ABinderProcess_setupPolling(&fd);
+Service::Service(void) : mBinderFd(-1) {
+ binder_status_t status = ABinderProcess_setupPolling(&mBinderFd);
CHECK_EQ(status, ::STATUS_OK);
- CHECK_GE(fd, 0);
- mBinderFd.reset(fd);
+ CHECK_GE(mBinderFd, 0);
}
void Service::Update(otSysMainloopContext& context) {
- FD_SET(mBinderFd.get(), &context.mReadFdSet);
- context.mMaxFd = std::max(context.mMaxFd, mBinderFd.get());
+ FD_SET(mBinderFd, &context.mReadFdSet);
+ context.mMaxFd = std::max(context.mMaxFd, mBinderFd);
}
void Service::Process(const otSysMainloopContext& context) {
- if (FD_ISSET(mBinderFd.get(), &context.mReadFdSet)) {
+ if (FD_ISSET(mBinderFd, &context.mReadFdSet)) {
ABinderProcess_handlePolledCommands();
}
}
diff --git a/staging/threadnetwork/aidl/default/service.hpp b/threadnetwork/aidl/default/service.hpp
similarity index 83%
rename from staging/threadnetwork/aidl/default/service.hpp
rename to threadnetwork/aidl/default/service.hpp
index 6e6e868..6a94791 100644
--- a/staging/threadnetwork/aidl/default/service.hpp
+++ b/threadnetwork/aidl/default/service.hpp
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#include <android-base/unique_fd.h>
-
#include "mainloop.hpp"
-#include "thread_chip.hpp"
namespace aidl {
namespace android {
@@ -26,15 +23,14 @@
class Service : public ot::Posix::Mainloop::Source {
public:
- Service(char* urls[], int numUrls);
+ Service(void);
void Update(otSysMainloopContext& context) override;
void Process(const otSysMainloopContext& context) override;
void startLoop(void);
private:
- ::android::base::unique_fd mBinderFd;
- std::vector<std::shared_ptr<ThreadChip>> mThreadChips;
+ int mBinderFd;
};
} // namespace threadnetwork
} // namespace hardware
diff --git a/staging/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
similarity index 66%
rename from staging/threadnetwork/aidl/default/thread_chip.cpp
rename to threadnetwork/aidl/default/thread_chip.cpp
index 38abad4..3d38cb8 100644
--- a/staging/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -23,56 +23,65 @@
#include <android/binder_process.h>
#include <utils/Log.h>
+#include "hdlc_interface.hpp"
+#include "spi_interface.hpp"
+
namespace aidl {
namespace android {
namespace hardware {
namespace threadnetwork {
-static ndk::ScopedAStatus errorStatus(int32_t error, const char* message) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(error, message));
-}
+ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) {
+ static const char kHdlcProtocol[] = "spinel+hdlc";
+ static const char kSpiProtocol[] = "spinel+spi";
+ const char* protocol;
-ThreadChip::ThreadChip(uint8_t id, char* url)
- : mUrl(),
- mInterface(handleReceivedFrame, this, mRxFrameBuffer),
- mRxFrameBuffer(),
- mCallback(nullptr) {
- const std::string name(std::string() + IThreadChip::descriptor + "/chip" + std::to_string(id));
- binder_status_t status;
-
- ALOGI("ServiceName: %s, Url: %s", name.c_str(), url);
CHECK_EQ(mUrl.Init(url), 0);
- status = AServiceManager_addService(asBinder().get(), name.c_str());
- CHECK_EQ(status, STATUS_OK);
+
+ protocol = mUrl.GetProtocol();
+ CHECK_NE(protocol, nullptr);
+
+ if (memcmp(protocol, kSpiProtocol, strlen(kSpiProtocol)) == 0) {
+ mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(handleReceivedFrameJump, this,
+ mRxFrameBuffer);
+ } else if (memcmp(protocol, kHdlcProtocol, strlen(kHdlcProtocol)) == 0) {
+ mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
+ mRxFrameBuffer);
+ } else {
+ ALOGE("The protocol \"%s\" is not supported", protocol);
+ exit(EXIT_FAILURE);
+ }
+
+ CHECK_NE(mSpinelInterface, nullptr);
mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
- AIBinder_DeathRecipient_new(ThreadChip::onBinderDied));
- AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinked);
+ AIBinder_DeathRecipient_new(ThreadChip::onBinderDiedJump));
+ AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump);
}
ThreadChip::~ThreadChip() {
AIBinder_DeathRecipient_delete(mDeathRecipient.get());
}
-void ThreadChip::onBinderDied(void* context) {
+void ThreadChip::onBinderDiedJump(void* context) {
reinterpret_cast<ThreadChip*>(context)->onBinderDied();
}
void ThreadChip::onBinderDied(void) {
- ALOGW("Thread Network HAL client is dead.");
+ ALOGW("Thread Network HAL client is dead");
}
-void ThreadChip::onBinderUnlinked(void* context) {
+void ThreadChip::onBinderUnlinkedJump(void* context) {
reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked();
}
void ThreadChip::onBinderUnlinked(void) {
- ALOGW("ThreadChip binder is unlinked.");
+ ALOGW("ThreadChip binder is unlinked");
deinitChip();
}
-void ThreadChip::handleReceivedFrame(void* context) {
- reinterpret_cast<ThreadChip*>(context)->handleReceivedFrame();
+void ThreadChip::handleReceivedFrameJump(void* context) {
+ static_cast<ThreadChip*>(context)->handleReceivedFrame();
}
void ThreadChip::handleReceivedFrame(void) {
@@ -89,9 +98,9 @@
if (status.isOk()) {
AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this);
- ALOGI("Open IThreadChip successfully.");
+ ALOGI("Open IThreadChip successfully");
} else {
- ALOGW("Open IThreadChip failed, error: %s", status.getDescription().c_str());
+ ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str());
}
return status;
@@ -101,7 +110,7 @@
if (in_callback == nullptr) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
} else if (mCallback == nullptr) {
- if (mInterface.Init(mUrl) != OT_ERROR_NONE) {
+ if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) {
return errorStatus(ERROR_FAILED, "Failed to initialize the interface");
}
@@ -109,7 +118,7 @@
ot::Posix::Mainloop::Manager::Get().Add(*this);
return ndk::ScopedAStatus::ok();
} else {
- return errorStatus(ERROR_BUSY, "Interface is already opened");
+ return errorStatus(ERROR_BUSY, "Interface has been opened");
}
}
@@ -125,7 +134,7 @@
ALOGI("Close IThreadChip successfully");
} else {
- ALOGW("Close IThreadChip failed, error: %s", status.getDescription().c_str());
+ ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str());
}
return status;
@@ -133,7 +142,7 @@
ndk::ScopedAStatus ThreadChip::deinitChip() {
if (mCallback != nullptr) {
- mInterface.Deinit();
+ mSpinelInterface->Deinit();
ot::Posix::Mainloop::Manager::Get().Remove(*this);
mCallback = nullptr;
return ndk::ScopedAStatus::ok();
@@ -149,8 +158,8 @@
if (mCallback == nullptr) {
status = errorStatus(ERROR_FAILED, "The interface is not open");
} else {
- error = mInterface.SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
- in_frame.size());
+ error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
+ in_frame.size());
if (error == OT_ERROR_NONE) {
status = ndk::ScopedAStatus::ok();
} else if (error == OT_ERROR_NO_BUFS) {
@@ -169,28 +178,30 @@
return status;
}
-ndk::ScopedAStatus ThreadChip::reset() {
- mInterface.OnRcpReset();
+ndk::ScopedAStatus ThreadChip::hardwareReset() {
+ if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+
ALOGI("reset()");
return ndk::ScopedAStatus::ok();
}
void ThreadChip::Update(otSysMainloopContext& context) {
if (mCallback != nullptr) {
- mInterface.UpdateFdSet(context.mReadFdSet, context.mWriteFdSet, context.mMaxFd,
- context.mTimeout);
+ mSpinelInterface->UpdateFdSet(&context);
}
}
void ThreadChip::Process(const otSysMainloopContext& context) {
- struct RadioProcessContext radioContext;
-
if (mCallback != nullptr) {
- radioContext.mReadFdSet = &context.mReadFdSet;
- radioContext.mWriteFdSet = &context.mWriteFdSet;
- mInterface.Process(radioContext);
+ mSpinelInterface->Process(&context);
}
}
+
+ndk::ScopedAStatus ThreadChip::errorStatus(int32_t error, const char* message) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(error, message));
+}
} // namespace threadnetwork
} // namespace hardware
} // namespace android
diff --git a/staging/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
similarity index 84%
rename from staging/threadnetwork/aidl/default/thread_chip.hpp
rename to threadnetwork/aidl/default/thread_chip.hpp
index da5cba7..1ab6d54 100644
--- a/staging/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -19,7 +19,6 @@
#include <aidl/android/hardware/threadnetwork/BnThreadChip.h>
#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
-#include "hdlc_interface.hpp"
#include "lib/spinel/spinel_interface.hpp"
#include "mainloop.hpp"
@@ -34,29 +33,29 @@
class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
public:
- ThreadChip(uint8_t id, char* url);
+ ThreadChip(char* url);
~ThreadChip();
ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus sendSpinelFrame(const std::vector<uint8_t>& in_frame) override;
- ndk::ScopedAStatus reset() override;
+ ndk::ScopedAStatus hardwareReset() override;
void Update(otSysMainloopContext& context) override;
void Process(const otSysMainloopContext& context) override;
private:
- static void onBinderDied(void* context);
+ static void onBinderDiedJump(void* context);
void onBinderDied(void);
- static void onBinderUnlinked(void* context);
+ static void onBinderUnlinkedJump(void* context);
void onBinderUnlinked(void);
- static void handleReceivedFrame(void* context);
+ static void handleReceivedFrameJump(void* context);
void handleReceivedFrame(void);
-
+ ndk::ScopedAStatus errorStatus(int32_t error, const char* message);
ndk::ScopedAStatus initChip(const std::shared_ptr<IThreadChipCallback>& in_callback);
ndk::ScopedAStatus deinitChip();
ot::Url::Url mUrl;
- ot::Posix::HdlcInterface mInterface;
+ std::shared_ptr<ot::Spinel::SpinelInterface> mSpinelInterface;
ot::Spinel::SpinelInterface::RxFrameBuffer mRxFrameBuffer;
std::shared_ptr<IThreadChipCallback> mCallback;
::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
diff --git a/threadnetwork/aidl/default/threadnetwork-default.xml b/threadnetwork/aidl/default/threadnetwork-default.xml
new file mode 100644
index 0000000..d7dee1e
--- /dev/null
+++ b/threadnetwork/aidl/default/threadnetwork-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.threadnetwork</name>
+ <fqname>IThreadChip/chip0</fqname>
+ </hal>
+</manifest>
diff --git a/threadnetwork/aidl/default/utils.cpp b/threadnetwork/aidl/default/utils.cpp
new file mode 100644
index 0000000..1cb42ec
--- /dev/null
+++ b/threadnetwork/aidl/default/utils.cpp
@@ -0,0 +1,80 @@
+
+/*
+ * 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.
+ */
+
+#include <openthread/instance.h>
+#include <openthread/logging.h>
+#include <openthread/platform/alarm-milli.h>
+#include <utils/Log.h>
+
+void otLogCritPlat(const char* format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_FATAL, LOG_TAG, format, args);
+ va_end(args);
+}
+
+void otLogWarnPlat(const char* format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, args);
+ va_end(args);
+}
+
+void otLogNotePlat(const char* format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
+ va_end(args);
+}
+
+void otLogInfoPlat(const char* format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
+ va_end(args);
+}
+
+void otLogDebgPlat(const char* format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, args);
+ va_end(args);
+}
+
+void otDumpDebgPlat(const char* aText, const void* aData, uint16_t aDataLength) {
+ constexpr uint16_t kBufSize = 512;
+ char buf[kBufSize];
+
+ if ((aText != nullptr) && (aData != nullptr)) {
+ const uint8_t* data = reinterpret_cast<const uint8_t*>(aData);
+
+ for (uint16_t i = 0; (i < aDataLength) && (i < (kBufSize - 1) / 3); i++) {
+ snprintf(buf + (i * 3), (kBufSize - 1) - (i * 3), "%02x ", data[i]);
+ }
+
+ __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s: %s", aText, buf);
+ }
+}
+
+OT_TOOL_WEAK void otPlatAlarmMilliFired(otInstance* aInstance) {
+ OT_UNUSED_VARIABLE(aInstance);
+}
diff --git a/staging/threadnetwork/aidl/vts/Android.bp b/threadnetwork/aidl/vts/Android.bp
similarity index 71%
rename from staging/threadnetwork/aidl/vts/Android.bp
rename to threadnetwork/aidl/vts/Android.bp
index e2609ed..864e885 100644
--- a/staging/threadnetwork/aidl/vts/Android.bp
+++ b/threadnetwork/aidl/vts/Android.bp
@@ -14,15 +14,6 @@
// limitations under the License.
//
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
cc_test {
name: "VtsHalThreadNetworkTargetTest",
defaults: [
@@ -38,7 +29,7 @@
"libbinder_ndk",
],
static_libs: [
- "android.hardware.threadnetwork-ndk",
+ "android.hardware.threadnetwork-V1-ndk",
],
test_suites: [
"general-tests",
diff --git a/staging/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
similarity index 95%
rename from staging/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
rename to threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
index 3e43f9c..5925b54 100644
--- a/staging/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
+++ b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.cpp
@@ -76,7 +76,6 @@
ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
EXPECT_TRUE(thread_chip->open(callback).isOk());
- EXPECT_EQ(thread_chip->open(callback).getServiceSpecificError(), IThreadChip::ERROR_BUSY);
}
TEST_P(ThreadNetworkAidl, Close) {
@@ -85,7 +84,6 @@
EXPECT_TRUE(thread_chip->open(callback).isOk());
EXPECT_TRUE(thread_chip->close().isOk());
- EXPECT_EQ(thread_chip->close().getExceptionCode(), EX_ILLEGAL_STATE);
}
TEST_P(ThreadNetworkAidl, Reset) {
@@ -93,7 +91,7 @@
ndk::SharedRefBase::make<ThreadChipCallback>([](auto /* data */) {});
EXPECT_TRUE(thread_chip->open(callback).isOk());
- EXPECT_TRUE(thread_chip->reset().isOk());
+ EXPECT_TRUE(thread_chip->hardwareReset().isOk());
}
TEST_P(ThreadNetworkAidl, SendSpinelFrame) {
diff --git a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
index 19830a6..0883de2 100644
--- a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
+++ b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
@@ -95,6 +95,7 @@
Status retval) override {
UsbClientCallbackArgs arg;
if (retval == Status::SUCCESS) {
+ arg.usb_last_port_status.status.portName = currentPortStatus[0].status.portName.c_str();
arg.usb_last_port_status.status.supportedModes =
currentPortStatus[0].status.supportedModes;
arg.usb_last_port_status.status.currentMode = currentPortStatus[0].status.currentMode;
@@ -165,9 +166,12 @@
auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_1);
EXPECT_TRUE(res.no_timeout);
EXPECT_EQ(2, res.args->last_usb_cookie);
- EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.currentMode);
- EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.supportedModes);
- EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
+ // if there are no type-c ports, skip below checks
+ if (!res.args->usb_last_port_status.status.portName.empty()) {
+ EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.currentMode);
+ EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.supportedModes);
+ EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
+ }
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest);
INSTANTIATE_TEST_SUITE_P(
diff --git a/usb/OWNERS b/usb/OWNERS
index 2b1d34d..3611b4d 100644
--- a/usb/OWNERS
+++ b/usb/OWNERS
@@ -1,4 +1,8 @@
# Bug component: 175220
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
albertccwang@google.com
badhri@google.com
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 25d704e..ff9c247 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -34,23 +34,24 @@
package android.hardware.uwb.fira_android;
@Backing(type="int") @VintfStability
enum UwbVendorCapabilityTlvTypes {
- SUPPORTED_POWER_STATS_QUERY = 192,
- CCC_SUPPORTED_CHAPS_PER_SLOT = 160,
- CCC_SUPPORTED_SYNC_CODES = 161,
- CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES = 162,
- CCC_SUPPORTED_CHANNELS = 163,
- CCC_SUPPORTED_VERSIONS = 164,
- CCC_SUPPORTED_UWB_CONFIGS = 165,
- CCC_SUPPORTED_PULSE_SHAPE_COMBOS = 166,
- CCC_SUPPORTED_RAN_MULTIPLIER = 167,
- CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 168,
- CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 169,
- SUPPORTED_AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 227,
- SUPPORTED_MIN_RANGING_INTERVAL_MS = 228,
- SUPPORTED_RANGE_DATA_NTF_CONFIG = 229,
- SUPPORTED_RSSI_REPORTING = 230,
- SUPPORTED_DIAGNOSTICS = 231,
- SUPPORTED_MIN_SLOT_DURATION_RSTU = 232,
- SUPPORTED_MAX_RANGING_SESSION_NUMBER = 233,
- SUPPORTED_CHANNELS_AOA = 234,
+ SUPPORTED_POWER_STATS_QUERY = 0xC0,
+ CCC_SUPPORTED_CHAPS_PER_SLOT = 0xA0,
+ CCC_SUPPORTED_SYNC_CODES = 0xA1,
+ CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES = 0xA2,
+ CCC_SUPPORTED_CHANNELS = 0xA3,
+ CCC_SUPPORTED_VERSIONS = 0xA4,
+ CCC_SUPPORTED_UWB_CONFIGS = 0xA5,
+ CCC_SUPPORTED_PULSE_SHAPE_COMBOS = 0xA6,
+ CCC_SUPPORTED_RAN_MULTIPLIER = 0xA7,
+ CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xA8,
+ CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
+ RADAR_SUPPORT = 0xB0,
+ SUPPORTED_AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 0xE3,
+ SUPPORTED_MIN_RANGING_INTERVAL_MS = 0xE4,
+ SUPPORTED_RANGE_DATA_NTF_CONFIG = 0xE5,
+ SUPPORTED_RSSI_REPORTING = 0xE6,
+ SUPPORTED_DIAGNOSTICS = 0xE7,
+ SUPPORTED_MIN_SLOT_DURATION_RSTU = 0xE8,
+ SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xE9,
+ SUPPORTED_CHANNELS_AOA = 0xEA,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
index 0e33f70..702e561 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
@@ -40,17 +40,19 @@
PULSE_SHAPE_PRECURSOR_FREE = 1,
PULSE_SHAPE_PRECURSOR_FREE_SPECIAL = 2,
CHAPS_PER_SLOT_3 = 1,
- CHAPS_PER_SLOT_4 = 2,
- CHAPS_PER_SLOT_6 = 4,
- CHAPS_PER_SLOT_8 = 8,
- CHAPS_PER_SLOT_9 = 16,
- CHAPS_PER_SLOT_12 = 32,
- CHAPS_PER_SLOT_24 = 64,
- HOPPING_SEQUENCE_DEFAULT = 16,
- HOPPING_SEQUENCE_AES = 8,
- HOPPING_CONFIG_MODE_NONE = 128,
- HOPPING_CONFIG_MODE_CONTINUOUS = 64,
- HOPPING_CONFIG_MODE_ADAPTIVE = 32,
+ CHAPS_PER_SLOT_4 = (1 << 1) /* 2 */,
+ CHAPS_PER_SLOT_6 = (1 << 2) /* 4 */,
+ CHAPS_PER_SLOT_8 = (1 << 3) /* 8 */,
+ CHAPS_PER_SLOT_9 = (1 << 4) /* 16 */,
+ CHAPS_PER_SLOT_12 = (1 << 5) /* 32 */,
+ CHAPS_PER_SLOT_24 = (1 << 6) /* 64 */,
+ HOPPING_SEQUENCE_DEFAULT = (1 << 4) /* 16 */,
+ HOPPING_SEQUENCE_AES = (1 << 3) /* 8 */,
+ HOPPING_CONFIG_MODE_NONE = (1 << 7) /* 128 */,
+ HOPPING_CONFIG_MODE_CONTINUOUS = (1 << 6) /* 64 */,
+ HOPPING_CONFIG_MODE_ADAPTIVE = (1 << 5) /* 32 */,
CCC_CHANNEL_5 = 1,
- CCC_CHANNEL_9 = 2,
+ CCC_CHANNEL_9 = (1 << 1) /* 2 */,
+ RADAR_NOT_SUPPORTED = 0,
+ RADAR_SWEEP_SAMPLES_SUPPORTED = 1,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
index fbcfbff..34bc4ec 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
@@ -34,7 +34,10 @@
package android.hardware.uwb.fira_android;
@Backing(type="byte") @VintfStability
enum UwbVendorGidAndroidOids {
- ANDROID_GET_POWER_STATS = 0,
- ANDROID_SET_COUNTRY_CODE = 1,
- ANDROID_RANGE_DIAGNOSTICS = 2,
+ ANDROID_GET_POWER_STATS = 0x0,
+ ANDROID_SET_COUNTRY_CODE = 0x1,
+ ANDROID_RANGE_DIAGNOSTICS = 0x2,
+ RADAR_SET_APP_CONFIG = 0x11,
+ RADAR_GET_APP_CONFIG = 0x12,
+ RADAR_DATA_NTF = 0x13,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
index 5515c67..f02ed70 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
@@ -34,5 +34,5 @@
package android.hardware.uwb.fira_android;
@Backing(type="byte") @VintfStability
enum UwbVendorGids {
- ANDROID = 12,
+ ANDROID = 0xC,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl
new file mode 100644
index 0000000..760166c
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.uwb.fira_android;
+@Backing(type="int") @VintfStability
+enum UwbVendorRadarAppConfigTlvTypes {
+ RADAR_TIMING_PARAMS = 0x0,
+ SAMPLES_PER_SWEEP = 0x1,
+ RADAR_CHANNEL_NUMBER = 0x2,
+ SWEEP_OFFSET = 0x3,
+ RADAR_RFRAME_CONFIG = 0x4,
+ RADAR_PREAMBLE_DURATION = 0x5,
+ RADAR_PREAMBLE_CODE_INDEX = 0x6,
+ RADAR_SESSION_PRIORITY = 0x7,
+ BITS_PER_SAMPLE = 0x8,
+ RADAR_PRF_MODE = 0x9,
+ NUMBER_OF_BURSTS = 0xA,
+ RADAR_DATA_TYPE = 0xB,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl
new file mode 100644
index 0000000..1eb2ce9
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.uwb.fira_android;
+@Backing(type="int") @VintfStability
+enum UwbVendorRadarAppConfigTlvValues {
+ RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES = 0x0,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorReasonCodes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorReasonCodes.aidl
index a438cbe..db1e0db 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorReasonCodes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorReasonCodes.aidl
@@ -34,7 +34,7 @@
package android.hardware.uwb.fira_android;
@Backing(type="int") @VintfStability
enum UwbVendorReasonCodes {
- REASON_ERROR_INVALID_CHANNEL_WITH_AOA = 128,
- REASON_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 129,
- REASON_REGULATION_UWB_OFF = 130,
+ REASON_ERROR_INVALID_CHANNEL_WITH_AOA = 0x80,
+ REASON_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 0x81,
+ REASON_REGULATION_UWB_OFF = 0x82,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
index c3ac401..d02cf4d 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
@@ -34,16 +34,16 @@
package android.hardware.uwb.fira_android;
@Backing(type="int") @VintfStability
enum UwbVendorSessionAppConfigTlvTypes {
- CCC_HOP_MODE_KEY = 160,
- CCC_UWB_TIME0 = 161,
- CCC_RANGING_PROTOCOL_VER = 163,
- CCC_UWB_CONFIG_ID = 164,
- CCC_PULSESHAPE_COMBO = 165,
- CCC_URSK_TTL = 166,
- CCC_LAST_INDEX_USED = 168,
- NB_OF_RANGE_MEASUREMENTS = 227,
- NB_OF_AZIMUTH_MEASUREMENTS = 228,
- NB_OF_ELEVATION_MEASUREMENTS = 229,
- ENABLE_DIAGNOSTICS = 232,
- DIAGRAMS_FRAME_REPORTS_FIELDS = 233,
+ CCC_HOP_MODE_KEY = 0xA0,
+ CCC_UWB_TIME0 = 0xA1,
+ CCC_RANGING_PROTOCOL_VER = 0xA3,
+ CCC_UWB_CONFIG_ID = 0xA4,
+ CCC_PULSESHAPE_COMBO = 0xA5,
+ CCC_URSK_TTL = 0xA6,
+ CCC_LAST_INDEX_USED = 0xA8,
+ NB_OF_RANGE_MEASUREMENTS = 0xE3,
+ NB_OF_AZIMUTH_MEASUREMENTS = 0xE4,
+ NB_OF_ELEVATION_MEASUREMENTS = 0xE5,
+ ENABLE_DIAGNOSTICS = 0xE8,
+ DIAGRAMS_FRAME_REPORTS_FIELDS = 0xE9,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvValues.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvValues.aidl
index a7f487b..5216e1f 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvValues.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvValues.aidl
@@ -34,5 +34,5 @@
package android.hardware.uwb.fira_android;
@Backing(type="int") @VintfStability
enum UwbVendorSessionAppConfigTlvValues {
- AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 240,
+ AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 0xF0,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
index 30a0a1b..bf968bd 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
@@ -34,5 +34,6 @@
package android.hardware.uwb.fira_android;
@Backing(type="int") @VintfStability
enum UwbVendorSessionInitSessionType {
- CCC = 160,
+ CCC = 0xA0,
+ RADAR = 0xA1,
}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
index 28cf7fe..52f1350 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
@@ -34,8 +34,8 @@
package android.hardware.uwb.fira_android;
@Backing(type="byte") @VintfStability
enum UwbVendorStatusCodes {
- STATUS_ERROR_CCC_SE_BUSY = 80,
- STATUS_ERROR_CCC_LIFECYCLE = 81,
- STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 82,
- STATUS_REGULATION_UWB_OFF = 83,
+ STATUS_ERROR_CCC_SE_BUSY = 0x50,
+ STATUS_ERROR_CCC_LIFECYCLE = 0x51,
+ STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 0x52,
+ STATUS_REGULATION_UWB_OFF = 0x53,
}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/README.md b/uwb/aidl/android/hardware/uwb/fira_android/README.md
index e658d93..7912bbc 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/README.md
+++ b/uwb/aidl/android/hardware/uwb/fira_android/README.md
@@ -10,6 +10,3 @@
All other interactions sent/received over the HAL interface is expected to
comply with the UCI specification that can be found [here](
https://groups.firaconsortium.org/wg/Technical/document/folder/127).
-
-TODO([b/196004116](b/196004116)): Link to the published specification.
-
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 22b7bfe..ceef1be 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -150,6 +150,16 @@
CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
/*********************************************
+ * RADAR specific
+ ********************************************/
+ /**
+ * 1 byte bitmask to indicate the supported Radar data types.
+ * Each "1" in this bitmap corresponds to a specific radar data type where:
+ * 0x01 = "Radar Sweep Samples",
+ */
+ RADAR_SUPPORT = 0xB0,
+
+ /*********************************************
* FIRA specific
********************************************/
/**
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
index 7c86b79..6ef52fe 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
@@ -51,4 +51,10 @@
CCC_CHANNEL_5 = 1,
CCC_CHANNEL_9 = 1 << 1,
+
+ /*********************************************
+ * RADAR specific
+ ********************************************/
+ RADAR_NOT_SUPPORTED = 0,
+ RADAR_SWEEP_SAMPLES_SUPPORTED = 1,
}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
index 4768f55..203b940 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
@@ -37,4 +37,15 @@
// Supported only if the UwbVendorCapabilityTlvTypes.SUPPORTED_DIAGNOSTICS set
// to 1.
ANDROID_RANGE_DIAGNOSTICS = 0x2,
+
+ /*********************************************
+ * Range 0x10 - 0x1F reserved for RADAR specific
+ * Supported only if the UwbVendorCapabilityTlvTypes.RADAR_SUPPORT is not 0x00.
+ ********************************************/
+ // Used to set application configurations for radar session.
+ RADAR_SET_APP_CONFIG = 0x11,
+ // Used to get application configurations for radar session.
+ RADAR_GET_APP_CONFIG = 0x12,
+ // Used to report radar data for certain radar data types.
+ RADAR_DATA_NTF = 0x13,
}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl
new file mode 100644
index 0000000..a5ea688
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvTypes.aidl
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific radar app params set/expected in UCI command:
+ * GID: 1100b (Android specific Group)
+ * OID: 010001b (RADAR_SET_APP_CONFIG_CMD)
+ * OID: 010010b (RADAR_GET_APP_CONFIG_CMD)
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbVendorRadarAppConfigTlvTypes {
+ /**
+ * 7 byte data
+ * Radar frame timing parameters:
+ * Octet [3:0] - BURST_PERIOD
+ * Duration between the start of two consecutive Radar bursts in ms.
+ * Octet [5:4] - SWEEP_PERIOD
+ * Duration between the start times of two consecutive Radar sweeps in
+ * RSTU.
+ * Octet [6] - SWEEPS_PER_BURST
+ * Number of Radar sweeps within the Radar burst.
+ */
+ RADAR_TIMING_PARAMS = 0x0,
+ /**
+ * 1 byte data
+ * The number of samples captured for each radar sweep. (default = 64)
+ */
+ SAMPLES_PER_SWEEP = 0x1,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config.
+ * (default = 9)
+ */
+ RADAR_CHANNEL_NUMBER = 0x2,
+ /**
+ * 2 byte data
+ * Defines the start offset with respect to 0cm distance to limit the sweep
+ * range. Signed value and unit in samples.
+ * (default = 0)
+ */
+ SWEEP_OFFSET = 0x3,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config.
+ * (default = 0x0)
+ */
+ RADAR_RFRAME_CONFIG = 0x4,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config, but extended to 0xA.
+ * (default = 0x2 : 128 symbols)
+ */
+ RADAR_PREAMBLE_DURATION = 0x5,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config, but extended to 127.
+ * (default = 25)
+ */
+ RADAR_PREAMBLE_CODE_INDEX = 0x6,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config.
+ * (default = 50)
+ */
+ RADAR_SESSION_PRIORITY = 0x7,
+ /**
+ * 1 byte data
+ * Bits per sample in the radar sweep.
+ * 0x00 = 32 bits per sample (default)
+ * 0x01 = 48 bits per sample
+ * 0x02 = 64 bits per sample
+ */
+ BITS_PER_SAMPLE = 0x8,
+ /**
+ * 1 byte data
+ * Same as in FiRa UCI Session App Config.
+ * (default = 0x1)
+ */
+ RADAR_PRF_MODE = 0x9,
+ /**
+ * 2 byte data
+ * Maximum number of Radar bursts to be executed in the session. The
+ * session is stopped and moved to SESSION_STATE_IDLE Session State when
+ * configured radar bursts are elapsed.
+ * 0x00 = Unlimited (default)
+ */
+ NUMBER_OF_BURSTS = 0xA,
+ /**
+ * 2 byte data
+ * Type of radar data to be reported.
+ * 0x00: Radar Sweep Samples. Reported in RADAR_DATA_NTF. (default)
+ */
+ RADAR_DATA_TYPE = 0xB,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl
new file mode 100644
index 0000000..81c0a4d
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorRadarAppConfigTlvValues.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific radar app config values set/expected in UCI command:
+ * GID: 1100b (Android specific Group)
+ * OID: 010001b (RADAR_SET_APP_CONFIG_CMD)
+ * OID: 010010b (RADAR_GET_APP_CONFIG_CMD)
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbVendorRadarAppConfigTlvValues {
+ RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES = 0x0,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
index 1e2c817..d3df672 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
@@ -29,4 +29,5 @@
enum UwbVendorSessionInitSessionType {
/** Added in vendor version 0. */
CCC = 0xA0,
+ RADAR = 0xA1,
}
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index 7c2c300..cf32694 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -6,8 +6,8 @@
use async_trait::async_trait;
use binder::{Result, Strong};
-use tokio::fs::File;
-use tokio::io::{AsyncReadExt, AsyncWriteExt};
+use tokio::fs::{self, File};
+use tokio::io::AsyncReadExt;
use tokio::sync::Mutex;
use std::os::fd::AsRawFd;
@@ -22,7 +22,6 @@
callbacks: Strong<dyn IUwbClientCallback>,
#[allow(dead_code)]
tasks: tokio::task::JoinSet<()>,
- write: File,
},
}
@@ -65,17 +64,11 @@
async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
log::debug!("open: {:?}", &self.path);
- let serial = File::open(&self.path)
+ let mut serial = File::open(&self.path)
.await
.and_then(makeraw)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
- let mut read = serial
- .try_clone()
- .await
- .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
- let write = serial;
-
let mut state = self.state.lock().await;
if let State::Closed = *state {
@@ -88,14 +81,16 @@
const UWB_HEADER_SIZE: usize = 4;
let mut buffer = vec![0; UWB_HEADER_SIZE];
- read.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
+ serial
+ .read_exact(&mut buffer[0..UWB_HEADER_SIZE])
.await
.unwrap();
let length = buffer[3] as usize + UWB_HEADER_SIZE;
buffer.resize(length, 0);
- read.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
+ serial
+ .read_exact(&mut buffer[UWB_HEADER_SIZE..length])
.await
.unwrap();
@@ -108,7 +103,6 @@
*state = State::Opened {
callbacks: callbacks.clone(),
tasks,
- write,
};
Ok(())
@@ -155,11 +149,10 @@
async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
log::debug!("sendUciMessage");
- if let State::Opened { write, .. } = &mut *self.state.lock().await {
- write
- .write(data)
+ if let State::Opened { .. } = &mut *self.state.lock().await {
+ fs::write(&self.path, data)
.await
- .map(|written| written as i32)
+ .map(|_| data.len() as i32)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
} else {
Err(binder::ExceptionCode::ILLEGAL_STATE.into())