Merge "Add a new utility class wifi_hidl_test_utils_1_6 for the Wifi VTS tests." into udc-dev am: 5df702513f am: 96003ab7f3
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/23571908
Change-Id: I81547a595e9e178f2239c424f2a756e5cc9568e6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 305c924..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(
@@ -111,30 +112,6 @@
device == ::aidl::android::media::audio::common::AudioDeviceType::OUT_TELEPHONY_TX;
}
-constexpr bool isUsbInputDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
- switch (type) {
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_DOCK:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_ACCESSORY:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_DEVICE:
- case ::aidl::android::media::audio::common::AudioDeviceType::IN_HEADSET:
- return true;
- default:
- return false;
- }
-}
-
-constexpr bool isUsbOutputtDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
- switch (type) {
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DOCK:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_ACCESSORY:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DEVICE:
- case ::aidl::android::media::audio::common::AudioDeviceType::OUT_HEADSET:
- return true;
- default:
- return false;
- }
-}
-
constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode mode) {
return std::find(kValidAudioModes.begin(), kValidAudioModes.end(), mode) !=
kValidAudioModes.end();
diff --git a/audio/aidl/default/AidlConversionXsdc.cpp b/audio/aidl/default/AidlConversionXsdc.cpp
new file mode 100644
index 0000000..c404d67
--- /dev/null
+++ b/audio/aidl/default/AidlConversionXsdc.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_AidlXsdc"
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+
+#include "core-impl/AidlConversionXsdc.h"
+
+using aidl::android::media::audio::common::AudioFormatDescription;
+
+namespace xsd = android::audio::policy::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<AudioFormatDescription> xsdc2aidl_AudioFormatDescription(const std::string& xsdc) {
+ return legacy2aidl_audio_format_t_AudioFormatDescription(::android::formatFromString(xsdc));
+}
+
+ConversionResult<SurroundSoundConfig::SurroundFormatFamily> xsdc2aidl_SurroundFormatFamily(
+ const ::xsd::SurroundFormats::Format& xsdc) {
+ SurroundSoundConfig::SurroundFormatFamily aidl;
+ aidl.primaryFormat = VALUE_OR_RETURN(xsdc2aidl_AudioFormatDescription(xsdc.getName()));
+ if (xsdc.hasSubformats()) {
+ aidl.subFormats = VALUE_OR_RETURN(convertContainer<std::vector<AudioFormatDescription>>(
+ xsdc.getSubformats(), xsdc2aidl_AudioFormatDescription));
+ }
+ return aidl;
+}
+
+ConversionResult<SurroundSoundConfig> xsdc2aidl_SurroundSoundConfig(
+ const ::xsd::SurroundSound& xsdc) {
+ SurroundSoundConfig aidl;
+ if (!xsdc.hasFormats() || !xsdc.getFirstFormats()->hasFormat()) return aidl;
+ aidl.formatFamilies = VALUE_OR_RETURN(
+ convertContainer<std::vector<SurroundSoundConfig::SurroundFormatFamily>>(
+ xsdc.getFirstFormats()->getFormat(), xsdc2aidl_SurroundFormatFamily));
+ return aidl;
+}
+
+} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index c9edae0..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/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/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index fabb93b..e2bc833 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -33,14 +33,19 @@
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_6;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_PENTA;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_QUAD;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+ enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_TRI;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index d57790a..9a3a447 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -535,12 +535,17 @@
<xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_MONO"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_STEREO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_TRI"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_6"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_2POINT0POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_3POINT0POINT2"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_QUAD"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_PENTA"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_5POINT1"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO"/>
<xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO"/>
diff --git a/audio/aidl/default/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/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/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index ecdbd5c..28116ae 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -30,13 +30,13 @@
#include "alsa_device_profile.h"
}
-using aidl::android::hardware::audio::common::isUsbInputDeviceType;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
@@ -117,7 +117,7 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- const bool isInput = isUsbInputDeviceType(devicePort.device.type.type);
+ const bool isInput = audioPort->flags.getTag() == AudioIoFlags::input;
alsa_device_profile profile;
profile_init(&profile, isInput ? PCM_IN : PCM_OUT);
profile.card = alsaAddress[0];
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/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/common/all-versions/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
index 757f8a8..c6a3963 100644
--- a/audio/common/all-versions/test/utility/Android.bp
+++ b/audio/common/all-versions/test/utility/Android.bp
@@ -62,6 +62,5 @@
"libxml2",
"liblog",
],
- static_libs: ["libgtest"],
test_suites: ["general-tests"],
}
diff --git a/audio/policy/1.0/xml/pfw_schemas/Android.bp b/audio/policy/1.0/xml/pfw_schemas/Android.bp
index 5d669c2..225c065 100644
--- a/audio/policy/1.0/xml/pfw_schemas/Android.bp
+++ b/audio/policy/1.0/xml/pfw_schemas/Android.bp
@@ -11,6 +11,7 @@
name: "audio_policy_engine_configurable_configuration_V1_0",
srcs: ["AllSchemas.xsd"],
package_name: "audio.policy.configurable.V1_0",
+ root_elements: ["ParameterFrameworkConfiguration"],
}
// Unfortunately, all rules only have a single output, thus
diff --git a/audio/policy/1.0/xml/pfw_schemas/api/current.txt b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
index c2fb6fc..2b83e60 100644
--- a/audio/policy/1.0/xml/pfw_schemas/api/current.txt
+++ b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
@@ -470,23 +470,7 @@
public class XmlParser {
ctor public XmlParser();
- method public static audio.policy.configurable.V1_0.BitParameterBlock readBitParameterBlock(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.BooleanParameter readBooleanParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ConfigurableDomainType readConfigurableDomainType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.ConfigurableDomains readConfigurableDomains(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.EnumParameterType readEnumParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.FixedPointParameterType readFixedPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.FloatingPointParameterType readFloatingPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.IntegerParameterType readIntegerParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.LinearAdaptationType readLinearAdaptationType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.LogarithmicAdaptation readLogarithmicAdaptation(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static audio.policy.configurable.V1_0.ParameterFrameworkConfiguration readParameterFrameworkConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.StringParameter readStringParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SubsystemPlugins readSubsystemPlugins(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SubsystemType readSubsystemType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static audio.policy.configurable.V1_0.SystemClass readSystemClass(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 876a91f..82ad917 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -7,11 +7,21 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
+filegroup {
+ name: "face-default.rc",
+ srcs: ["face-default.rc"],
+}
+
+filegroup {
+ name: "face-default.xml",
+ srcs: ["face-default.xml"],
+}
+
cc_binary {
name: "android.hardware.biometrics.face-service.example",
relative_install_path: "hw",
- init_rc: ["face-default.rc"],
- vintf_fragments: ["face-default.xml"],
+ init_rc: [":face-default.rc"],
+ vintf_fragments: [":face-default.xml"],
vendor: true,
shared_libs: [
"libbase",
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..2f39a08
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+ name: "com.android.hardware.biometrics.face.key",
+ public_key: "com.android.hardware.biometrics.face.avbpubkey",
+ private_key: "com.android.hardware.biometrics.face.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.biometrics.face.certificate",
+ certificate: "com.android.hardware.biometrics.face",
+}
+
+apex {
+ name: "com.android.hardware.biometrics.face",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.biometrics.face.key",
+ certificate: ":com.android.hardware.biometrics.face.certificate",
+ updatable: false,
+
+ vendor: true,
+ use_vndk_as_stable: true,
+
+ binaries: [
+ // hal
+ "android.hardware.biometrics.face-service.example",
+ ],
+ prebuilts: [
+ // init_rc
+ "face-default-apex.rc",
+ // vintf_fragment
+ "face-default-apex.xml",
+ // permission
+ "android.hardware.biometrics.face.prebuilt.xml",
+ ],
+
+ overrides: [
+ "android.hardware.biometrics.face-service.example",
+ ],
+}
+
+prebuilt_etc {
+ name: "face-default-apex.rc",
+ src: ":gen-face-default-apex.rc",
+ vendor: true,
+ installable: false,
+}
+
+genrule {
+ name: "gen-face-default-apex.rc",
+ srcs: [":face-default.rc"],
+ out: ["face-default-apex.rc"],
+ cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "face-default-apex.xml",
+ src: ":face-default.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ installable: false,
+}
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
new file mode 100644
index 0000000..9f358ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
new file mode 100644
index 0000000..ad8f57d
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCoZ28KVXxB9kkX
+zPhi8pVSmiMU0xchU4PkoOvFzmr9t5b7rA1zmzOLjkNWMrxt1XCUEfOgT3N50z5T
+484dpEZBrwIH31NqSOr/T8mG5frZAkNg0WqfgV+AG81mCuA+nG4a08fmDL4nEzVg
+irQvWpXzRCNIn+LEx+gG4I2KG8EGWDiFnzXwSFJG4n60rfLQNHgsejv/06BmPCnS
+gp06LhqJTO2oJKCJVQxfO0TPNUd9FSVSXdWuHcHE2gwoHM/7C/10Bdx8XXCMbAQR
+a4d3moH5oRuhh1841PtIQ0ozw/vHapCTmdMbjmgbwpXZ49DfvJl2cnz5c5G/CUO1
+9CkLDdxffsHh48jLUzH1nRgcWW2CAnSIs8nGjScyOKB+gn831ke8agJGbVHs1Cp/
+ONbMZeQIhEL0kderI1vVoufeBf38/I93rpz6PXp5NiTwOnVdEik595/W7oldr/rM
+taKvWwfnjml+Z1uzJWWDKPnS+onxBVcoBGFhiewIejPz3UjncMiHW5QAx/BzfGgh
+UmFO0vsh8qrEfAqT4AqL4uCuyVm0JmugdWKoeQISh5i4+HMmvPaudd+8yF0plr10
++pyNGkLZm4NBJxOD7V0AMjfTIpKRbmV8xnCAnWQ+xx/qWxHAZ0wfbZXXF0m6L6po
+dVwJJI7EnuQbAkbXnzMtCTQToZTSVwIDAQABAoICAAGjGJNY15kYKO3xzXWMyfXT
+gl7L9Im1TNVwP3Dpu+S7U0NSd1w12Iju35znzlwhx7/j8skOrKubaZvM9ztJ79Yb
+1CDs3PWhP6OVJeGvvHU9zkp59RexQ5Ma8hXskIroE2WJ97bQgRkfi/r9x8wKc39T
+aYv/SrTC0SPr+YRFSjMvfV35kvLC759slgwkmsH6ZWatSeyhPooJfX1kTRBi08A2
+i4lOBD+Bhtn2jG/+1eYtFyYXVaHx/E9XfU6QhSPgIhBULdujPucmj6pc4yRYnKxA
+32QxGc35u0QHEqJ9/iWAoporIMAmU/Qp7phl9g+OvxrFkloMc3cp3GSMh8k2bJUY
+nRvk0IPG1bF7jwezHbQGTwTlguJlWPl3+v+qeKJQI4pov3Cz6aNrBmBfEbjwcJrf
+RvPNCQ2X1GciZcGoJxcHRgFNKarzb+m92qNRftr6YDBZM8PlvJgGhnTRkOuFmIZB
+WPRergEwaClp1DbQsXwKlWpGfSMLznj57oKT3MJ31R4pusfMDBS39p9jUFH7uO+p
+e/Wdy+RaKei4AYBZIc+ks8LJzeIG+YWD9kN0lPVvzoza6nJYGGNVe/bxErjpESsR
+fZDs5EMNPGsCQ56Tgt+vtHEGF3x7ufGMF1XqisCMlaxH03aT2N3Wi5um8jO2pfFC
+4NEBq4ixvlyefb0TER+5AoIBAQC6nSDDzeeseLOJ8QSb1kHHkvQOGb8kdYY/KJ51
++uiwoEWOYAxKubqumo2rYaqcM0lbZKWb/9cgVK4LAzdqY4z3BINA7YRzXSUXdb8T
+rbqtg33Yj7f1KBiBqns2FMktfIZ+6JUDALb+CD7rHGpi62RDd8JaKL8wugqMBmwM
+YHBfzECVSjDosjGpbILbDJPTfiEQLyPEoJxJ48Z3Xg6l+0BSZrrH9FqGVgsvEQ7f
+zhZ6rpJIefb1cFjwIRFORS4tMqS1keu+dugyUBs83AOp5kaq6O31n5hDAOyZVFsw
+HSBu8pbWAceWJrF7R1Am23063hIztjPbU9yeN2mvhVQSgO4PAoIBAQDnBQHt3prI
+AajCYbHmk0v1WT2kDD5yEX/fZzifTU5k/+0Jvixpa0KOR2qaUXyx4ocIT6F1hR89
+VXGby2UG6SlvuwXMzwmoVf5sueQ6wshu3fCaS8BYNpJnOAfgLTnUpKIWITDm/2Hj
+4NCFYL77EfBXXhFH7lLPhiPcTWQlPDuFCXU/BJuVhJbpd+GtF1+loiNQArg9nmKb
+9Ac7ccR9UBO/XSQN1th4+yaxyGQKaiYsBqsy8SPp2ynTdGXT72LePqSUrkNsjgE7
+PkzgX0pBZw8upBXk+8ByfIaaQONRbCuMQEXj6B66szaWeR2hDfaoDOk3/w6JN93r
+yPKfk4TFNB85AoIBAGoiHVVfUOjViP7l9cIPvD+eQ3GVkRFSSfS3zE+7UQXLUWPl
+GniRYywUuIgFNvw5avowpsOvYRGBN68JuEWosq52gZO2wkK+ce8Cx5aQkwBGLZey
+PWSP1khAxmx+q+BT10ZsTvtzN6AI3ofnFFaIG/EHNqECVaKH3KHAsUjkvGSvjPeb
+R2/AkOAT1+RvJc/+Bx3mQYh99AVOJz0SYHBkEjQLOyWnwqhuXVP6dqQw2LYTfRz9
+SMhUijCgDfCfBeEs0WJ2yEX96Jdc2fDmDKtfTUe8zEGK8BUDfIzD3kzh8+VF0SWL
+w5CRFxXO/DXtVS7ayC1i7eFKs8nEKDZsNOGFNF8CggEAKXRMlFKNk7Y4gijls2pb
+Bvusg/NugSmCuKPdFTjaCGWkM0tczM3ic4V9K5PTvFfZwzQG1P++S1M5v6sPxd2x
+AcudjtLX+Mz1iq0QtzqcnMhWlFljenDQdJUpVKDI789bBn2OOOU6u5lr0YM6wfLG
+HedTUoUBdxuq860vez8DryuzTkuVX48bRWmtpVG8aAxgKctTJDt3lmSDp7cSeyoT
+YRNllNYoogzvNJew2+2QS/YmYk3DFAOvzbHlU9Jw+1BiWAutLZ2NuwPC58AxourL
+XqMzCpPiRKjzvlpGcCXo6pHd+Ld+TCI8eWPiXTQUPrOSZenuwdC0kcrNPrVJ7dkc
+gQKCAQEAmE6BTX7nn0HT859PtBlsy3rM8psihR4UYuYkTdE0+KF4hBRIP6uhMAVh
+vV6UMnt3QubKIekG14seGkwkBnEhv5reYWn/1+t3qP7qqvgndGgI2yPbzJx/cPMK
++KKhRbBAIgkjiY6hlo+DhrNS5nuBjZS2q/NnkO4NK7qBHvpIYAnRZK9qNsT4KZm6
+EO9YlCCnoZ3EB7brNgBZkxoekZG4jTlpD0E7nTxPTF1iVWedKRfmLFxAiDaSz0eo
+9tbTaRQ6ybU6jl1hMg4aINjp4xl/ScKk51veKg5ptjpPtspIh7keJRIUz3qwhuvk
+ZJpVwCxgxAOagrQtvwdedbmvChAfGA==
+-----END PRIVATE KEY-----
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8 b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
new file mode 100644
index 0000000..af0ff4e
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
new file mode 100644
index 0000000..3dc37ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF7TCCA9UCFCmJBOOYRVUgdy8vKm8OQd0ii2pPMA0GCSqGSIb3DQEBCwUAMIGx
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEtMCsGA1UEAwwkY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5mYWNlMCAXDTIzMDUyNTA2NDIw
+MFoYDzQ3NjEwNDIwMDY0MjAwWjCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJv
+aWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k
+cm9pZC5jb20xLTArBgNVBAMMJGNvbS5hbmRyb2lkLmhhcmR3YXJlLmJpb21ldHJp
+Y3MuZmFjZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPadnCNPEvKN
+HxACZt3C+tE2rga6gZ1pxfvlwGo1UY9yAxcQjL22SW93OA6R3de5uvQUbHh7b9g5
+AbNYcRnxOMiuUK2XSGWGDscxuGpQVCph4G1rXCOtbTmz1Zb42vQLCCQHHyxzI7ZE
+9Y6+rzw4p3jtEyBSiiErk13GFZTzwcDzqsQs12vDn9ovSTTn5Nyy6Csz7+O2t4SN
+qU4S/uLE6b/TiXj7196r58DcGvJgKbzbbnv/DUHGfaESrVWYLk3xoX3X8VJvP7jI
+M9XoZBbbgFLgAP5DFEvf5QWS9tR092z0YXOGr+mLHtkJM7Or9nKOohm6aFfHbuvu
+pSWyR4FWnaFANQ8wLH+fH485fiO6juJdTuRWeQpZddv0/IgguZ2Plu7z6NHCf5+L
+KYFjQ5y716wOufIqHhRLqYnpsAG2AFaMuPKzsy2KMifqoyB4KYR24EA1MCT7vwqu
+Hurp+SJrmNdkFVXbhGVUfMKf4nRZ37b9Miie0ju0OxJ9C3zY5uR5BMnqEjqq/rCX
+pQh5o1y+bWacOQVp0iQWJHfy8KkjhhQ1Pd1VeoVk9l2DsAJWm6unwMvGHviRcvzg
+BejDOVcE0x4xDj+TwAu2X2+w2hbUSY9W6lmkX4nGHlbLz211bIBFq42PzAMpRnYq
+jLxml4VpO4UnhyRp7Ipps99s7/iMFOn7AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
+AG/5t56hKYKORne0bwJpMSCWZNT6JcYjf6fEmNrvG3/gz9BCuj4osZjJHD2OSUJl
+F5yI52RgPrXK8bNqJOvX6MIc4Y2JoSI2Uz4J2vZ3QhRkPC9oqwk/Enz4GIVJ4Dnm
+/kgpBbN2SN0TjnmEooptly5tWb3IPTjqLZpaPIW1ntQeCAbgrYVHiMsvNe1BuBrn
+RNi1xqw3QGp2ZV/RfJ3MH6d49TswEL1gwiUeg3hw5eG7IDfLB/2IJBrff7kmPTQ6
+n+il4uXuXMmX70xSvJXwP/NinomJsORZ4Npbmp7xV/QJp9cNoxNAo3DJ4OHRAnA+
+L7E1KZ3+nSRxGcVlqBekmG6wH9U39NN+dh758aGdJOWqA+B+1PAGxkvFCNqLgTpm
+xNl62YiRRo4FiIAkntvs+JneMEphv/T5i824t2xFZD2lBuW8r54nWj5cpx8AU9W2
+rulR0jx7BnVdj6czn1/pPCIah8Os9pZM8q1CbF8vXD+QLAF0/NjPNomTEGd/M+V+
+sfn1OhLGF/E1kWyNeOmkvX26txQdY8k6jUdsAc5vmQqgwxdorjI38ynpYQnFwq2g
+eO4l62sx8icsSh2TRklWy8BwZpaCyO/WVv/FcjIUexYhmZ0EHpmQk/RAlD1f9wFy
+CciNa/Dm94AwJgZk9LcXye3BSvb1sKF6C7eYrW0eI95V
+-----END CERTIFICATE-----
diff --git a/biometrics/face/aidl/default/apex/file_contexts b/biometrics/face/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..4f935c1
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:hal_face_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/face/aidl/default/apex/manifest.json b/biometrics/face/aidl/default/apex/manifest.json
new file mode 100644
index 0000000..4d46896
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.biometrics.face",
+ "version": 1
+}
diff --git a/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/TEST_MAPPING b/bluetooth/aidl/TEST_MAPPING
index 41a508e..18958d2 100644
--- a/bluetooth/aidl/TEST_MAPPING
+++ b/bluetooth/aidl/TEST_MAPPING
@@ -1,24 +1,12 @@
{
"presubmit" : [
{
- "name" : "VtsHalBluetoothTargetTest",
- "options": [
- {
- // TODO(b/275847929)
- "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
- }
- ]
+ "name" : "VtsHalBluetoothTargetTest"
}
],
"hwasan-presubmit" : [
{
- "name" : "VtsHalBluetoothTargetTest",
- "options": [
- {
- // TODO(b/275847929)
- "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
- }
- ]
+ "name" : "VtsHalBluetoothTargetTest"
}
]
}
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index ac2eabc..18a371d 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -174,7 +174,10 @@
mFdWatcher.WatchFdForNonBlockingReads(mFd,
[this](int) { mH4->OnDataReady(); });
- send(PacketType::COMMAND, reset);
+ ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
+ if (!result.isOk()) {
+ ALOGE("Error sending reset command");
+ }
auto status = resetFuture.wait_for(std::chrono::seconds(1));
mFdWatcher.StopWatchingFileDescriptors();
if (status == std::future_status::ready) {
@@ -301,30 +304,35 @@
ndk::ScopedAStatus BluetoothHci::sendHciCommand(
const std::vector<uint8_t>& packet) {
- send(PacketType::COMMAND, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::COMMAND, packet);
}
ndk::ScopedAStatus BluetoothHci::sendAclData(
const std::vector<uint8_t>& packet) {
- send(PacketType::ACL_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::ACL_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendScoData(
const std::vector<uint8_t>& packet) {
- send(PacketType::SCO_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::SCO_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendIsoData(
const std::vector<uint8_t>& packet) {
- send(PacketType::ISO_DATA, packet);
- return ndk::ScopedAStatus::ok();
+ return send(PacketType::ISO_DATA, packet);
}
-void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
+ndk::ScopedAStatus BluetoothHci::send(PacketType type,
+ const std::vector<uint8_t>& v) {
+ if (mH4 == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (v.empty()) {
+ ALOGE("Packet is empty, no data was found to be sent");
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
mH4->Send(type, v);
+ return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
index 85aafc8..477cc5c 100644
--- a/bluetooth/aidl/default/BluetoothHci.h
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -66,8 +66,9 @@
::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
int getFdFromDevPath();
- void send(::android::hardware::bluetooth::hci::PacketType type,
- const std::vector<uint8_t>& packet);
+ [[nodiscard]] ndk::ScopedAStatus send(
+ ::android::hardware::bluetooth::hci::PacketType type,
+ const std::vector<uint8_t>& packet);
std::unique_ptr<NetBluetoothMgmt> management_{};
// Send a reset command and discard all packets until a reset is received.
diff --git a/bluetooth/audio/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/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
index 51a624f..5f6d86e 100644
--- a/bluetooth/hci/h4_protocol.cc
+++ b/bluetooth/hci/h4_protocol.cc
@@ -105,15 +105,12 @@
buffer_offset += 1;
} else {
bool packet_ready = hci_packetizer_.OnDataReady(
- hci_packet_type_, input_buffer, buffer_offset);
+ hci_packet_type_, input_buffer, &buffer_offset);
if (packet_ready) {
- // Call packet callback and move offset.
- buffer_offset += OnPacketReady(hci_packetizer_.GetPacket());
+ // Call packet callback.
+ OnPacketReady(hci_packetizer_.GetPacket());
// Get ready for the next type byte.
hci_packet_type_ = PacketType::UNKNOWN;
- } else {
- // The data was consumed, but there wasn't a packet.
- buffer_offset = input_buffer.size();
}
}
}
diff --git a/bluetooth/hci/hci_packetizer.cc b/bluetooth/hci/hci_packetizer.cc
index 5b6c443..4135920 100644
--- a/bluetooth/hci/hci_packetizer.cc
+++ b/bluetooth/hci/hci_packetizer.cc
@@ -51,9 +51,10 @@
bool HciPacketizer::OnDataReady(PacketType packet_type,
const std::vector<uint8_t>& buffer,
- size_t offset) {
+ size_t* offset) {
bool packet_completed = false;
- size_t bytes_available = buffer.size() - offset;
+ size_t bytes_available = buffer.size() - *offset;
+
switch (state_) {
case HCI_HEADER: {
size_t header_size =
@@ -62,18 +63,20 @@
bytes_remaining_ = header_size;
packet_.clear();
}
+
size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
- packet_.insert(packet_.end(), buffer.begin() + offset,
- buffer.begin() + offset + bytes_to_copy);
+ packet_.insert(packet_.end(), buffer.begin() + *offset,
+ buffer.begin() + *offset + bytes_to_copy);
bytes_remaining_ -= bytes_to_copy;
bytes_available -= bytes_to_copy;
+ *offset += bytes_to_copy;
+
if (bytes_remaining_ == 0) {
bytes_remaining_ = HciGetPacketLengthForType(packet_type, packet_);
if (bytes_remaining_ > 0) {
state_ = HCI_PAYLOAD;
if (bytes_available > 0) {
- packet_completed =
- OnDataReady(packet_type, buffer, offset + bytes_to_copy);
+ packet_completed = OnDataReady(packet_type, buffer, offset);
}
} else {
packet_completed = true;
@@ -84,9 +87,10 @@
case HCI_PAYLOAD: {
size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
- packet_.insert(packet_.end(), buffer.begin() + offset,
- buffer.begin() + offset + bytes_to_copy);
+ packet_.insert(packet_.end(), buffer.begin() + *offset,
+ buffer.begin() + *offset + bytes_to_copy);
bytes_remaining_ -= bytes_to_copy;
+ *offset += bytes_to_copy;
if (bytes_remaining_ == 0) {
state_ = HCI_HEADER;
packet_completed = true;
@@ -94,6 +98,7 @@
break;
}
}
+
return packet_completed;
}
diff --git a/bluetooth/hci/hci_packetizer.h b/bluetooth/hci/hci_packetizer.h
index ba3e841..0d9319f 100644
--- a/bluetooth/hci/hci_packetizer.h
+++ b/bluetooth/hci/hci_packetizer.h
@@ -28,7 +28,7 @@
public:
HciPacketizer() = default;
bool OnDataReady(PacketType packet_type, const std::vector<uint8_t>& data,
- size_t offset);
+ size_t* offset);
const std::vector<uint8_t>& GetPacket() const;
protected:
diff --git a/bluetooth/hci/test/h4_protocol_unittest.cc b/bluetooth/hci/test/h4_protocol_unittest.cc
index d3fab61..f0c49b5 100644
--- a/bluetooth/hci/test/h4_protocol_unittest.cc
+++ b/bluetooth/hci/test/h4_protocol_unittest.cc
@@ -31,7 +31,6 @@
#include <vector>
#include "async_fd_watcher.h"
-#include "log/log.h"
using android::hardware::bluetooth::async::AsyncFdWatcher;
using namespace android::hardware::bluetooth::hci;
@@ -49,6 +48,7 @@
static char event_data[100] = "The edges of a surface are lines.";
static char iso_data[100] =
"A plane angle is the inclination to one another of two lines in a ...";
+static char short_payload[10] = "12345";
// 5 seconds. Just don't hang.
static constexpr size_t kTimeoutMs = 5000;
@@ -225,6 +225,49 @@
CallDataReady();
}
+ void WriteAndExpectManyAclDataPacketsDifferentOffsetsShort() {
+ std::promise<void> last_packet_promise;
+ size_t kNumPackets = 30;
+ // h4 type[1] + handle[2] + size[2]
+ char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
+ 0};
+ int length = strlen(short_payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = 0;
+
+ EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, kAclHeaderSize,
+ short_payload)))
+ .Times(kNumPackets);
+ ExpectInboundEvent(event_data, &last_packet_promise);
+
+ char all_packets[kNumPackets * 10];
+ size_t total_bytes = 0;
+
+ for (size_t packet = 0; packet < kNumPackets; packet++) {
+ for (size_t i = 0; i < sizeof(preamble); i++) {
+ all_packets[total_bytes++] = preamble[i];
+ }
+ for (size_t i = 0; i < length; i++) {
+ all_packets[total_bytes++] = short_payload[i];
+ }
+ }
+
+ size_t written_bytes = 0;
+ size_t partial_size = 1;
+ while (written_bytes < total_bytes) {
+ size_t to_write = std::min(partial_size, total_bytes - written_bytes);
+ TEMP_FAILURE_RETRY(
+ write(chip_uart_fd_, all_packets + written_bytes, to_write));
+ written_bytes += to_write;
+ CallDataReady();
+ partial_size++;
+ partial_size = partial_size % 5 + 1;
+ }
+ WriteInboundEvent(event_data);
+ CallDataReady();
+ WaitForTimeout(&last_packet_promise);
+ }
+
testing::MockFunction<void(const std::vector<uint8_t>&)> cmd_cb_;
testing::MockFunction<void(const std::vector<uint8_t>&)> event_cb_;
testing::MockFunction<void(const std::vector<uint8_t>&)> acl_cb_;
@@ -276,6 +319,10 @@
WriteAndExpectManyInboundAclDataPackets(sco_data);
}
+TEST_F(H4ProtocolTest, TestMultipleWritesPacketsShortWrites) {
+ WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
TEST_F(H4ProtocolTest, TestDisconnect) {
EXPECT_CALL(disconnect_cb_, Call());
close(chip_uart_fd_);
@@ -332,10 +379,8 @@
void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
- void CallDataReady() override {
- // The Async test can't call data ready.
- FAIL();
- }
+ // Calling CallDataReady() has no effect in the AsyncTest
+ void CallDataReady() override {}
void SendAndReadUartOutbound(PacketType type, char* data) {
ALOGD("%s sending", __func__);
@@ -434,6 +479,10 @@
WriteAndExpectManyInboundAclDataPackets(sco_data);
}
+TEST_F(H4ProtocolAsyncTest, TestMultipleWritesPacketsShortWrites) {
+ WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
TEST_F(H4ProtocolAsyncTest, TestDisconnect) {
std::promise<void> promise;
EXPECT_CALL(disconnect_cb_, Call()).WillOnce(Notify(&promise));
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 93b5380..b3ca293 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -82,3 +82,15 @@
"kernel_config_u_6.1",
],
}
+
+vintf_compatibility_matrix {
+ name: "framework_compatibility_matrix.9.xml",
+ stem: "compatibility_matrix.9.xml",
+ srcs: [
+ "compatibility_matrix.9.xml",
+ ],
+ kernel_configs: [
+ "kernel_config_v_5.15",
+ "kernel_config_v_6.1",
+ ],
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6e4c419..a82a421 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -103,6 +103,7 @@
framework_compatibility_matrix.6.xml \
framework_compatibility_matrix.7.xml \
framework_compatibility_matrix.8.xml \
+ framework_compatibility_matrix.9.xml \
framework_compatibility_matrix.device.xml \
my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 188746d..361723e 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -1,4 +1,3 @@
-<!-- WARNING: This file is unused in the Android 14 branch. -->
<compatibility-matrix version="1.0" type="framework" level="9">
<hal format="hidl" optional="true">
<name>android.hardware.audio</name>
@@ -115,7 +114,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.face</name>
<version>3</version>
<interface>
@@ -123,7 +122,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>3</version>
<interface>
@@ -132,14 +131,6 @@
<instance>virtual</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.bluetooth</name>
- <version>1.0-1</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.bluetooth</name>
<interface>
@@ -493,16 +484,6 @@
</interface>
</hal>
<hal format="aidl" optional="true">
- <name>android.hardware.radio.satellite</name>
- <version>1</version>
- <interface>
- <name>IRadioSatellite</name>
- <instance>slot1</instance>
- <instance>slot2</instance>
- <instance>slot3</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
<name>android.hardware.radio.ims.media</name>
<version>1</version>
<interface>
@@ -510,14 +491,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.renderscript</name>
- <version>1.0</version>
- <interface>
- <name>IDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.rebootescrow</name>
<version>1</version>
@@ -560,14 +533,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.soundtrigger</name>
- <version>2.3</version>
- <interface>
- <name>ISoundTriggerHw</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.soundtrigger3</name>
<version>1</version>
@@ -576,22 +541,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tetheroffload.config</name>
- <version>1.0</version>
- <interface>
- <name>IOffloadConfig</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tetheroffload.control</name>
- <version>1.1</version>
- <interface>
- <name>IOffloadControl</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.tetheroffload</name>
<version>1</version>
diff --git a/drm/1.3/vts/OWNERS b/drm/1.3/vts/OWNERS
index 3a0672e..744827c 100644
--- a/drm/1.3/vts/OWNERS
+++ b/drm/1.3/vts/OWNERS
@@ -1,9 +1,11 @@
+# Bug component: 49079
conglin@google.com
-edwinwong@google.com
fredgc@google.com
-jtinker@google.com
juce@google.com
+kelzhan@google.com
kylealexander@google.com
+mattfedd@google.com
rfrias@google.com
robertshih@google.com
sigquit@google.com
+vickymin@google.com
\ No newline at end of file
diff --git a/gnss/aidl/OWNERS b/gnss/aidl/OWNERS
index b7b4a2e..e5b585e 100644
--- a/gnss/aidl/OWNERS
+++ b/gnss/aidl/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 393449
+
gomo@google.com
smalkos@google.com
wyattriley@google.com
diff --git a/graphics/composer/2.4/vts/functional/TEST_MAPPING b/graphics/composer/2.4/vts/functional/TEST_MAPPING
new file mode 100644
index 0000000..aedac5b
--- /dev/null
+++ b/graphics/composer/2.4/vts/functional/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalGraphicsComposerV2_4TargetTest"
+ }
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "VtsHalGraphicsComposerV2_4TargetTest"
+ }
+ ]
+}
+
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index e4a84e1..03d9041 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -677,7 +677,7 @@
const native_handle_t* clonedBufferHandle;
ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
- error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+ error = mGralloc->getMapper()->freeBuffer(const_cast<native_handle_t*>(clonedBufferHandle));
EXPECT_EQ(Error::BAD_BUFFER, error)
<< "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 2c06353..b329de2 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -1371,6 +1371,28 @@
EXPECT_EQ(buffer->info().usage, *value);
}
+TEST_P(GraphicsMapperStableCTests, GetUsage64) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::FRONT_BUFFER | BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE,
+ .reservedSize = 0,
+ };
+ if (!isSupported(info)) {
+ GTEST_SKIP();
+ }
+ auto buffer = allocate(info);
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ using T = std::underlying_type_t<BufferUsage>;
+ EXPECT_EQ(static_cast<T>(buffer->info().usage), static_cast<T>(*value));
+}
+
TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
auto buffer = allocateGeneric();
auto bufferHandle = buffer->import();
diff --git a/health/storage/aidl/vts/functional/OWNERS b/health/storage/aidl/vts/functional/OWNERS
new file mode 100644
index 0000000..a15ed7c
--- /dev/null
+++ b/health/storage/aidl/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+file:platform/hardware/interfaces:/health/aidl/OWNERS
\ No newline at end of file
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 3096fe5..d62d055 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -22,15 +22,8 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_library {
- name: "android.hardware.identity-support-lib",
- vendor_available: true,
- srcs: [
- "src/IdentityCredentialSupport.cpp",
- ],
- export_include_dirs: [
- "include",
- ],
+cc_defaults {
+ name: "android.hardware.identity-support-lib-deps",
shared_libs: [
"android.hardware.keymaster@4.0",
"libcrypto",
@@ -47,19 +40,36 @@
],
}
+cc_library {
+ name: "android.hardware.identity-support-lib",
+ vendor_available: true,
+ defaults: [
+ "android.hardware.identity-support-lib-deps",
+ ],
+ srcs: [
+ "src/IdentityCredentialSupport.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+}
+
cc_test {
name: "android.hardware.identity-support-lib-test",
srcs: [
"tests/IdentityCredentialSupportTest.cpp",
],
+ defaults: [
+ "android.hardware.identity-support-lib-deps",
+ ],
shared_libs: [
- "android.hardware.identity-support-lib",
"libcrypto",
"libbase",
"libhidlbase",
"libhardware",
],
static_libs: [
+ "android.hardware.identity-support-lib",
"libcppbor_external",
"libgmock",
],
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 554afe7..65b3dfa 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2617,10 +2617,11 @@
EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
- size_t modulus_len = BN_num_bytes(rsa->n);
+ const BIGNUM* n = RSA_get0_n(rsa.get());
+ size_t modulus_len = BN_num_bytes(n);
ASSERT_EQ(1024U / 8, modulus_len);
std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n, modulus_buf.get());
// The modulus is too big to encrypt.
string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2632,10 +2633,12 @@
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
// One smaller than the modulus is okay.
- BN_sub(rsa->n, rsa->n, BN_value_one());
- modulus_len = BN_num_bytes(rsa->n);
+ BIGNUM_Ptr n_minus_1(BN_new());
+ ASSERT_TRUE(n_minus_1);
+ ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+ modulus_len = BN_num_bytes(n_minus_1.get());
ASSERT_EQ(1024U / 8, modulus_len);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n_minus_1.get(), modulus_buf.get());
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index b709904..96580c0 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2449,10 +2449,11 @@
EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
- size_t modulus_len = BN_num_bytes(rsa->n);
+ const BIGNUM* n = RSA_get0_n(rsa.get());
+ size_t modulus_len = BN_num_bytes(n);
ASSERT_EQ(2048U / 8, modulus_len);
std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n, modulus_buf.get());
// The modulus is too big to encrypt.
string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2464,10 +2465,12 @@
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
// One smaller than the modulus is okay.
- BN_sub(rsa->n, rsa->n, BN_value_one());
- modulus_len = BN_num_bytes(rsa->n);
+ BIGNUM_Ptr n_minus_1(BN_new());
+ ASSERT_TRUE(n_minus_1);
+ ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+ modulus_len = BN_num_bytes(n_minus_1.get());
ASSERT_EQ(2048U / 8, modulus_len);
- BN_bn2bin(rsa->n, modulus_buf.get());
+ BN_bn2bin(n_minus_1.get(), modulus_buf.get());
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 7bc65ff..8b7af11 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -23,4 +23,8 @@
"android.hidl.base@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index 772e5e6..b93c80c 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -21,4 +21,8 @@
"android.hidl.base@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 2b83d39..63e0f61 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -28,4 +28,8 @@
"android.hidl.safe_union@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index aa8fc39..c343802 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -29,4 +29,8 @@
"android.hidl.safe_union@1.0",
],
gen_java: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 82c8a0d..a4fab55 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -126,8 +126,8 @@
*
* o The HMAC field must validate correctly.
*
- * o The challenge field in the auth token must contain the challenge value contained in the
- * BeginResult returned from IKeyMintDevice::begin().
+ * o The challenge field in the timestamp token must contain the challenge value contained in
+ * the BeginResult returned from IKeyMintDevice::begin().
*
* The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
* auth token to be valid, all of the following has to be true:
@@ -139,9 +139,6 @@
*
* o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
*
- * o The challenge field in the auth token must contain the challenge value contained in the
- * BeginResult returned from IKeyMintDevice::begin().
- *
* o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
* than the provided secure timestamp.
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
index 78c88f4..290e8fc 100644
--- a/security/keymint/aidl/vts/functional/AuthTest.cpp
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -93,17 +93,21 @@
void TearDown() {
if (gk_ == nullptr) return;
gk_->deleteUser(uid_);
+ if (alt_uid_ != 0) {
+ gk_->deleteUser(alt_uid_);
+ }
}
bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
- std::optional<GatekeeperEnrollResponse> doEnroll(const std::vector<uint8_t>& newPwd,
+ std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid,
+ const std::vector<uint8_t>& newPwd,
const std::vector<uint8_t>& curHandle = {},
const std::vector<uint8_t>& curPwd = {}) {
if (gk_ != nullptr) {
while (true) {
GatekeeperEnrollResponse rsp;
- Status status = gk_->enroll(uid_, curHandle, curPwd, newPwd, &rsp);
+ Status status = gk_->enroll(uid, curHandle, curPwd, newPwd, &rsp);
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
sleep(1);
@@ -120,7 +124,7 @@
while (true) {
HidlGatekeeperResponse rsp;
auto status = hidl_gk_->enroll(
- uid_, curHandle, curPwd, newPwd,
+ uid, curHandle, curPwd, newPwd,
[&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
if (!status.isOk()) {
GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
@@ -155,20 +159,23 @@
}
}
- std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd,
+ std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid, const string& newPwd,
const std::vector<uint8_t>& curHandle = {},
const string& curPwd = {}) {
- return doEnroll(std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
+ return doEnroll(uid, std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
}
+ std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd) {
+ return doEnroll(uid_, newPwd);
+ }
- std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
+ std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
const std::vector<uint8_t>& handle,
const std::vector<uint8_t>& pwd) {
if (gk_ != nullptr) {
while (true) {
GatekeeperVerifyResponse rsp;
- Status status = gk_->verify(uid_, challenge, handle, pwd, &rsp);
+ Status status = gk_->verify(uid, challenge, handle, pwd, &rsp);
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
sleep(1);
@@ -185,7 +192,7 @@
while (true) {
HidlGatekeeperResponse rsp;
auto status = hidl_gk_->verify(
- uid_, challenge, handle, pwd,
+ uid, challenge, handle, pwd,
[&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
if (!status.isOk()) {
GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
@@ -220,10 +227,15 @@
return std::nullopt;
}
}
+ std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
+ const std::vector<uint8_t>& handle,
+ const string& pwd) {
+ return doVerify(uid, challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+ }
std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
const std::vector<uint8_t>& handle,
const string& pwd) {
- return doVerify(challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+ return doVerify(uid_, challenge, handle, pwd);
}
// Variants of the base class methods but with authentication information included.
@@ -268,6 +280,13 @@
return plaintext;
}
+ string SignMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params,
+ const HardwareAuthToken& hat) {
+ SCOPED_TRACE("SignMessage");
+ return ProcessMessage(key_blob, KeyPurpose::SIGN, message, in_params, out_params, hat);
+ }
+
protected:
std::shared_ptr<IGatekeeper> gk_;
sp<IHidlGatekeeper> hidl_gk_;
@@ -275,6 +294,8 @@
string password_;
uint32_t uid_;
int64_t sid_;
+ uint32_t alt_uid_;
+ int64_t alt_sid_;
std::vector<uint8_t> handle_;
};
@@ -347,6 +368,116 @@
}
}
+// Test use of a key that requires user-authentication within recent history, but where
+// the `TimestampToken` provided to the device is unrelated to the in-progress operation.
+TEST_P(AuthTest, TimeoutAuthenticationIncorrectTimestampToken) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+ if (!timestamp_token_required_) {
+ GTEST_SKIP() << "Test only applies to devices with no secure clock";
+ }
+ if (clock_ == nullptr) {
+ GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+ }
+
+ // Create an AES key that requires authentication within the last 3 seconds.
+ const uint32_t timeout_secs = 3;
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
+ .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Verify to get a HAT, arbitrary challenge.
+ const uint64_t challenge = 42;
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ // KeyMint implementation has no clock, so only detects timeout via timestamp token provided
+ // on update()/finish(). However, for this test we ensure that that the timestamp token has a
+ // *different* challenge value.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
+
+ secureclock::TimeStampToken time_token;
+ EXPECT_EQ(ErrorCode::OK,
+ GetReturnErrorCode(clock_->generateTimeStamp(challenge_ + 1, &time_token)));
+ string output;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &output, hat, time_token));
+}
+
+// Test use of a key with multiple USER_SECURE_ID values. For variety, use an EC signing key
+// generated with attestation.
+TEST_P(AuthTest, TimeoutAuthenticationMultiSid) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+ if (timestamp_token_required_ && clock_ == nullptr) {
+ GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+ }
+
+ // Enroll a password for a second user.
+ alt_uid_ = 20001;
+ const string alt_password = "correcthorsebatterystaple2";
+ std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+ ASSERT_TRUE(rsp.has_value());
+ alt_sid_ = rsp->secureUserId;
+ const std::vector<uint8_t> alt_handle = rsp->data;
+
+ // Create an attested EC key that requires authentication within the last 3 seconds from either
+ // secure ID. Also allow any authenticator type.
+ const uint32_t timeout_secs = 3;
+ auto builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity()
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("app_id")
+ .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY)
+ .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Verify first user to get a HAT that should work.
+ const uint64_t challenge = 42;
+ const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ AuthorizationSet out_params;
+ const string signature = SignMessage(keyblob, message, params, &out_params, hat.value());
+
+ // Verify second user to get a HAT that should work.
+ const uint64_t alt_challenge = 43;
+ const std::optional<HardwareAuthToken> alt_hat =
+ doVerify(alt_uid_, alt_challenge, alt_handle, alt_password);
+ ASSERT_TRUE(alt_hat.has_value());
+ EXPECT_EQ(alt_hat->userId, alt_sid_);
+
+ const string alt_signature =
+ SignMessage(keyblob, message, params, &out_params, alt_hat.value());
+}
+
// Test use of a key that requires an auth token for each action on the operation, with
// a per-operation challenge value included.
TEST_P(AuthTest, AuthPerOperation) {
@@ -407,6 +538,93 @@
Finish(message, {} /* signature */, &ciphertext, hat.value()));
}
+// Test use of a key that requires an auth token for each action on the operation, with
+// a per-operation challenge value included, with multiple secure IDs allowed.
+TEST_P(AuthTest, AuthPerOperationMultiSid) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+
+ // Enroll a password for a second user.
+ alt_uid_ = 20001;
+ const string alt_password = "correcthorsebatterystaple2";
+ std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+ ASSERT_TRUE(rsp.has_value());
+ alt_sid_ = rsp->secureUserId;
+ const std::vector<uint8_t> alt_handle = rsp->data;
+
+ // Create an AES key that requires authentication per-action.
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Get a HAT for first user with the challenge from an in-progress operation.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge_, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
+
+ // Get a HAT for second user with the challenge from an in-progress operation.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> alt_hat =
+ doVerify(alt_uid_, challenge_, alt_handle, alt_password);
+ ASSERT_TRUE(alt_hat.has_value());
+ EXPECT_EQ(alt_hat->userId, alt_sid_);
+ string alt_ciphertext;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, alt_hat.value()));
+}
+
+// Test use of a key that requires an auth token for each action on the operation, but
+// which gets passed a HAT of the wrong type
+TEST_P(AuthTest, AuthPerOperationWrongAuthType) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+
+ // Create an AES key that requires authentication per-action, but with no valid authenticator
+ // types.
+ auto builder =
+ AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::FINGERPRINT);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Get a HAT with the challenge from an in-progress operation.
+ const string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ // Should fail because auth type doesn't (can't) match.
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &ciphertext, hat.value()));
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(AuthTest);
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
index 6892442..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 e99149b..c54a2c9 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -3119,7 +3119,7 @@
*/
TEST_P(SigningOperationsTest, NoUserConfirmation) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(1024, 65537)
+ .RsaSigningKey(2048, 65537)
.Digest(Digest::NONE)
.Padding(PaddingMode::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -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/staging/threadnetwork/aidl/default/thread_chip.cpp b/staging/threadnetwork/aidl/default/thread_chip.cpp
index 38abad4..9bd729d 100644
--- a/staging/threadnetwork/aidl/default/thread_chip.cpp
+++ b/staging/threadnetwork/aidl/default/thread_chip.cpp
@@ -170,7 +170,7 @@
}
ndk::ScopedAStatus ThreadChip::reset() {
- mInterface.OnRcpReset();
+ mInterface.HardwareReset();
ALOGI("reset()");
return ndk::ScopedAStatus::ok();
}
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/usb/OWNERS b/usb/OWNERS
index 2b1d34d..3611b4d 100644
--- a/usb/OWNERS
+++ b/usb/OWNERS
@@ -1,4 +1,8 @@
# Bug component: 175220
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
albertccwang@google.com
badhri@google.com
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index 7c2c300..cf32694 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -6,8 +6,8 @@
use async_trait::async_trait;
use binder::{Result, Strong};
-use tokio::fs::File;
-use tokio::io::{AsyncReadExt, AsyncWriteExt};
+use tokio::fs::{self, File};
+use tokio::io::AsyncReadExt;
use tokio::sync::Mutex;
use std::os::fd::AsRawFd;
@@ -22,7 +22,6 @@
callbacks: Strong<dyn IUwbClientCallback>,
#[allow(dead_code)]
tasks: tokio::task::JoinSet<()>,
- write: File,
},
}
@@ -65,17 +64,11 @@
async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
log::debug!("open: {:?}", &self.path);
- let serial = File::open(&self.path)
+ let mut serial = File::open(&self.path)
.await
.and_then(makeraw)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
- let mut read = serial
- .try_clone()
- .await
- .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
- let write = serial;
-
let mut state = self.state.lock().await;
if let State::Closed = *state {
@@ -88,14 +81,16 @@
const UWB_HEADER_SIZE: usize = 4;
let mut buffer = vec![0; UWB_HEADER_SIZE];
- read.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
+ serial
+ .read_exact(&mut buffer[0..UWB_HEADER_SIZE])
.await
.unwrap();
let length = buffer[3] as usize + UWB_HEADER_SIZE;
buffer.resize(length, 0);
- read.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
+ serial
+ .read_exact(&mut buffer[UWB_HEADER_SIZE..length])
.await
.unwrap();
@@ -108,7 +103,6 @@
*state = State::Opened {
callbacks: callbacks.clone(),
tasks,
- write,
};
Ok(())
@@ -155,11 +149,10 @@
async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
log::debug!("sendUciMessage");
- if let State::Opened { write, .. } = &mut *self.state.lock().await {
- write
- .write(data)
+ if let State::Opened { .. } = &mut *self.state.lock().await {
+ fs::write(&self.path, data)
.await
- .map(|written| written as i32)
+ .map(|_| data.len() as i32)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
} else {
Err(binder::ExceptionCode::ILLEGAL_STATE.into())