Merge "No longer allow HIDL bluetooth HAL for new SoCs"
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 652d63c..bd903d7 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -102,7 +102,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(
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..bda0de2 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -65,6 +65,7 @@
],
export_include_dirs: ["include"],
srcs: [
+ "AidlConversionXsdc.cpp",
"AudioPolicyConfigXmlConverter.cpp",
"Bluetooth.cpp",
"Config.cpp",
@@ -92,6 +93,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 +124,19 @@
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_defaults {
diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
index 6290912..2848d71 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),
+ 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 5a83fef..71d111b 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -14,12 +14,17 @@
* limitations under the License.
*/
+#include <optional>
+#include <string>
#define LOG_TAG "AHAL_EffectConfig"
#include <android-base/logging.h>
+#include <system/audio_effects/audio_effects_conf.h>
#include <system/audio_effects/effect_uuid.h>
#include "effectFactory-impl/EffectConfig.h"
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
using aidl::android::media::audio::common::AudioUuid;
namespace aidl::android::hardware::audio::effect {
@@ -55,14 +60,16 @@
// Parse pre processing chains
for (auto& xmlPreprocess : getChildren(xmlConfig, "preprocess")) {
for (auto& xmlStream : getChildren(xmlPreprocess, "stream")) {
- registerFailure(parseStream(xmlStream));
+ // AudioSource
+ registerFailure(parseProcessing(Processing::Type::source, xmlStream));
}
}
// Parse post processing chains
for (auto& xmlPostprocess : getChildren(xmlConfig, "postprocess")) {
for (auto& xmlStream : getChildren(xmlPostprocess, "stream")) {
- registerFailure(parseStream(xmlStream));
+ // AudioStreamType
+ registerFailure(parseProcessing(Processing::Type::streamType, xmlStream));
}
}
}
@@ -140,21 +147,6 @@
return true;
}
-bool EffectConfig::parseStream(const tinyxml2::XMLElement& xml) {
- LOG(DEBUG) << __func__ << dump(xml);
- const char* type = xml.Attribute("type");
- RETURN_VALUE_IF(!type, false, "noTypeInProcess");
- RETURN_VALUE_IF(0 != mProcessingMap.count(type), false, "duplicateType");
-
- for (auto& apply : getChildren(xml, "apply")) {
- const char* name = apply.get().Attribute("effect");
- RETURN_VALUE_IF(!name, false, "noEffectAttribute");
- mProcessingMap[type].push_back(name);
- LOG(DEBUG) << __func__ << " " << type << " : " << name;
- }
- return true;
-}
-
bool EffectConfig::parseLibraryUuid(const tinyxml2::XMLElement& xml,
struct LibraryUuid& libraryUuid, bool isProxy) {
// Retrieve library name only if not effectProxy element
@@ -174,6 +166,80 @@
return true;
}
+std::optional<Processing::Type> EffectConfig::stringToProcessingType(Processing::Type::Tag typeTag,
+ const std::string& type) {
+ // see list of audio stream types in audio_stream_type_t:
+ // system/media/audio/include/system/audio_effects/audio_effects_conf.h
+ // AUDIO_STREAM_DEFAULT_TAG is not listed here because according to SYS_RESERVED_DEFAULT in
+ // AudioStreamType.aidl: "Value reserved for system use only. HALs must never return this value
+ // to the system or accept it from the system".
+ static const std::map<const std::string, AudioStreamType> sAudioStreamTypeTable = {
+ {AUDIO_STREAM_VOICE_CALL_TAG, AudioStreamType::VOICE_CALL},
+ {AUDIO_STREAM_SYSTEM_TAG, AudioStreamType::SYSTEM},
+ {AUDIO_STREAM_RING_TAG, AudioStreamType::RING},
+ {AUDIO_STREAM_MUSIC_TAG, AudioStreamType::MUSIC},
+ {AUDIO_STREAM_ALARM_TAG, AudioStreamType::ALARM},
+ {AUDIO_STREAM_NOTIFICATION_TAG, AudioStreamType::NOTIFICATION},
+ {AUDIO_STREAM_BLUETOOTH_SCO_TAG, AudioStreamType::BLUETOOTH_SCO},
+ {AUDIO_STREAM_ENFORCED_AUDIBLE_TAG, AudioStreamType::ENFORCED_AUDIBLE},
+ {AUDIO_STREAM_DTMF_TAG, AudioStreamType::DTMF},
+ {AUDIO_STREAM_TTS_TAG, AudioStreamType::TTS},
+ {AUDIO_STREAM_ASSISTANT_TAG, AudioStreamType::ASSISTANT}};
+
+ // see list of audio sources in audio_source_t:
+ // system/media/audio/include/system/audio_effects/audio_effects_conf.h
+ static const std::map<const std::string, AudioSource> sAudioSourceTable = {
+ {MIC_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_UL_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_DL_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_CALL_SRC_TAG, AudioSource::VOICE_CALL},
+ {CAMCORDER_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_REC_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_COMM_SRC_TAG, AudioSource::VOICE_CALL},
+ {REMOTE_SUBMIX_SRC_TAG, AudioSource::VOICE_CALL},
+ {UNPROCESSED_SRC_TAG, AudioSource::VOICE_CALL},
+ {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_CALL}};
+
+ if (typeTag == Processing::Type::streamType) {
+ auto typeIter = sAudioStreamTypeTable.find(type);
+ if (typeIter != sAudioStreamTypeTable.end()) {
+ return typeIter->second;
+ }
+ } else if (typeTag == Processing::Type::source) {
+ auto typeIter = sAudioSourceTable.find(type);
+ if (typeIter != sAudioSourceTable.end()) {
+ return typeIter->second;
+ }
+ }
+
+ return std::nullopt;
+}
+
+bool EffectConfig::parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml) {
+ LOG(DEBUG) << __func__ << dump(xml);
+ const char* typeStr = xml.Attribute("type");
+ auto aidlType = stringToProcessingType(typeTag, typeStr);
+ RETURN_VALUE_IF(!aidlType.has_value(), false, "illegalStreamType");
+ RETURN_VALUE_IF(0 != mProcessingMap.count(aidlType.value()), false, "duplicateStreamType");
+
+ for (auto& apply : getChildren(xml, "apply")) {
+ const char* name = apply.get().Attribute("effect");
+ if (mEffectsMap.find(name) == mEffectsMap.end()) {
+ LOG(ERROR) << __func__ << " effect " << name << " doesn't exist, skipping";
+ continue;
+ }
+ RETURN_VALUE_IF(!name, false, "noEffectAttribute");
+ mProcessingMap[aidlType.value()].emplace_back(mEffectsMap[name]);
+ LOG(WARNING) << __func__ << " " << typeStr << " : " << name;
+ }
+ return true;
+}
+
+const std::map<Processing::Type, std::vector<EffectConfig::EffectLibraries>>&
+EffectConfig::getProcessingMap() const {
+ return mProcessingMap;
+}
+
bool EffectConfig::findUuid(const std::string& xmlEffectName, AudioUuid* uuid) {
// Difference from EFFECT_TYPE_LIST_DEF, there could be multiple name mapping to same Effect Type
#define EFFECT_XML_TYPE_LIST_DEF(V) \
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index f0687cc..7073a10 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -15,8 +15,10 @@
*/
#include <dlfcn.h>
+#include <algorithm>
#include <iterator>
#include <memory>
+#include <optional>
#include <tuple>
#include <unordered_set>
#define LOG_TAG "AHAL_EffectFactory"
@@ -52,6 +54,22 @@
}
}
+ndk::ScopedAStatus Factory::getDescriptorWithUuid(const AudioUuid& uuid, Descriptor* desc) {
+ RETURN_IF(!desc, EX_NULL_POINTER, "nullDescriptor");
+
+ if (mEffectLibMap.count(uuid)) {
+ auto& entry = mEffectLibMap[uuid];
+ getDlSyms(entry);
+ auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
+ RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
+ "dlNullQueryEffectFunc");
+ RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&uuid, desc));
+ return ndk::ScopedAStatus::ok();
+ }
+
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
const std::optional<AudioUuid>& in_impl_uuid,
const std::optional<AudioUuid>& in_proxy_uuid,
@@ -69,12 +87,7 @@
for (const auto& id : idList) {
if (mEffectLibMap.count(id.uuid)) {
Descriptor desc;
- auto& entry = mEffectLibMap[id.uuid];
- getDlSyms(entry);
- auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
- RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
- "dlNullQueryEffectFunc");
- RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&id.uuid, &desc));
+ RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(id.uuid, &desc), "getDescriptorFailed");
// update proxy UUID with information from config xml
desc.common.id.proxy = id.proxy;
_aidl_return->emplace_back(std::move(desc));
@@ -85,12 +98,26 @@
ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
std::vector<Processing>* _aidl_return) {
- // TODO: implement this with audio_effect.xml.
- if (in_type.has_value()) {
- // return all matching process filter
- LOG(DEBUG) << __func__ << " process type: " << in_type.value().toString();
+ const auto& processings = mConfig.getProcessingMap();
+ // Processing stream type
+ for (const auto& procIter : processings) {
+ if (!in_type.has_value() || in_type.value() == procIter.first) {
+ Processing process = {.type = procIter.first /* Processing::Type */};
+ for (const auto& libs : procIter.second /* std::vector<struct EffectLibraries> */) {
+ for (const auto& lib : libs.libraries /* std::vector<struct LibraryUuid> */) {
+ Descriptor desc;
+ if (libs.proxyLibrary.has_value()) {
+ desc.common.id.proxy = libs.proxyLibrary.value().uuid;
+ }
+ RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(lib.uuid, &desc),
+ "getDescriptorFailed");
+ process.ids.emplace_back(desc);
+ }
+ }
+ _aidl_return->emplace_back(process);
+ }
}
- LOG(DEBUG) << __func__ << " return " << _aidl_return->size();
+
return ndk::ScopedAStatus::ok();
}
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..6885a49 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -187,7 +187,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;
@@ -281,7 +281,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: "
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index c06742d..6627ae7 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -95,8 +95,17 @@
<libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
</effectProxy>
<effect name="extensioneffect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+ <effect name="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
</effects>
+ <preprocess>
+ <stream type="voice_communication">
+ <apply effect="acoustic_echo_canceler"/>
+ <apply effect="noise_suppression"/>
+ </stream>
+ </preprocess>
+
<!-- Audio pre processor configurations.
The pre processor configuration is described in a "preprocess" element and consists in a
list of elements each describing pre processor settings for a given use case or "stream".
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index dbf2e15..6072d89 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -68,8 +68,7 @@
const Capability BassBoostSw::kCapability = {.range = {BassBoostSw::kRanges}};
const Descriptor BassBoostSw::kDescriptor = {
.common = {.id = {.type = getEffectTypeUuidBassBoost(),
- .uuid = getEffectImplUuidBassBoostSw(),
- .proxy = getEffectImplUuidBassBoostProxy()},
+ .uuid = getEffectImplUuidBassBoostSw()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index ad79a0c..ba867a0 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 301c969..92d6777 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -533,12 +533,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/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp
index 9769924..b2add31 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.cpp
+++ b/audio/aidl/default/equalizer/EqualizerSw.cpp
@@ -88,16 +88,14 @@
MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({0}))};
const Capability EqualizerSw::kEqCap = {.range = EqualizerSw::kRanges};
-const Descriptor EqualizerSw::kDesc = {
- .common = {.id = {.type = getEffectTypeUuidEqualizer(),
- .uuid = getEffectImplUuidEqualizerSw(),
- .proxy = getEffectImplUuidEqualizerProxy()},
- .flags = {.type = Flags::Type::INSERT,
- .insert = Flags::Insert::FIRST,
- .volume = Flags::Volume::CTRL},
- .name = EqualizerSw::kEffectName,
- .implementor = "The Android Open Source Project"},
- .capability = EqualizerSw::kEqCap};
+const Descriptor EqualizerSw::kDesc = {.common = {.id = {.type = getEffectTypeUuidEqualizer(),
+ .uuid = getEffectImplUuidEqualizerSw()},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = EqualizerSw::kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = EqualizerSw::kEqCap};
ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDesc.toString();
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..94501a8 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,8 +36,11 @@
::android::status_t getStatus() const { return mConverter.getStatus(); }
const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
+ const SurroundSoundConfig& getSurroundSoundConfig();
private:
+ static const SurroundSoundConfig& getDefaultSurroundSoundConfig();
+
const std::optional<::android::audio::policy::configuration::AudioPolicyConfiguration>&
getXsdcConfig() const {
return mConverter.getXsdcConfig();
@@ -48,7 +52,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/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 65680df..476f1ff 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -155,20 +155,19 @@
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 transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) = 0;
virtual ::android::status_t standby() = 0;
+ // The method below is called from a thread of the Binder pool. Access to data shared with other
+ // methods of this interface must be done in a thread-safe manner.
+ virtual ::android::status_t setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>&
+ connectedDevices) = 0;
};
class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index df0182c..436e610 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -24,15 +24,16 @@
public:
DriverStub(const StreamContext& context, bool isInput);
::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 transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
::android::status_t standby() override;
+ // Note: called on a different thread.
+ ::android::status_t setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
+ override;
private:
const size_t mFrameSizeBytes;
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 36e64cb..05d889a 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -34,15 +34,16 @@
public:
DriverUsb(const StreamContext& context, bool isInput);
::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 transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
::android::status_t standby() override;
+ // Note: called on a different thread.
+ ::android::status_t setConnectedDevices(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
+ override;
private:
::android::status_t exitStandby();
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/include/effectFactory-impl/EffectConfig.h b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
index c627a27..f8a86e1 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
@@ -26,6 +26,7 @@
#include <cutils/properties.h>
#include <tinyxml2.h>
+#include <aidl/android/hardware/audio/effect/Processing.h>
#include "effect-impl/EffectTypes.h"
namespace aidl::android::hardware::audio::effect {
@@ -39,11 +40,6 @@
public:
explicit EffectConfig(const std::string& file);
- // <library>
- struct Library {
- std::string name;
- std::string path;
- };
struct LibraryUuid {
std::string name; // library name
::aidl::android::media::audio::common::AudioUuid uuid;
@@ -59,13 +55,13 @@
const std::unordered_map<std::string, struct EffectLibraries> getEffectsMap() const {
return mEffectsMap;
}
- const std::unordered_map<std::string, std::vector<std::string>> getProcessingMap() const {
- return mProcessingMap;
- }
static bool findUuid(const std::string& xmlEffectName,
::aidl::android::media::audio::common::AudioUuid* uuid);
+ using ProcessingLibrariesMap = std::map<Processing::Type, std::vector<struct EffectLibraries>>;
+ const ProcessingLibrariesMap& getProcessingMap() const;
+
private:
static constexpr const char* kEffectLibPath[] =
#ifdef __LP64__
@@ -79,8 +75,11 @@
std::unordered_map<std::string, std::string> mLibraryMap;
/* Parsed Effects result */
std::unordered_map<std::string, struct EffectLibraries> mEffectsMap;
- /* Parsed pre/post processing result */
- std::unordered_map<std::string, std::vector<std::string>> mProcessingMap;
+ /**
+ * For parsed pre/post processing result: {key: AudioStreamType/AudioSource, value:
+ * EffectLibraries}
+ */
+ ProcessingLibrariesMap mProcessingMap;
/** @return all `node`s children that are elements and match the tag if provided. */
std::vector<std::reference_wrapper<const tinyxml2::XMLElement>> getChildren(
@@ -94,7 +93,7 @@
*/
bool parseEffect(const tinyxml2::XMLElement& xml);
- bool parseStream(const tinyxml2::XMLElement& xml);
+ bool parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml);
// Function to parse effect.library name and effect.uuid from xml
bool parseLibraryUuid(const tinyxml2::XMLElement& xml, struct LibraryUuid& libraryUuid,
@@ -104,6 +103,9 @@
tinyxml2::XMLPrinter&& printer = {}) const;
bool resolveLibrary(const std::string& path, std::string* resolvedPath);
+
+ std::optional<Processing::Type> stringToProcessingType(Processing::Type::Tag typeTag,
+ const std::string& type);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index b7f63af..ad59ca7 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -107,6 +107,10 @@
const EffectConfig::LibraryUuid& configLib,
const ::aidl::android::media::audio::common::AudioUuid& typeUuidStr,
const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
+
+ ndk::ScopedAStatus getDescriptorWithUuid(
+ const aidl::android::media::audio::common::AudioUuid& uuid, Descriptor* desc);
+
void loadEffectLibs();
/* Get effect_dl_interface_s from library handle */
void getDlSyms(DlEntry& entry);
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/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index 5d1d7fe..9ac1cc9 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -106,10 +106,13 @@
::android::status_t DriverUsb::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;
+ {
+ std::lock_guard guard(mLock);
+ 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) {
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/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
index e34464f..0e8435e 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.cpp
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
@@ -16,6 +16,7 @@
#include <algorithm>
#include <cstddef>
+#include <optional>
#define LOG_TAG "AHAL_VirtualizerSw"
#include <Utils.h>
@@ -76,8 +77,7 @@
const Descriptor VirtualizerSw::kDescriptor = {
.common = {.id = {.type = getEffectTypeUuidVirtualizer(),
- .uuid = getEffectImplUuidVirtualizerSw(),
- .proxy = getEffectImplUuidVirtualizerProxy()},
+ .uuid = getEffectImplUuidVirtualizerSw()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
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/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 7b9477d..9cd6c22 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -267,6 +267,7 @@
TEST_P(EffectFactoryTest, QueryProcess) {
std::vector<Processing> processing;
EXPECT_IS_OK(mEffectFactory->queryProcessing(std::nullopt, &processing));
+ std::set<Processing> processingSet(processing.begin(), processing.end());
Processing::Type streamType =
Processing::Type::make<Processing::Type::streamType>(AudioStreamType::SYSTEM);
@@ -279,7 +280,14 @@
EXPECT_IS_OK(mEffectFactory->queryProcessing(source, &processingFilteredBySource));
EXPECT_TRUE(processing.size() >= processingFilteredByStream.size());
+ EXPECT_TRUE(std::all_of(
+ processingFilteredByStream.begin(), processingFilteredByStream.end(),
+ [&](const auto& proc) { return processingSet.find(proc) != processingSet.end(); }));
+
EXPECT_TRUE(processing.size() >= processingFilteredBySource.size());
+ EXPECT_TRUE(std::all_of(
+ processingFilteredBySource.begin(), processingFilteredBySource.end(),
+ [&](const auto& proc) { return processingSet.find(proc) != processingSet.end(); }));
}
INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
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/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 7f66eca..8aa06f8 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/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/aidl/vts/VtsHalBluetoothTargetTest.cpp b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
index 529e092..e5222a7 100644
--- a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
+++ b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
@@ -14,12 +14,14 @@
* limitations under the License.
*/
+#include <VtsCoreUtil.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/bluetooth/BnBluetoothHciCallbacks.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
#include <aidl/android/hardware/bluetooth/Status.h>
+#include <android-base/properties.h>
#include <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -67,6 +69,7 @@
using ::bluetooth::hci::ReadLocalVersionInformationCompleteView;
static constexpr uint8_t kMinLeAdvSetForBt5 = 16;
+static constexpr uint8_t kMinLeAdvSetForBt5FoTv = 10;
static constexpr uint8_t kMinLeResolvingListForBt5 = 8;
static constexpr size_t kNumHciCommandsBandwidth = 100;
@@ -81,6 +84,40 @@
// To discard Qualcomm ACL debugging
static constexpr uint16_t kAclHandleQcaDebugMessage = 0xedc;
+static int get_vsr_api_level() {
+ int vendor_api_level =
+ ::android::base::GetIntProperty("ro.vendor.api_level", -1);
+ if (vendor_api_level != -1) {
+ return vendor_api_level;
+ }
+
+ // Android S and older devices do not define ro.vendor.api_level
+ vendor_api_level = ::android::base::GetIntProperty("ro.board.api_level", -1);
+ if (vendor_api_level == -1) {
+ vendor_api_level =
+ ::android::base::GetIntProperty("ro.board.first_api_level", -1);
+ }
+
+ int product_api_level =
+ ::android::base::GetIntProperty("ro.product.first_api_level", -1);
+ if (product_api_level == -1) {
+ product_api_level =
+ ::android::base::GetIntProperty("ro.build.version.sdk", -1);
+ EXPECT_NE(product_api_level, -1) << "Could not find ro.build.version.sdk";
+ }
+
+ // VSR API level is the minimum of vendor_api_level and product_api_level.
+ if (vendor_api_level == -1 || vendor_api_level > product_api_level) {
+ return product_api_level;
+ }
+ return vendor_api_level;
+}
+
+static bool isTv() {
+ return testing::deviceSupportsFeature("android.software.leanback") ||
+ testing::deviceSupportsFeature("android.hardware.type.television");
+}
+
class ThroughputLogger {
public:
explicit ThroughputLogger(std::string task)
@@ -914,7 +951,7 @@
ASSERT_EQ(status, std::future_status::ready);
}
-TEST_P(BluetoothAidlTest, Cdd_C_12_1_Bluetooth5Requirements) {
+TEST_P(BluetoothAidlTest, Vsr_Bluetooth5Requirements) {
std::vector<uint8_t> version_event;
send_and_wait_for_cmd_complete(ReadLocalVersionInformationBuilder::Create(),
version_event);
@@ -959,7 +996,12 @@
ASSERT_TRUE(num_adv_set_view.IsValid());
ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS, num_adv_set_view.GetStatus());
auto num_adv_set = num_adv_set_view.GetNumberSupportedAdvertisingSets();
- ASSERT_GE(num_adv_set, kMinLeAdvSetForBt5);
+
+ if (isTv() && get_vsr_api_level() == __ANDROID_API_U__) {
+ ASSERT_GE(num_adv_set, kMinLeAdvSetForBt5FoTv);
+ } else {
+ ASSERT_GE(num_adv_set, kMinLeAdvSetForBt5);
+ }
std::vector<uint8_t> num_resolving_list_event;
send_and_wait_for_cmd_complete(LeReadResolvingListSizeBuilder::Create(),
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/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/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index ceb7870..637f1da 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -134,7 +134,7 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.face</name>
<version>2</version>
<interface>
@@ -142,7 +142,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>2</version>
<interface>
@@ -629,14 +629,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>
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 2ec98d4..0ddb236 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/identity/aidl/vts/Util.cpp b/identity/aidl/vts/Util.cpp
index 4f5c121..ad9281c 100644
--- a/identity/aidl/vts/Util.cpp
+++ b/identity/aidl/vts/Util.cpp
@@ -73,7 +73,7 @@
ndkMacedPublicKey.macedKey = macedPublicKey.macedKey;
vector<uint8_t> publicKeyBits;
- check_maced_pubkey(ndkMacedPublicKey, /*testMode=*/true, &publicKeyBits);
+ check_maced_pubkey(ndkMacedPublicKey, /*testMode=*/false, &publicKeyBits);
::aidl::android::hardware::security::keymint::EVP_PKEY_Ptr publicKey;
p256_pub_key(publicKeyBits, &publicKey);
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 94d4c88..eb74fa2 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -125,7 +125,8 @@
MacedPublicKey macedPublicKey;
std::vector<uint8_t> attestationKey;
- result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+ // Start by RPC version 3, we don't support testMode=true. So just verify testMode=false here.
+ result = rpc->generateEcdsaP256KeyPair(/*testMode=*/false, &macedPublicKey, &attestationKey);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
@@ -176,7 +177,8 @@
MacedPublicKey macedPublicKey;
std::vector<uint8_t> attestationKey;
- result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+ // Start by RPC version 3, we don't support testMode=true. So just verify testMode=false here.
+ result = rpc->generateEcdsaP256KeyPair(/*testMode=*/false, &macedPublicKey, &attestationKey);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
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/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index f9a02ba..e1dfcfc 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -30,13 +30,17 @@
"keymaster_hidl_hal_test.cpp",
],
srcs: [
+ "BootloaderStateTest.cpp",
"HmacKeySharingTest.cpp",
"VerificationTokenTest.cpp",
"keymaster_hidl_hal_test.cpp",
],
static_libs: [
"android.hardware.keymaster@4.0",
+ "libavb_user",
+ "libavb",
"libcrypto_static",
+ "libfs_mgr",
"libkeymaster4support",
"libkeymaster4vtstest",
],
@@ -64,6 +68,7 @@
],
static_libs: [
"android.hardware.keymaster@4.0",
+ "libcrypto_static",
"libkeymaster4support",
],
}
diff --git a/keymaster/4.0/vts/functional/BootloaderStateTest.cpp b/keymaster/4.0/vts/functional/BootloaderStateTest.cpp
new file mode 100644
index 0000000..912b59b
--- /dev/null
+++ b/keymaster/4.0/vts/functional/BootloaderStateTest.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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 <optional>
+#include <string>
+#include <vector>
+
+#include <android-base/properties.h>
+#include <fstab/fstab.h>
+#include <libavb/libavb.h>
+#include <libavb_user/avb_ops_user.h>
+
+#include "KeymasterHidlTest.h"
+
+namespace android::hardware::keymaster::V4_0::test {
+
+using ::std::string;
+using ::std::vector;
+
+// Since this test needs to talk to Keymaster HAL, it can only run as root. Thus,
+// bootloader can not be locked.
+class BootloaderStateTest : public KeymasterHidlTest {
+ public:
+ virtual void SetUp() override {
+ KeymasterHidlTest::SetUp();
+
+ // Generate a key.
+ auto ec = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256));
+ ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate key.";
+
+ // Generate attestation.
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ ec = AttestKey(AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+ &cert_chain);
+ ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate attestation.";
+
+ X509_Ptr cert(parse_cert_blob(cert_chain[0]));
+ ASSERT_TRUE(cert.get()) << "Failed to parse certificate blob.";
+
+ ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+ ASSERT_TRUE(attest_rec) << "Failed to get attestation record.";
+
+ // Parse root of trust.
+ auto result = parse_root_of_trust(attest_rec->data, attest_rec->length, &attestedVbKey_,
+ &attestedVbState_, &attestedBootloaderState_,
+ &attestedVbmetaDigest_);
+ ASSERT_EQ(result, ErrorCode::OK) << "Failed to parse root of trust.";
+ }
+
+ hidl_vec<uint8_t> attestedVbKey_;
+ keymaster_verified_boot_t attestedVbState_;
+ bool attestedBootloaderState_;
+ hidl_vec<uint8_t> attestedVbmetaDigest_;
+};
+
+// Check that attested bootloader state is set to unlocked.
+TEST_P(BootloaderStateTest, BootloaderIsUnlocked) {
+ ASSERT_FALSE(attestedBootloaderState_)
+ << "This test runs as root. Bootloader must be unlocked.";
+}
+
+// Check that verified boot state is set to "unverified", i.e. "orange".
+TEST_P(BootloaderStateTest, VbStateIsUnverified) {
+ // Unlocked bootloader implies that verified boot state must be "unverified".
+ ASSERT_EQ(attestedVbState_, KM_VERIFIED_BOOT_UNVERIFIED)
+ << "Verified boot state must be \"UNVERIFIED\" aka \"orange\".";
+
+ // AVB spec stipulates that bootloader must set "androidboot.verifiedbootstate" parameter
+ // on the kernel command-line. This parameter is exposed to userspace as
+ // "ro.boot.verifiedbootstate" property.
+ auto vbStateProp = ::android::base::GetProperty("ro.boot.verifiedbootstate", "");
+ ASSERT_EQ(vbStateProp, "orange")
+ << "Verified boot state must be \"UNVERIFIED\" aka \"orange\".";
+}
+
+// Following error codes from avb_slot_data() mean that slot data was loaded
+// (even if verification failed).
+static inline bool avb_slot_data_loaded(AvbSlotVerifyResult result) {
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Check that attested vbmeta digest is correct.
+TEST_P(BootloaderStateTest, VbmetaDigest) {
+ AvbSlotVerifyData* avbSlotData;
+ auto suffix = fs_mgr_get_slot_suffix();
+ const char* partitions[] = {nullptr};
+ auto avbOps = avb_ops_user_new();
+
+ // For VTS, devices run with vendor_boot-debug.img, which is not release key
+ // signed. Use AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR to bypass avb
+ // verification errors. This is OK since we only care about the digest for
+ // this test case.
+ auto result = avb_slot_verify(avbOps, partitions, suffix.c_str(),
+ AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
+ AVB_HASHTREE_ERROR_MODE_EIO, &avbSlotData);
+ ASSERT_TRUE(avb_slot_data_loaded(result)) << "Failed to load avb slot data";
+
+ // Unfortunately, bootloader is not required to report the algorithm used
+ // to calculate the digest. There are only two supported options though,
+ // SHA256 and SHA512. Attested VBMeta digest must match one of these.
+ vector<uint8_t> digest256(AVB_SHA256_DIGEST_SIZE);
+ vector<uint8_t> digest512(AVB_SHA512_DIGEST_SIZE);
+
+ avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA256,
+ digest256.data());
+ avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA512,
+ digest512.data());
+
+ ASSERT_TRUE((attestedVbmetaDigest_ == digest256) || (attestedVbmetaDigest_ == digest512))
+ << "Attested digest does not match computed digest.";
+}
+
+INSTANTIATE_KEYMASTER_HIDL_TEST(BootloaderStateTest);
+
+} // namespace android::hardware::keymaster::V4_0::test
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index 315a4bd..e2ad0ef 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -841,6 +841,30 @@
return {};
}
+X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) {
+ const uint8_t* p = blob.data();
+ return d2i_X509(nullptr, &p, blob.size());
+}
+
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
+ ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+ EXPECT_TRUE(!!oid.get());
+ if (!oid.get()) return nullptr;
+
+ int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+ EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
+ if (location == -1) return nullptr;
+
+ X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+ EXPECT_TRUE(!!attest_rec_ext)
+ << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug.";
+ if (!attest_rec_ext) return nullptr;
+
+ ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+ EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
+ return attest_rec;
+}
+
} // namespace test
} // namespace V4_0
} // namespace keymaster
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index ad30aa7..67829ec 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -22,7 +22,9 @@
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
+#include <keymasterV4_0/attestation_record.h>
#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/openssl_utils.h>
namespace android {
namespace hardware {
@@ -241,6 +243,11 @@
testing::ValuesIn(KeymasterHidlTest::build_params()), \
android::hardware::PrintInstanceNameToString)
+X509* parse_cert_blob(const hidl_vec<uint8_t>& blob);
+// Extract attestation record from cert. Returned object is still part of cert; don't free it
+// separately.
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
+
} // namespace test
} // namespace V4_0
} // namespace keymaster
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 728cc91..96580c0 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -263,11 +263,6 @@
void operator()(RSA* p) { RSA_free(p); }
};
-X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) {
- const uint8_t* p = blob.data();
- return d2i_X509(nullptr, &p, blob.size());
-}
-
bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain, const std::string& msg,
const std::string& signature) {
{
@@ -337,27 +332,6 @@
return true;
}
-// Extract attestation record from cert. Returned object is still part of cert; don't free it
-// separately.
-ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
- ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
- EXPECT_TRUE(!!oid.get());
- if (!oid.get()) return nullptr;
-
- int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
- EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
- if (location == -1) return nullptr;
-
- X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
- EXPECT_TRUE(!!attest_rec_ext)
- << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug.";
- if (!attest_rec_ext) return nullptr;
-
- ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
- EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
- return attest_rec;
-}
-
bool tag_in_list(const KeyParameter& entry) {
// Attestations don't contain everything in key authorization lists, so we need to filter
// the key lists to produce the lists that we expect to match the attestations.
@@ -2475,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);
@@ -2490,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/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index c035f19..a868c96 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -80,7 +80,13 @@
return "";
}
- return ::android::base::Trim(out[0]);
+ 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;
+ return "";
+ }
+
+ return imei;
}
} // namespace
@@ -972,7 +978,7 @@
// Skip the test if there is no second IMEI exists.
string second_imei = get_imei(1);
- if (second_imei.empty() || second_imei.compare("null") == 0) {
+ if (second_imei.empty()) {
GTEST_SKIP() << "Test not applicable as there is no second IMEI";
}
@@ -1050,13 +1056,13 @@
// Skip the test if there is no first IMEI exists.
string imei = get_imei(0);
- if (imei.empty() || imei.compare("null") == 0) {
+ if (imei.empty()) {
GTEST_SKIP() << "Test not applicable as there is no first IMEI";
}
// Skip the test if there is no second IMEI exists.
string second_imei = get_imei(1);
- if (second_imei.empty() || second_imei.compare("null") == 0) {
+ if (second_imei.empty()) {
GTEST_SKIP() << "Test not applicable as there is no second IMEI";
}
diff --git a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
index 6892442..4f72f67 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.).
@@ -408,12 +411,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:
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index a8ea407..b55e609 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -174,6 +174,7 @@
bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
bool KeyMintAidlTestBase::dump_Attestations = false;
std::string KeyMintAidlTestBase::keyblob_dir;
+std::optional<bool> KeyMintAidlTestBase::expect_upgrade = std::nullopt;
uint32_t KeyMintAidlTestBase::boot_patch_level(
const vector<KeyCharacteristics>& key_characteristics) {
@@ -1605,7 +1606,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) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 30ac452..415a83e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -70,6 +70,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 {
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index bdec4d3..c54a2c9 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -8718,6 +8718,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/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/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/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 9f0f30d..0a645fc 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -379,7 +379,7 @@
break;
}
case FrontendStatusTypeExt1_1::UEC: {
- ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec());
+ ASSERT_TRUE(realStatuses[i].uec() >= 0 );
break;
}
case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index 669fa11..dcdc673 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -86,7 +86,7 @@
types.push_back(FrontendStatusTypeExt1_1::IS_MISO);
vector<FrontendStatusExt1_1> statuses;
FrontendStatusExt1_1 status;
- status.uec(4);
+ status.uec(0);
statuses.push_back(status);
status.isMiso(true);
statuses.push_back(status);
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/wifi/1.6/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.6/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 5b5e623..0572ac6 100644
--- a/wifi/1.6/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.6/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -78,6 +78,13 @@
virtual void TearDown() override { stopWifi(GetInstanceName()); }
+ RttCapabilities getRttCapabilities() {
+ std::pair<WifiStatus, RttCapabilities> status_and_caps;
+ status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_6);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+ return status_and_caps.second;
+ }
+
// A simple test implementation of WifiRttControllerEventCallback.
class WifiRttControllerEventCallback
: public ::testing::VtsHalHidlTargetCallbackBase<WifiRttControllerHidlTest>,
@@ -151,12 +158,9 @@
* This test case tests the two sided ranging - 802.11mc FTM protocol.
*/
TEST_P(WifiRttControllerHidlTest, Request2SidedRangeMeasurement) {
- std::pair<WifiStatus, RttCapabilities> status_and_caps;
-
// Get the Capabilities
- status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_6);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
- if (!status_and_caps.second.rttFtmSupported) {
+ RttCapabilities capabilities = getRttCapabilities();
+ if (!capabilities.rttFtmSupported) {
GTEST_SKIP() << "Skipping two sided RTT since driver/fw doesn't support";
}
std::vector<RttConfig> configs;
@@ -196,19 +200,16 @@
* rangeRequest_1_6
*/
TEST_P(WifiRttControllerHidlTest, RangeRequest_1_6) {
- std::pair<WifiStatus, RttCapabilities> status_and_caps;
-
// Get the Capabilities
- status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_6);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
- if (!status_and_caps.second.rttOneSidedSupported) {
+ RttCapabilities capabilities = getRttCapabilities();
+ if (!capabilities.rttOneSidedSupported) {
GTEST_SKIP() << "Skipping one sided RTT since driver/fw doesn't support";
}
// Get the highest support preamble
int preamble = 1;
- status_and_caps.second.preambleSupport >>= 1;
- while (status_and_caps.second.preambleSupport != 0) {
- status_and_caps.second.preambleSupport >>= 1;
+ capabilities.preambleSupport >>= 1;
+ while (capabilities.preambleSupport != 0) {
+ capabilities.preambleSupport >>= 1;
preamble <<= 1;
}
std::vector<RttConfig> configs;
@@ -259,9 +260,14 @@
* getResponderInfo_1_6
*/
TEST_P(WifiRttControllerHidlTest, GetResponderInfo_1_6) {
- std::pair<WifiStatus, RttResponder> status_and_info;
+ // Get the capabilities
+ RttCapabilities capabilities = getRttCapabilities();
+ if (!capabilities.responderSupported) {
+ GTEST_SKIP() << "Skipping because responder is not supported";
+ }
// Invoke the call
+ std::pair<WifiStatus, RttResponder> status_and_info;
status_and_info = HIDL_INVOKE(wifi_rtt_controller_, getResponderInfo_1_6);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_info.first.code);
}
@@ -270,6 +276,12 @@
* enableResponder_1_6
*/
TEST_P(WifiRttControllerHidlTest, EnableResponder_1_6) {
+ // Get the capabilities
+ RttCapabilities capabilities = getRttCapabilities();
+ if (!capabilities.responderSupported) {
+ GTEST_SKIP() << "Skipping because responder is not supported";
+ }
+
std::pair<WifiStatus, RttResponder> status_and_info;
int cmdId = 55;
WifiChannelInfo channelInfo;