Merge "audio: Add effect attachment to devices and streams"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 0918971..7d474b2 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -41,6 +41,7 @@
"android/hardware/audio/common/SinkMetadata.aidl",
"android/hardware/audio/common/SourceMetadata.aidl",
],
+ frozen: true,
imports: [
"android.media.audio.common.types-V2",
],
@@ -169,6 +170,53 @@
],
}
+// Used for the standalone sounddose HAL
+aidl_interface {
+ name: "android.hardware.audio.core.sounddose",
+ defaults: [
+ "android.hardware.audio_defaults",
+ ],
+ srcs: [
+ "android/hardware/audio/core/ISoundDose.aidl",
+ ],
+ imports: [
+ "android.media.audio.common.types-V2",
+ ],
+ backend: {
+ // The C++ backend is disabled transitively due to use of FMQ by the core HAL.
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+ versions_with_info: [
+ // IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
+ // add the latest frozen version to versions_with_info
+ ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.core.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+ name: "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_core_sounddose + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_hardware_audio_core_sounddose_ndk_static",
+ static_libs: [
+ latest_android_hardware_audio_core_sounddose + "-ndk",
+ ],
+}
+
aidl_interface {
name: "android.hardware.audio.effect",
defaults: [
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 484320f..b4607f9 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -14,6 +14,9 @@
},
{
"name": "VtsHalLoudnessEnhancerTargetTest"
+ },
+ {
+ "name": "VtsHalVisualizerTargetTest"
}
]
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..bc010ca
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ const int MIN_RS2 = 80;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index b9b8cd8..a7a515a 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -29,6 +29,29 @@
],
}
+cc_library {
+ name: "libaudioservicesounddoseimpl",
+ vendor: true,
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "SoundDose.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libutils",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/sounddose/default",
+ ],
+}
+
cc_library_static {
name: "libaudioserviceexampleimpl",
defaults: [
@@ -132,7 +155,7 @@
"libenvreverbsw",
"libequalizersw",
"libhapticgeneratorsw",
- "libloudnessenhancersw",
+ "libloudnessenhanceraidl",
"libpresetreverbsw",
"libtinyxml2",
"libvirtualizersw",
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index f4ac8fe..c33ebf5 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -33,7 +33,7 @@
<library name="dynamics_processingsw" path="libdynamicsprocessingsw.so"/>
<library name="equalizersw" path="libequalizersw.so"/>
<library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
- <library name="loudness_enhancersw" path="libloudnessenhancersw.so"/>
+ <library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
<library name="env_reverbsw" path="libenvreverbsw.so"/>
<library name="preset_reverbsw" path="libpresetreverbsw.so"/>
<library name="virtualizersw" path="libvirtualizersw.so"/>
@@ -61,10 +61,13 @@
-->
<effects>
- <effect name="bassboost" library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <effectProxy name="bassboost" uuid="14804144-a5ee-4d24-aa88-0002a5d5c51b">
+ <libsw library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
+ </effectProxy>
<effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
<effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
- <effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
<effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
<effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
<effect name="virtualizer" library="virtualizersw" uuid="fa819d86-588b-11ed-9b6a-0242ac120002"/>
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index 61976c8..8e4779d 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -66,7 +66,7 @@
const Descriptor BassBoostSw::kDescriptor = {
.common = {.id = {.type = kBassBoostTypeUUID,
.uuid = kBassBoostSwImplUUID,
- .proxy = std::nullopt},
+ .proxy = kBassBoostProxyUUID},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index 5a8b970..ad79a0c 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -167,6 +167,7 @@
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+ enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_PCM;
}
public enum AudioFormat {
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index ddaa122..301c969 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -576,6 +576,7 @@
<xs:restriction base="xs:string">
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_PCM"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="profile">
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 7709eab..8c381c7 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -45,6 +45,18 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 8631f300-72e2-11df-b57e-0002a5d5c51b
+static const AudioUuid kBassBoostBundleImplUUID = {static_cast<int32_t>(0x8631f300),
+ 0x72e2,
+ 0x11df,
+ 0xb57e,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 14804144-a5ee-4d24-aa88-0002a5d5c51b
+static const AudioUuid kBassBoostProxyUUID = {static_cast<int32_t>(0x14804144),
+ 0xa5ee,
+ 0x4d24,
+ 0xaa88,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81862a-588b-11ed-9b6a-0242ac120002
static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
0x588b,
@@ -117,6 +129,12 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa415329-2034-4bea-b5dc-5b381c8d1e2c
+static const AudioUuid kLoudnessEnhancerImplUUID = {static_cast<int32_t>(0xfa415329),
+ 0x2034,
+ 0x4bea,
+ 0xb5dc,
+ {0x5b, 0x38, 0x1c, 0x8d, 0x1e, 0x2c}};
// c2e5d5f0-94bd-4763-9cac-4e234d06839e
static const AudioUuid kEnvReverbTypeUUID = {static_cast<int32_t>(0xc2e5d5f0),
0x94bd,
diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
index b898c00..37eb30b 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.cpp
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -14,14 +14,9 @@
* limitations under the License.
*/
-#include <cstddef>
#define LOG_TAG "AHAL_VisualizerSw"
-#include <Utils.h>
-#include <algorithm>
-#include <unordered_set>
#include <android-base/logging.h>
-#include <fmq/AidlMessageQueue.h>
#include "VisualizerSw.h"
@@ -60,7 +55,10 @@
namespace aidl::android::hardware::audio::effect {
const std::string VisualizerSw::kEffectName = "VisualizerSw";
-const Visualizer::Capability VisualizerSw::kCapability;
+/* capabilities */
+const Visualizer::CaptureSizeRange mCaptureSizeRange = {MIN_CAPTURE_SIZE, MAX_CAPTURE_SIZE};
+const Visualizer::Capability VisualizerSw::kCapability = {.maxLatencyMs = MAX_LATENCY,
+ .captureSizeRange = mCaptureSizeRange};
const Descriptor VisualizerSw::kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerSwImplUUID,
@@ -82,8 +80,53 @@
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::visualizer>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ auto& vsParam = specific.get<Parameter::Specific::visualizer>();
+ auto tag = vsParam.getTag();
+
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ RETURN_IF(mContext->setVsCaptureSize(vsParam.get<Visualizer::captureSizeBytes>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::scalingMode: {
+ RETURN_IF(mContext->setVsScalingMode(vsParam.get<Visualizer::scalingMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "scalingModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::measurementMode: {
+ RETURN_IF(mContext->setVsMeasurementMode(vsParam.get<Visualizer::measurementMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "measurementModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::setOnlyParameters: {
+ return setSetOnlyParameterVisualizer(vsParam.get<Visualizer::setOnlyParameters>());
+ }
+ case Visualizer::getOnlyParameters: {
+ LOG(ERROR) << __func__ << " unsupported settable getOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "SetofGetOnlyParamsNotSupported");
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus VisualizerSw::setSetOnlyParameterVisualizer(
+ Visualizer::SetOnlyParameters setOnlyParam) {
+ auto tag = setOnlyParam.getTag();
+ RETURN_IF(Visualizer::SetOnlyParameters::latencyMs != tag, EX_ILLEGAL_ARGUMENT,
+ "SetOnlyParametersTagNotSupported");
+ RETURN_IF(
+ mContext->setVsLatency(setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "latencyNotSupported");
return ndk::ScopedAStatus::ok();
}
@@ -91,7 +134,76 @@
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::visualizer>(mSpecificParam);
+ auto vsId = id.get<Parameter::Id::visualizerTag>();
+ auto vsIdTag = vsId.getTag();
+ switch (vsIdTag) {
+ case Visualizer::Id::commonTag:
+ return getParameterVisualizer(vsId.get<Visualizer::Id::commonTag>(), specific);
+ case Visualizer::Id::getOnlyParamTag:
+ return getGetOnlyParameterVisualizer(vsId.get<Visualizer::Id::getOnlyParamTag>(),
+ specific);
+ case Visualizer::Id::setOnlyParamTag: {
+ LOG(ERROR) << __func__ << " unsupported gettable setOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetofSetOnlyParamsNotSupported");
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+}
+ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Visualizer vsParam;
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ vsParam.set<Visualizer::captureSizeBytes>(mContext->getVsCaptureSize());
+ break;
+ }
+ case Visualizer::scalingMode: {
+ vsParam.set<Visualizer::scalingMode>(mContext->getVsScalingMode());
+ break;
+ }
+ case Visualizer::measurementMode: {
+ vsParam.set<Visualizer::measurementMode>(mContext->getVsMeasurementMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+ specific->set<Parameter::Specific::visualizer>(vsParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer(
+ const Visualizer::GetOnlyParameters::Tag& tag, Parameter::Specific* specific) {
+ Visualizer::GetOnlyParameters getOnlyParam;
+ switch (tag) {
+ case Visualizer::GetOnlyParameters::measurement: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::measurement>(
+ mContext->getVsMeasurement());
+ break;
+ }
+ case Visualizer::GetOnlyParameters::captureBytes: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::captureBytes>(
+ mContext->getVsCaptureBytes());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetOnlyParameterTagNotSupported");
+ }
+ }
+ Visualizer vsParam;
+ vsParam.set<Visualizer::getOnlyParameters>(getOnlyParam);
+ specific->set<Parameter::Specific::visualizer>(vsParam);
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
index 24b92dd..a95537c 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.h
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -17,13 +17,16 @@
#pragma once
#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include <fmq/AidlMessageQueue.h>
-#include <cstdlib>
-#include <memory>
+#include <vector>
#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectUUID.h"
+#define MIN_CAPTURE_SIZE 128
+#define MAX_CAPTURE_SIZE 1024
+#define MAX_LATENCY 3000
+#define CAPTURE_BUF_SIZE 65536
+
namespace aidl::android::hardware::audio::effect {
class VisualizerSwContext final : public EffectContext {
@@ -31,8 +34,55 @@
VisualizerSwContext(int statusDepth, const Parameter::Common& common)
: EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
+ mCaptureBytes.resize(CAPTURE_BUF_SIZE);
+ fill(mCaptureBytes.begin(), mCaptureBytes.end(), 0x80);
}
- // TODO: add specific context here
+
+ RetCode setVsCaptureSize(int captureSize) {
+ if (captureSize < MIN_CAPTURE_SIZE || captureSize > MAX_CAPTURE_SIZE) {
+ LOG(ERROR) << __func__ << " invalid captureSize " << captureSize;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new captureSize
+ mCaptureSize = captureSize;
+ return RetCode::SUCCESS;
+ }
+ int getVsCaptureSize() const { return mCaptureSize; }
+
+ RetCode setVsScalingMode(Visualizer::ScalingMode scalingMode) {
+ // TODO : Add implementation to apply new scalingMode
+ mScalingMode = scalingMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::ScalingMode getVsScalingMode() const { return mScalingMode; }
+
+ RetCode setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) {
+ // TODO : Add implementation to apply new measurementMode
+ mMeasurementMode = measurementMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; }
+
+ RetCode setVsLatency(int latency) {
+ if (latency < 0 || latency > MAX_LATENCY) {
+ LOG(ERROR) << __func__ << " invalid latency " << latency;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to modify latency
+ mLatency = latency;
+ return RetCode::SUCCESS;
+ }
+
+ Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; }
+ std::vector<uint8_t> getVsCaptureBytes() const { return mCaptureBytes; }
+
+ private:
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency;
+ const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0};
+ std::vector<uint8_t> mCaptureBytes;
};
class VisualizerSw final : public EffectImpl {
@@ -60,7 +110,11 @@
private:
std::shared_ptr<VisualizerSwContext> mContext;
- /* parameters */
- Visualizer mSpecificParam;
+
+ ndk::ScopedAStatus setSetOnlyParameterVisualizer(Visualizer::SetOnlyParameters setOnlyParam);
+ ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus getGetOnlyParameterVisualizer(const Visualizer::GetOnlyParameters::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/sounddose/Android.bp b/audio/aidl/sounddose/Android.bp
new file mode 100644
index 0000000..85d6e21
--- /dev/null
+++ b/audio/aidl/sounddose/Android.bp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.audio.sounddose",
+ host_supported: true,
+ vendor_available: true,
+ stability: "vintf",
+ srcs: [
+ "android/hardware/audio/sounddose/ISoundDoseFactory.aidl",
+ ],
+ imports: [
+ latest_android_hardware_audio_core_sounddose,
+ ],
+ backend: {
+ // The C++ backend is disabled transitively due to use by core audio HAL.
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+ versions_with_info: [
+ // IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
+ // add the latest frozen version to versions_with_info
+ ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V1"
+
+// Modules that depend on android.hardware.audio.sounddose directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+ name: "latest_android_hardware_audio_sounddose_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_sounddose + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_hardware_audio_sounddose_ndk_static",
+ static_libs: [
+ latest_android_hardware_audio_sounddose + "-ndk",
+ ],
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..dff17e2
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.core.sounddose/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..7dda011
--- /dev/null
+++ b/audio/aidl/sounddose/aidl_api/android.hardware.audio.sounddose/current/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.sounddose;
+@VintfStability
+interface ISoundDoseFactory {
+ @nullable android.hardware.audio.core.ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
new file mode 100644
index 0000000..3487237
--- /dev/null
+++ b/audio/aidl/sounddose/android/hardware/audio/sounddose/ISoundDoseFactory.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.sounddose;
+
+import android.hardware.audio.core.ISoundDose;
+
+/**
+ * This interface is used to provide an easy way to implement the ISoundDose interface
+ * without switching the audio HAL to AIDL. The implementation is intended as a workaround
+ * for the certification with IEC62368-1 3rd edition and EN50332-3.
+ * Note that this interface will be deprecated in favor of the audio AIDL HAL.
+ */
+@VintfStability
+interface ISoundDoseFactory {
+ /**
+ * Retrieve the sound dose interface for a given audio HAL module name.
+ *
+ * If a device must comply to IEC62368-1 3rd edition audio safety requirements and is
+ * implementing audio offload decoding or other direct playback paths where volume control
+ * happens below the audio HAL, it must return an instance of the ISoundDose interface.
+ * The same instance must be returned during the lifetime of the HAL module.
+ * If the HAL module does not support sound dose, null must be returned, without throwing
+ * any errors.
+ *
+ * @param module for which we trigger sound dose updates.
+ * @return An instance of the ISoundDose interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable ISoundDose getSoundDose(in @utf8InCpp String module);
+}
diff --git a/audio/aidl/sounddose/default/Android.bp b/audio/aidl/sounddose/default/Android.bp
new file mode 100644
index 0000000..bd770fa
--- /dev/null
+++ b/audio/aidl/sounddose/default/Android.bp
@@ -0,0 +1,46 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_defaults {
+ name: "aidlsounddoseservice_defaults",
+ vendor: true,
+ header_libs: [
+ "libsounddoseaidl_headers",
+ ],
+}
+
+cc_library {
+ name: "libsounddoseserviceexampleimpl",
+ defaults: [
+ "aidlsounddoseservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "SoundDoseFactory.cpp",
+ ],
+ shared_libs: [
+ "libaudioservicesounddoseimpl",
+ "libbase",
+ "libbinder_ndk",
+ ],
+
+ visibility: [
+ "//hardware/interfaces/audio/common/all-versions/default/service",
+ ],
+}
+
+cc_library_headers {
+ name: "libsounddoseaidl_headers",
+ export_include_dirs: ["include"],
+ vendor_available: true,
+ host_supported: true,
+}
diff --git a/audio/aidl/sounddose/default/SoundDoseFactory.cpp b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
new file mode 100644
index 0000000..50796d0
--- /dev/null
+++ b/audio/aidl/sounddose/default/SoundDoseFactory.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_SoundDoseFactory"
+
+#include "SoundDoseFactory.h"
+
+#include <android-base/logging.h>
+#include <core-impl/SoundDose.h>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::SoundDose;
+
+ndk::ScopedAStatus SoundDoseFactory::getSoundDose(const std::string& in_module,
+ std::shared_ptr<ISoundDose>* _aidl_return) {
+ auto soundDoseIt = mSoundDoseBinderMap.find(in_module);
+ if (soundDoseIt != mSoundDoseBinderMap.end()) {
+ *_aidl_return = ISoundDose::fromBinder(soundDoseIt->second);
+
+ LOG(DEBUG) << __func__
+ << ": returning cached instance of ISoundDose: " << _aidl_return->get()
+ << " for module " << in_module;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ auto soundDose = ndk::SharedRefBase::make<SoundDose>();
+ mSoundDoseBinderMap[in_module] = soundDose->asBinder();
+ *_aidl_return = soundDose;
+
+ LOG(DEBUG) << __func__ << ": returning new instance of ISoundDose: " << _aidl_return->get()
+ << " for module " << in_module;
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/default/include/SoundDoseFactory.h b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
new file mode 100644
index 0000000..4cf3277
--- /dev/null
+++ b/audio/aidl/sounddose/default/include/SoundDoseFactory.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
+#include <aidl/android/hardware/audio/sounddose/BnSoundDoseFactory.h>
+#include <android/binder_interface_utils.h>
+
+#include <unordered_map>
+
+namespace aidl::android::hardware::audio::sounddose {
+
+using ::aidl::android::hardware::audio::core::ISoundDose;
+
+class SoundDoseFactory : public BnSoundDoseFactory {
+ public:
+ ndk::ScopedAStatus getSoundDose(const std::string& module,
+ std::shared_ptr<ISoundDose>* _aidl_return) override;
+
+ private:
+ std::unordered_map<std::string, ndk::SpAIBinder> mSoundDoseBinderMap;
+};
+
+} // namespace aidl::android::hardware::audio::sounddose
diff --git a/audio/aidl/sounddose/vts/Android.bp b/audio/aidl/sounddose/vts/Android.bp
new file mode 100644
index 0000000..88be968
--- /dev/null
+++ b/audio/aidl/sounddose/vts/Android.bp
@@ -0,0 +1,36 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalSoundDoseFactoryTargetTest",
+ defaults: [
+ "latest_android_hardware_audio_core_sounddose_ndk_static",
+ "latest_android_hardware_audio_sounddose_ndk_static",
+ "latest_android_media_audio_common_types_ndk_static",
+ "use_libaidlvintf_gtest_helper_static",
+ "VtsHalTargetTestDefaults",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ ],
+ srcs: [
+ "VtsHalSoundDoseFactoryTargetTest.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/audio/aidl/sounddose/vts/TEST_MAPPING b/audio/aidl/sounddose/vts/TEST_MAPPING
new file mode 100644
index 0000000..bebeed9
--- /dev/null
+++ b/audio/aidl/sounddose/vts/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalSoundDoseFactoryTargetTest"
+ }
+ ]
+}
diff --git a/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
new file mode 100644
index 0000000..7448c1f
--- /dev/null
+++ b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalSoundDose.Factory"
+#include <android-base/logging.h>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
+#include <android/binder_manager.h>
+
+#include <memory>
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+
+inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
+ if (status.isOk()) {
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure()
+ << "Expected the transaction \'" << expr << "\' to succeed\n"
+ << " but it has failed with: " << status;
+}
+
+} // namespace detail
+
+} // namespace android::hardware::audio::common::testing
+
+// Test that the transaction status 'isOk'
+#define EXPECT_IS_OK(ret) \
+ EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+
+using namespace android;
+
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
+class SoundDoseFactory : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService(GetParam())); }
+
+ void TearDown() override {}
+
+ void ConnectToService(const std::string& interfaceName) {
+ ndk::SpAIBinder binder =
+ ndk::SpAIBinder(AServiceManager_waitForService(interfaceName.c_str()));
+ if (binder == nullptr) {
+ LOG(ERROR) << "Failed to get service " << interfaceName;
+ } else {
+ LOG(DEBUG) << "Succeeded to get service " << interfaceName;
+ }
+ soundDoseFactory = ISoundDoseFactory::fromBinder(binder);
+ ASSERT_NE(soundDoseFactory, nullptr);
+ }
+
+ std::shared_ptr<ISoundDoseFactory> soundDoseFactory;
+};
+
+TEST_P(SoundDoseFactory, GetSoundDoseForSameModule) {
+ const std::string module = "primary";
+
+ std::shared_ptr<ISoundDose> soundDose1;
+ EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose1));
+
+ if (soundDose1 == nullptr) {
+ LOG(WARNING) << "Primary module does not support sound dose";
+ return;
+ }
+
+ std::shared_ptr<ISoundDose> soundDose2;
+ EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose2));
+ EXPECT_NE(nullptr, soundDose2);
+ EXPECT_EQ(soundDose1->asBinder(), soundDose2->asBinder())
+ << "getSoundDose must return the same interface for the same module";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SoundDoseFactoryTest, SoundDoseFactory,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISoundDoseFactory::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundDoseFactory);
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 068742d..26467c9 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -24,6 +24,7 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"libaudioaidlcommon",
+ "libaidlcommonsupport",
],
header_libs: ["libaudioaidl_headers"],
cflags: [
@@ -83,3 +84,9 @@
defaults: ["VtsHalAudioTargetTestDefaults"],
srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"],
}
+
+cc_test {
+ name: "VtsHalVisualizerTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalVisualizerTargetTest.cpp"],
+}
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
new file mode 100644
index 0000000..a7834fb
--- /dev/null
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/Vintf.h>
+
+#define LOG_TAG "VtsHalVisualizerTest"
+
+#include <Utils.h>
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kVisualizerTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::Visualizer;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName {
+ PARAM_INSTANCE_NAME,
+ PARAM_CAPTURE_SIZE,
+ PARAM_SCALING_MODE,
+ PARAM_MEASUREMENT_MODE,
+ PARAM_LATENCY,
+};
+using VisualizerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, Visualizer::ScalingMode,
+ Visualizer::MeasurementMode, int>;
+
+const int MIN_CAPTURE_SIZE = 128;
+const int MAX_CAPTURE_SIZE = 1024;
+const int MAX_LATENCY = 3000;
+
+const std::vector<int> kCaptureSizeValues = {MIN_CAPTURE_SIZE - 1, MIN_CAPTURE_SIZE,
+ MAX_CAPTURE_SIZE, MAX_CAPTURE_SIZE + 1};
+const std::vector<Visualizer::ScalingMode> kScalingModeValues = {
+ Visualizer::ScalingMode::NORMALIZED, Visualizer::ScalingMode::AS_PLAYED};
+const std::vector<Visualizer::MeasurementMode> kMeasurementModeValues = {
+ Visualizer::MeasurementMode::NONE, Visualizer::MeasurementMode::PEAK_RMS};
+const std::vector<int> kLatencyValues = {-1, 0, MAX_LATENCY, MAX_LATENCY + 1};
+
+class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
+ public EffectHelper {
+ public:
+ VisualizerParamTest()
+ : mCaptureSize(std::get<PARAM_CAPTURE_SIZE>(GetParam())),
+ mScalingMode(std::get<PARAM_SCALING_MODE>(GetParam())),
+ mMeasurementMode(std::get<PARAM_MEASUREMENT_MODE>(GetParam())),
+ mLatency(std::get<PARAM_LATENCY>(GetParam())) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ Visualizer vs = Visualizer::make<Visualizer::captureSizeBytes>(MIN_CAPTURE_SIZE);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::visualizer>(vs);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency = 0;
+
+ void SetAndGetCommonParameters() {
+ for (auto& it : mCommonTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // only get if parameter in range and set success
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::commonTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+ }
+ }
+
+ void SetAndGetSetOnlyParameters() {
+ for (auto& it : mSetOnlyParamTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isSetOnlyParamTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ expectParam.set<Parameter::specific>(specific);
+ ASSERT_STATUS(expected, mEffect->setParameter(expectParam));
+
+ // parameter defined in this setOnlyParameter union must be settable via
+ // setParameter(), but must not be gettable
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::setOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->getParameter(id, &getParam));
+ }
+ }
+
+ void GetandSetGetOnlyParameters() {
+ for (auto& tag : mGetOnlyParamTags) {
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::getOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ ASSERT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ // parameter defined in this getOnlyParameter union must be gettable via
+ // getParameter(), but must not be settable
+ // set parameter
+ ASSERT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->setParameter(getParam));
+ }
+ }
+
+ void addCaptureSizeParam(int captureSize) {
+ Visualizer vs;
+ vs.set<Visualizer::captureSizeBytes>(captureSize);
+ mCommonTags.push_back({Visualizer::captureSizeBytes, vs});
+ }
+
+ void addScalingModeParam(Visualizer::ScalingMode scalingMode) {
+ Visualizer vs;
+ vs.set<Visualizer::scalingMode>(scalingMode);
+ mCommonTags.push_back({Visualizer::scalingMode, vs});
+ }
+
+ void addMeasurementModeParam(Visualizer::MeasurementMode measurementMode) {
+ Visualizer vs;
+ vs.set<Visualizer::measurementMode>(measurementMode);
+ mCommonTags.push_back({Visualizer::measurementMode, vs});
+ }
+
+ void addLatencyParam(int latency) {
+ Visualizer vs;
+ Visualizer::SetOnlyParameters setOnlyParam;
+ setOnlyParam.set<Visualizer::SetOnlyParameters::latencyMs>(latency);
+ vs.set<Visualizer::setOnlyParameters>(setOnlyParam);
+ mSetOnlyParamTags.push_back({Visualizer::SetOnlyParameters::latencyMs, vs});
+ }
+
+ void addMeasurementTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::measurement);
+ }
+
+ void addCaptureBytesTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::captureBytes);
+ }
+
+ bool isTagInRange(const Visualizer::Tag& tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ int captureSize = vs.get<Visualizer::captureSizeBytes>();
+ return isCaptureSizeInRange(vsCap, captureSize);
+ }
+ case Visualizer::scalingMode:
+ case Visualizer::measurementMode:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isSetOnlyParamTagInRange(Visualizer::SetOnlyParameters::Tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ if (vs.getTag() != Visualizer::setOnlyParameters) return false;
+ Visualizer::SetOnlyParameters setOnlyParam = vs.get<Visualizer::setOnlyParameters>();
+ if (setOnlyParam.getTag() != Visualizer::SetOnlyParameters::latencyMs) return false;
+ int latency = setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>();
+ return isLatencyInRange(vsCap, latency);
+ }
+
+ bool isCaptureSizeInRange(const Visualizer::Capability& cap, int captureSize) const {
+ return (captureSize >= cap.captureSizeRange.minBytes &&
+ captureSize <= cap.captureSizeRange.maxBytes);
+ }
+
+ bool isLatencyInRange(const Visualizer::Capability& cap, int latency) const {
+ return (latency >= 0 && latency <= cap.maxLatencyMs);
+ }
+
+ private:
+ std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
+ std::vector<std::pair<Visualizer::SetOnlyParameters::Tag, Visualizer>> mSetOnlyParamTags;
+ std::vector<Visualizer::GetOnlyParameters::Tag> mGetOnlyParamTags;
+ void CleanUp() {
+ mCommonTags.clear();
+ mSetOnlyParamTags.clear();
+ mGetOnlyParamTags.clear();
+ }
+};
+
+TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetScalingMode) {
+ EXPECT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetLatency) {
+ EXPECT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ SetAndGetSetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetMeasurement) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementTag());
+ GetandSetGetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetCaptureBytes) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureBytesTag());
+ GetandSetGetOnlyParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VisualizerTest, VisualizerParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kVisualizerTypeUUID)),
+ testing::ValuesIn(kCaptureSizeValues),
+ testing::ValuesIn(kScalingModeValues),
+ testing::ValuesIn(kMeasurementModeValues),
+ testing::ValuesIn(kLatencyValues)),
+ [](const testing::TestParamInfo<VisualizerParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string captureSize = std::to_string(std::get<PARAM_CAPTURE_SIZE>(info.param));
+ std::string scalingMode =
+ std::to_string(static_cast<int>(std::get<PARAM_SCALING_MODE>(info.param)));
+ std::string measurementMode =
+ std::to_string(static_cast<int>(std::get<PARAM_MEASUREMENT_MODE>(info.param)));
+ std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_captureSize" + captureSize +
+ "_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
+ "_latency" + latency;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 9890be2..2fcfb23 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -38,9 +38,15 @@
name: "android.hardware.audio.service",
init_rc: ["android.hardware.audio.service.rc"],
+ vintf_fragments: ["android.hardware.audio.sounddose-aidl.xml"],
relative_install_path: "hw",
vendor: true,
+ defaults: [
+ "android_hardware_audio_config_defaults",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+
srcs: ["service.cpp"],
cflags: [
@@ -50,6 +56,7 @@
],
shared_libs: [
+ "//hardware/interfaces/audio/aidl/sounddose/default:libsounddoseserviceexampleimpl",
"libcutils",
"libbinder",
"libbinder_ndk",
@@ -58,10 +65,6 @@
"libutils",
"libhardware",
],
-
- defaults: [
- "android_hardware_audio_config_defaults",
- ],
}
// Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
new file mode 100644
index 0000000..a297bfb
--- /dev/null
+++ b/audio/common/all-versions/default/service/android.hardware.audio.sounddose-aidl.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.audio.sounddose</name>
+ <version>1</version>
+ <fqname>ISoundDoseFactory/default</fqname>
+ </hal>
+</manifest>
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index fbf6165..e79ad75 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,6 +20,10 @@
#include <string>
#include <vector>
+#include <SoundDoseFactory.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
@@ -33,6 +37,8 @@
using InterfacesList = std::vector<std::string>;
+using aidl::android::hardware::audio::sounddose::SoundDoseFactory;
+
/** Try to register the provided factories in the provided order.
* If any registers successfully, do not register any other and return true.
* If all fail, return false.
@@ -164,5 +170,13 @@
}
}
+ // Register ISoundDoseFactory interface as a workaround for using the audio AIDL HAL
+ auto soundDoseDefault = ndk::SharedRefBase::make<SoundDoseFactory>();
+ const std::string soundDoseDefaultName =
+ std::string() + SoundDoseFactory::descriptor + "/default";
+ binder_status_t status = AServiceManager_addService(soundDoseDefault->asBinder().get(),
+ soundDoseDefaultName.c_str());
+ CHECK_EQ(STATUS_OK, status);
+
joinRpcThreadpool();
}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index f51a8d0..9d93bb0 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -30,6 +30,7 @@
"android.hardware.audio.common.test.utility",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libstagefright_foundation",
],
shared_libs: [
diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp
index 9aeb4d2..88d1c74 100644
--- a/automotive/vehicle/aidl/Android.bp
+++ b/automotive/vehicle/aidl/Android.bp
@@ -27,6 +27,7 @@
srcs: [
"android/hardware/automotive/vehicle/**/*.aidl",
],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp
index 167e0c7..0f795f8 100644
--- a/biometrics/common/aidl/Android.bp
+++ b/biometrics/common/aidl/Android.bp
@@ -13,6 +13,7 @@
srcs: [
"android/hardware/biometrics/common/*.aidl",
],
+ frozen: true,
stability: "vintf",
backend: {
java: {
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 7b8099f..89d8625 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable AidlCasPluginDescriptor {
int caSystemId;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
index dd355af..b69cc33 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
union DestinationBuffer {
android.hardware.cas.SharedBuffer nonsecureMemory;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
index e169beb..28c9eb0 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICas {
void closeSession(in byte[] sessionId);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
index ebc13ce..db75062 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICasListener {
void onEvent(in int event, in int arg, in byte[] data);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
index 9bf7903..411891b 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IDescrambler {
int descramble(in android.hardware.cas.ScramblingControl scramblingControl, in android.hardware.cas.SubSample[] subSamples, in android.hardware.cas.SharedBuffer srcBuffer, in long srcOffset, in android.hardware.cas.DestinationBuffer dstBuffer, in long dstOffset);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
index f5c8018..1f945a7 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IMediaCasService {
android.hardware.cas.IDescrambler createDescrambler(in int CA_system_id);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
index e3923c7..c73f482 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
@@ -44,9 +44,9 @@
DVB_IDSA = 7,
MULTI2 = 8,
AES128 = 9,
- AES_CBC = 10,
- AES_ECB = 11,
- AES_SCTE52 = 12,
- TDES_ECB = 13,
- TDES_SCTE52 = 14,
+ AES_ECB = 10,
+ AES_SCTE52 = 11,
+ TDES_ECB = 12,
+ TDES_SCTE52 = 13,
+ AES_CBC = 14,
}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
index a18aa57..9200b1d 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SharedBuffer {
android.hardware.common.Ashmem heapBase;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
index 3d3a8a0..343c810 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable Status {
const int OK = 0;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
index 178cabc..165c0d4 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@Backing(type="byte") @VintfStability
enum StatusEvent {
PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
index d9ee3b4..5bd1a1e 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SubSample {
int numBytesOfClearData;
diff --git a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 55b328a..1dc7ac6 100644
--- a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -18,6 +18,7 @@
/**
* Describes a CAS plugin with its system ID and name.
+ * @hide
*/
@VintfStability
parcelable AidlCasPluginDescriptor {
diff --git a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
index 068f29d..74336c2 100644
--- a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
@@ -19,6 +19,9 @@
import android.hardware.cas.SharedBuffer;
import android.hardware.common.NativeHandle;
+/**
+ * @hide
+ */
@VintfStability
union DestinationBuffer {
/**
diff --git a/cas/aidl/android/hardware/cas/ICas.aidl b/cas/aidl/android/hardware/cas/ICas.aidl
index 4c938c7..e6494ae 100644
--- a/cas/aidl/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/android/hardware/cas/ICas.aidl
@@ -23,6 +23,7 @@
* ICas is the API to control the CAS. It is used to manage sessions, provision/refresh the cas
* system, and process the EMM/ECM messages. It also allows bi-directional, scheme-specific
* communications between the client and the cas system.
+ * @hide
*/
@VintfStability
interface ICas {
diff --git a/cas/aidl/android/hardware/cas/ICasListener.aidl b/cas/aidl/android/hardware/cas/ICasListener.aidl
index 32d843f..21cd257 100644
--- a/cas/aidl/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/android/hardware/cas/ICasListener.aidl
@@ -18,6 +18,9 @@
import android.hardware.cas.StatusEvent;
+/**
+ * @hide
+ */
@VintfStability
interface ICasListener {
/**
diff --git a/cas/aidl/android/hardware/cas/IDescrambler.aidl b/cas/aidl/android/hardware/cas/IDescrambler.aidl
index 33fbe75..0ac995c 100644
--- a/cas/aidl/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/android/hardware/cas/IDescrambler.aidl
@@ -23,6 +23,7 @@
/**
* IDescrambler is the API to control the descrambling operations.
+ * @hide
*/
@VintfStability
interface IDescrambler {
diff --git a/cas/aidl/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
index 8bc31f6..641c4a9 100644
--- a/cas/aidl/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
@@ -26,6 +26,7 @@
* cas HAL to create cas and descrambler plugin instances. A cas plugin instance
* opens cas sessions which are used to obtain keys for a descrambler session,
* which can in turn be used to descramble protected video content.
+ * @hide
*/
@VintfStability
interface IMediaCasService {
diff --git a/cas/aidl/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
index 9d73eba..2a4858a 100644
--- a/cas/aidl/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
@@ -70,11 +70,6 @@
AES128,
/**
- * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
- */
- AES_CBC,
-
- /**
* Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
*/
AES_ECB,
@@ -95,4 +90,9 @@
* Engineers (SCTE) 52 mode.
*/
TDES_SCTE52,
+
+ /**
+ * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
+ */
+ AES_CBC,
}
diff --git a/cas/aidl/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
index 8a94ff7..0c89cfe 100644
--- a/cas/aidl/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
@@ -22,6 +22,7 @@
* SharedBuffer describes a shared buffer which is defined by a heapBase, an
* offset and a size. The offset is relative to the shared memory base for the
* memory region identified by heapBase.
+ * @hide
*/
@VintfStability
parcelable SharedBuffer {
diff --git a/cas/aidl/android/hardware/cas/Status.aidl b/cas/aidl/android/hardware/cas/Status.aidl
index b2be34b..e7ae8ff 100644
--- a/cas/aidl/android/hardware/cas/Status.aidl
+++ b/cas/aidl/android/hardware/cas/Status.aidl
@@ -16,6 +16,9 @@
package android.hardware.cas;
+/**
+ * @hide
+ */
@VintfStability
parcelable Status {
/**
diff --git a/cas/aidl/android/hardware/cas/StatusEvent.aidl b/cas/aidl/android/hardware/cas/StatusEvent.aidl
index 0f62634..1fe732e 100644
--- a/cas/aidl/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/android/hardware/cas/StatusEvent.aidl
@@ -18,6 +18,7 @@
/**
* The Event Type for status change.
+ * @hide
*/
@VintfStability
@Backing(type="byte")
diff --git a/cas/aidl/android/hardware/cas/SubSample.aidl b/cas/aidl/android/hardware/cas/SubSample.aidl
index c1353cb..8e1ff77 100644
--- a/cas/aidl/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/android/hardware/cas/SubSample.aidl
@@ -19,6 +19,7 @@
/**
* A subsample consists of some number of bytes of clear (unscrambled)
* data followed by a number of bytes of scrambled data.
+ * @hide
*/
@VintfStability
parcelable SubSample {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 99d4bb7..5e1589b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -53,6 +53,14 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.audio.sounddose</name>
+ <version>1</version>
+ <interface>
+ <name>ISoundDoseFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.authsecret</name>
<version>1</version>
<interface>
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 4e3d1f7..3096fe5 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -65,57 +65,3 @@
],
test_suites: ["general-tests"],
}
-
-// --
-
-cc_library {
- name: "libcppbor",
- vendor_available: true,
- host_supported: true,
- srcs: [
- "src/cppbor.cpp",
- "src/cppbor_parse.cpp",
- ],
- export_include_dirs: [
- "include/cppbor",
- ],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_test {
- name: "cppbor_test",
- tidy_timeout_srcs: [
- "tests/cppbor_test.cpp",
- ],
- srcs: [
- "tests/cppbor_test.cpp",
- ],
- shared_libs: [
- "libcppbor_external",
- "libbase",
- ],
- static_libs: [
- "libgmock",
- ],
- test_suites: ["general-tests"],
-}
-
-cc_test_host {
- name: "cppbor_host_test",
- tidy_timeout_srcs: [
- "tests/cppbor_test.cpp",
- ],
- srcs: [
- "tests/cppbor_test.cpp",
- ],
- shared_libs: [
- "libcppbor_external",
- "libbase",
- ],
- static_libs: [
- "libgmock",
- ],
- test_suites: ["general-tests"],
-}
diff --git a/identity/support/include/cppbor/README.md b/identity/support/include/cppbor/README.md
deleted file mode 100644
index 723bfcf..0000000
--- a/identity/support/include/cppbor/README.md
+++ /dev/null
@@ -1,216 +0,0 @@
-CppBor: A Modern C++ CBOR Parser and Generator
-==============================================
-
-CppBor provides a natural and easy-to-use syntax for constructing and
-parsing CBOR messages. It does not (yet) support all features of
-CBOR, nor (yet) support validation against CDDL schemata, though both
-are planned. CBOR features that aren't supported include:
-
-* Indefinite length values
-* Semantic tagging
-* Floating point
-
-CppBor requires C++-17.
-
-## CBOR representation
-
-CppBor represents CBOR data items as instances of the `Item` class or,
-more precisely, as instances of subclasses of `Item`, since `Item` is a
-pure interface. The subclasses of `Item` correspond almost one-to-one
-with CBOR major types, and are named to match the CDDL names to which
-they correspond. They are:
-
-* `Uint` corresponds to major type 0, and can hold unsigned integers
- up through (2^64 - 1).
-* `Nint` corresponds to major type 1. It can only hold values from -1
- to -(2^63 - 1), since it's internal representation is an int64_t.
- This can be fixed, but it seems unlikely that applications will need
- the omitted range from -(2^63) to (2^64 - 1), since it's
- inconvenient to represent them in many programming languages.
-* `Int` is an abstract base of `Uint` and `Nint` that facilitates
- working with all signed integers representable with int64_t.
-* `Bstr` corresponds to major type 2, a byte string.
-* `Tstr` corresponds to major type 3, a text string.
-* `Array` corresponds to major type 4, an Array. It holds a
- variable-length array of `Item`s.
-* `Map` corresponds to major type 5, a Map. It holds a
- variable-length array of pairs of `Item`s.
-* `Simple` corresponds to major type 7. It's an abstract class since
- items require more specific type.
-* `Bool` is the only currently-implemented subclass of `Simple`.
-
-Note that major type 6, semantic tag, is not yet implemented.
-
-In practice, users of CppBor will rarely use most of these classes
-when generating CBOR encodings. This is because CppBor provides
-straightforward conversions from the obvious normal C++ types.
-Specifically, the following conversions are provided in appropriate
-contexts:
-
-* Signed and unsigned integers convert to `Uint` or `Nint`, as
- appropriate.
-* `std::string`, `std::string_view`, `const char*` and
- `std::pair<char iterator, char iterator>` convert to `Tstr`.
-* `std::vector<uint8_t>`, `std::pair<uint8_t iterator, uint8_t
- iterator>` and `std::pair<uint8_t*, size_t>` convert to `Bstr`.
-* `bool` converts to `Bool`.
-
-## CBOR generation
-
-### Complete tree generation
-
-The set of `encode` methods in `Item` provide the interface for
-producing encoded CBOR. The basic process for "complete tree"
-generation (as opposed to "incremental" generation, which is discussed
-below) is to construct an `Item` which models the data to be encoded,
-and then call one of the `encode` methods, whichever is convenient for
-the encoding destination. A trivial example:
-
-```
-cppbor::Uint val(0);
-std::vector<uint8_t> encoding = val.encode();
-```
-
- It's relatively rare that single values are encoded as above. More often, the
- "root" data item will be an `Array` or `Map` which contains a more complex structure.For example
- :
-
-``` using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec = // ...
- Map val("key1", Array(Map("key_a", 99 "key_b", vec), "foo"), "key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-This creates a map with two entries, with `Tstr` keys "Outer1" and
-"Outer2", respectively. The "Outer1" entry has as its value an
-`Array` containing a `Map` and a `Tstr`. The "Outer2" entry has a
-`Bool` value.
-
-This example demonstrates how automatic conversion of C++ types to
-CppBor `Item` subclass instances is done. Where the caller provides a
-C++ or C string, a `Tstr` entry is added. Where the caller provides
-an integer literal or variable, a `Uint` or `Nint` is added, depending
-on whether the value is positive or negative.
-
-As an alternative, a more fluent-style API is provided for building up
-structures. For example:
-
-```
-using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec = // ...
- Map val();
-val.add("key1", Array().add(Map().add("key_a", 99).add("key_b", vec)).add("foo")).add("key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
- An advantage of this interface over the constructor -
- based creation approach above is that it need not be done all at once
- .The `add` methods return a reference to the object added to to allow calls to be chained,
- but chaining is not necessary; calls can be made
-sequentially, as the data to add is available.
-
-#### `encode` methods
-
-There are several variations of `Item::encode`, all of which
-accomplish the same task but output the encoded data in different
-ways, and with somewhat different performance characteristics. The
-provided options are:
-
-* `bool encode(uint8\_t** pos, const uint8\_t* end)` encodes into the
- buffer referenced by the range [`*pos`, end). `*pos` is moved. If
- the encoding runs out of buffer space before finishing, the method
- returns false. This is the most efficient way to encode, into an
- already-allocated buffer.
-* `void encode(EncodeCallback encodeCallback)` calls `encodeCallback`
- for each encoded byte. It's the responsibility of the implementor
- of the callback to behave safely in the event that the output buffer
- (if applicable) is exhausted. This is less efficient than the prior
- method because it imposes an additional function call for each byte.
-* `template </*...*/> void encode(OutputIterator i)`
- encodes into the provided iterator. SFINAE ensures that the
- template doesn't match for non-iterators. The implementation
- actually uses the callback-based method, plus has whatever overhead
- the iterator adds.
-* `std::vector<uint8_t> encode()` creates a new std::vector, reserves
- sufficient capacity to hold the encoding, and inserts the encoded
- bytes with a std::pushback_iterator and the previous method.
-* `std::string toString()` does the same as the previous method, but
- returns a string instead of a vector.
-
-### Incremental generation
-
-Incremental generation requires deeper understanding of CBOR, because
-the library can't do as much to ensure that the output is valid. The
-basic tool for intcremental generation is the `encodeHeader`
-function. There are two variations, one which writes into a buffer,
-and one which uses a callback. Both simply write out the bytes of a
-header. To construct the same map as in the above examples,
-incrementally, one might write:
-
-```
-using namespace cppbor; // For example brevity
-
-std::vector encoding;
-auto iter = std::back_inserter(result);
-encodeHeader(MAP, 2 /* # of map entries */, iter);
-std::string s = "key1";
-encodeHeader(TSTR, s.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(ARRAY, 2 /* # of array entries */, iter);
-Map().add("key_a", 99).add("key_b", vec).encode(iter)
-s = "foo";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-s = "key2";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(SIMPLE, TRUE, iter);
-```
-
-As the above example demonstrates, the styles can be mixed -- Note the
-creation and encoding of the inner Map using the fluent style.
-
-## Parsing
-
-CppBor also supports parsing of encoded CBOR data, with the same
-feature set as encoding. There are two basic approaches to parsing,
-"full" and "stream"
-
-### Full parsing
-
-Full parsing means completely parsing a (possibly-compound) data
-item from a byte buffer. The `parse` functions that do not take a
-`ParseClient` pointer do this. They return a `ParseResult` which is a
-tuple of three values:
-
-* std::unique_ptr<Item> that points to the parsed item, or is nullptr
- if there was a parse error.
-* const uint8_t* that points to the byte after the end of the decoded
- item, or to the first unparseable byte in the event of an error.
-* std::string that is empty on success or contains an error message if
- a parse error occurred.
-
-Assuming a successful parse, you can then use `Item::type()` to
-discover the type of the parsed item (e.g. MAP), and then use the
-appropriate `Item::as*()` method (e.g. `Item::asMap()`) to get a
-pointer to an interface which allows you to retrieve specific values.
-
-### Stream parsing
-
-Stream parsing is more complex, but more flexible. To use
-StreamParsing, you must create your own subclass of `ParseClient` and
-call one of the `parse` functions that accepts it. See the
-`ParseClient` methods docstrings for details.
-
-One unusual feature of stream parsing is that the `ParseClient`
-callback methods not only provide the parsed Item, but also pointers
-to the portion of the buffer that encode that Item. This is useful
-if, for example, you want to find an element inside of a structure,
-and then copy the encoding of that sub-structure, without bothering to
-parse the rest.
-
-The full parser is implemented with the stream parser.
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
deleted file mode 100644
index af5d82e..0000000
--- a/identity/support/include/cppbor/cppbor.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <numeric>
-#include <string>
-#include <vector>
-
-namespace cppbor {
-
-enum MajorType : uint8_t {
- UINT = 0 << 5,
- NINT = 1 << 5,
- BSTR = 2 << 5,
- TSTR = 3 << 5,
- ARRAY = 4 << 5,
- MAP = 5 << 5,
- SEMANTIC = 6 << 5,
- SIMPLE = 7 << 5,
-};
-
-enum SimpleType {
- BOOLEAN,
- NULL_T, // Only two supported, as yet.
-};
-
-enum SpecialAddlInfoValues : uint8_t {
- FALSE = 20,
- TRUE = 21,
- NULL_V = 22,
- ONE_BYTE_LENGTH = 24,
- TWO_BYTE_LENGTH = 25,
- FOUR_BYTE_LENGTH = 26,
- EIGHT_BYTE_LENGTH = 27,
-};
-
-class Item;
-class Uint;
-class Nint;
-class Int;
-class Tstr;
-class Bstr;
-class Simple;
-class Bool;
-class Array;
-class Map;
-class Null;
-class Semantic;
-
-/**
- * Returns the size of a CBOR header that contains the additional info value addlInfo.
- */
-size_t headerSize(uint64_t addlInfo);
-
-/**
- * Encodes a CBOR header with the specified type and additional info into the range [pos, end).
- * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space
- * to write the header.
- */
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end);
-
-using EncodeCallback = std::function<void(uint8_t)>;
-
-/**
- * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to
- * encodeCallback.
- */
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback);
-
-/**
- * Encodes a CBOR header with the specified type and additional info, writing each byte to the
- * provided OutputIterator.
- */
-template <typename OutputIterator,
- typename = std::enable_if_t<std::is_base_of_v<
- std::output_iterator_tag,
- typename std::iterator_traits<OutputIterator>::iterator_category>>>
-void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) {
- return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; });
-}
-
-/**
- * Item represents a CBOR-encodeable data item. Item is an abstract interface with a set of virtual
- * methods that allow encoding of the item or conversion to the appropriate derived type.
- */
-class Item {
- public:
- virtual ~Item() {}
-
- /**
- * Returns the CBOR type of the item.
- */
- virtual MajorType type() const = 0;
-
- // These methods safely downcast an Item to the appropriate subclass.
- virtual const Int* asInt() const { return nullptr; }
- virtual const Uint* asUint() const { return nullptr; }
- virtual const Nint* asNint() const { return nullptr; }
- virtual const Tstr* asTstr() const { return nullptr; }
- virtual const Bstr* asBstr() const { return nullptr; }
- virtual const Simple* asSimple() const { return nullptr; }
- virtual const Map* asMap() const { return nullptr; }
- virtual const Array* asArray() const { return nullptr; }
- virtual const Semantic* asSemantic() const { return nullptr; }
-
- /**
- * Returns true if this is a "compound" item, i.e. one that contains one or more other items.
- */
- virtual bool isCompound() const { return false; }
-
- bool operator==(const Item& other) const&;
- bool operator!=(const Item& other) const& { return !(*this == other); }
-
- /**
- * Returns the number of bytes required to encode this Item into CBOR. Note that if this is a
- * complex Item, calling this method will require walking the whole tree.
- */
- virtual size_t encodedSize() const = 0;
-
- /**
- * Encodes the Item into buffer referenced by range [*pos, end). Returns a pointer to one past
- * the last position written. Returns nullptr if there isn't enough space to encode.
- */
- virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0;
-
- /**
- * Encodes the Item by passing each encoded byte to encodeCallback.
- */
- virtual void encode(EncodeCallback encodeCallback) const = 0;
-
- /**
- * Clones the Item
- */
- virtual std::unique_ptr<Item> clone() const = 0;
-
- /**
- * Encodes the Item into the provided OutputIterator.
- */
- template <typename OutputIterator,
- typename = typename std::iterator_traits<OutputIterator>::iterator_category>
- void encode(OutputIterator i) const {
- return encode([&](uint8_t v) { *i++ = v; });
- }
-
- /**
- * Encodes the Item into a new std::vector<uint8_t>.
- */
- std::vector<uint8_t> encode() const {
- std::vector<uint8_t> retval;
- retval.reserve(encodedSize());
- encode(std::back_inserter(retval));
- return retval;
- }
-
- /**
- * Encodes the Item into a new std::string.
- */
- std::string toString() const {
- std::string retval;
- retval.reserve(encodedSize());
- encode([&](uint8_t v) { retval.push_back(v); });
- return retval;
- }
-
- /**
- * Encodes only the header of the Item.
- */
- inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const {
- return ::cppbor::encodeHeader(type(), addlInfo, pos, end);
- }
-
- /**
- * Encodes only the header of the Item.
- */
- inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const {
- ::cppbor::encodeHeader(type(), addlInfo, encodeCallback);
- }
-};
-
-/**
- * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about
- * the sign.
- */
-class Int : public Item {
- public:
- bool operator==(const Int& other) const& { return value() == other.value(); }
-
- virtual int64_t value() const = 0;
-
- const Int* asInt() const override { return this; }
-};
-
-/**
- * Uint is a concrete Item that implements CBOR major type 0.
- */
-class Uint : public Int {
- public:
- static constexpr MajorType kMajorType = UINT;
-
- explicit Uint(uint64_t v) : mValue(v) {}
-
- bool operator==(const Uint& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Uint* asUint() const override { return this; }
-
- size_t encodedSize() const override { return headerSize(mValue); }
-
- int64_t value() const override { return mValue; }
- uint64_t unsignedValue() const { return mValue; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(mValue, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue, encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); }
-
- private:
- uint64_t mValue;
-};
-
-/**
- * Nint is a concrete Item that implements CBOR major type 1.
-
- * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only
- * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1]. It cannot
- * express values in the range [std::numeric_limits<int64_t>::min() - 1,
- * -std::numeric_limits<uint64_t>::max()].
- */
-class Nint : public Int {
- public:
- static constexpr MajorType kMajorType = NINT;
-
- explicit Nint(int64_t v);
-
- bool operator==(const Nint& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Nint* asNint() const override { return this; }
- size_t encodedSize() const override { return headerSize(addlInfo()); }
-
- int64_t value() const override { return mValue; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(addlInfo(), pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(addlInfo(), encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
-
- private:
- uint64_t addlInfo() const { return -1LL - mValue; }
-
- int64_t mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 2.
- */
-class Bstr : public Item {
- public:
- static constexpr MajorType kMajorType = BSTR;
-
- // Construct from a vector
- explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {}
-
- // Construct from a string
- explicit Bstr(const std::string& v)
- : mValue(reinterpret_cast<const uint8_t*>(v.data()),
- reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {}
-
- // Construct from a pointer/size pair
- explicit Bstr(const std::pair<const uint8_t*, size_t>& buf)
- : mValue(buf.first, buf.first + buf.second) {}
-
- // Construct from a pair of iterators
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
- // Construct from an iterator range.
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- Bstr(I1 begin, I2 end) : mValue(begin, end) {}
-
- bool operator==(const Bstr& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Bstr* asBstr() const override { return this; }
- size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue.size(), encodeCallback);
- encodeValue(encodeCallback);
- }
-
- const std::vector<uint8_t>& value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); }
-
- private:
- void encodeValue(EncodeCallback encodeCallback) const;
-
- std::vector<uint8_t> mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 3.
- */
-class Tstr : public Item {
- public:
- static constexpr MajorType kMajorType = TSTR;
-
- // Construct from a string
- explicit Tstr(std::string v) : mValue(std::move(v)) {}
-
- // Construct from a string_view
- explicit Tstr(const std::string_view& v) : mValue(v) {}
-
- // Construct from a C string
- explicit Tstr(const char* v) : mValue(std::string(v)) {}
-
- // Construct from a pair of iterators
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
- // Construct from an iterator range
- template <typename I1, typename I2,
- typename = typename std::iterator_traits<I1>::iterator_category,
- typename = typename std::iterator_traits<I2>::iterator_category>
- Tstr(I1 begin, I2 end) : mValue(begin, end) {}
-
- bool operator==(const Tstr& other) const& { return mValue == other.mValue; }
-
- MajorType type() const override { return kMajorType; }
- const Tstr* asTstr() const override { return this; }
- size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue.size(), encodeCallback);
- encodeValue(encodeCallback);
- }
-
- const std::string& value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); }
-
- private:
- void encodeValue(EncodeCallback encodeCallback) const;
-
- std::string mValue;
-};
-
-/**
- * CompoundItem is an abstract Item that provides common functionality for Items that contain other
- * items, i.e. Arrays (CBOR type 4) and Maps (CBOR type 5).
- */
-class CompoundItem : public Item {
- public:
- bool operator==(const CompoundItem& other) const&;
-
- virtual size_t size() const { return mEntries.size(); }
-
- bool isCompound() const override { return true; }
-
- size_t encodedSize() const override {
- return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()),
- [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
- }
-
- using Item::encode; // Make base versions visible.
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
- void encode(EncodeCallback encodeCallback) const override;
-
- virtual uint64_t addlInfo() const = 0;
-
- protected:
- std::vector<std::unique_ptr<Item>> mEntries;
-};
-
-/*
- * Array is a concrete Item that implements CBOR major type 4.
- *
- * Note that Arrays are not copyable. This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally. If you actually want to copy an Array,
- * use the clone() method.
- */
-class Array : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = ARRAY;
-
- Array() = default;
- Array(const Array& other) = delete;
- Array(Array&&) = default;
- Array& operator=(const Array&) = delete;
- Array& operator=(Array&&) = default;
-
- /**
- * Construct an Array from a variable number of arguments of different types. See
- * details::makeItem below for details on what types may be provided. In general, this accepts
- * all of the types you'd expect and doest the things you'd expect (integral values are addes as
- * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.).
- */
- template <typename... Args, typename Enable>
- Array(Args&&... args);
-
- /**
- * Append a single element to the Array, of any compatible type.
- */
- template <typename T>
- Array& add(T&& v) &;
- template <typename T>
- Array&& add(T&& v) &&;
-
- const std::unique_ptr<Item>& operator[](size_t index) const { return mEntries[index]; }
- std::unique_ptr<Item>& operator[](size_t index) { return mEntries[index]; }
-
- MajorType type() const override { return kMajorType; }
- const Array* asArray() const override { return this; }
-
- virtual std::unique_ptr<Item> clone() const override;
-
- uint64_t addlInfo() const override { return size(); }
-};
-
-/*
- * Map is a concrete Item that implements CBOR major type 5.
- *
- * Note that Maps are not copyable. This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally. If you actually want to copy a
- * Map, use the clone() method.
- */
-class Map : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = MAP;
-
- Map() = default;
- Map(const Map& other) = delete;
- Map(Map&&) = default;
- Map& operator=(const Map& other) = delete;
- Map& operator=(Map&&) = default;
-
- /**
- * Construct a Map from a variable number of arguments of different types. An even number of
- * arguments must be provided (this is verified statically). See details::makeItem below for
- * details on what types may be provided. In general, this accepts all of the types you'd
- * expect and doest the things you'd expect (integral values are addes as Uint or Nint,
- * std::string and char* are added as Tstr, bools are added as Bool, etc.).
- */
- template <typename... Args, typename Enable>
- Map(Args&&... args);
-
- /**
- * Append a key/value pair to the Map, of any compatible types.
- */
- template <typename Key, typename Value>
- Map& add(Key&& key, Value&& value) &;
- template <typename Key, typename Value>
- Map&& add(Key&& key, Value&& value) &&;
-
- size_t size() const override {
- assertInvariant();
- return mEntries.size() / 2;
- }
-
- template <typename Key, typename Enable>
- std::pair<std::unique_ptr<Item>&, bool> get(Key key);
-
- std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> operator[](
- size_t index) const {
- assertInvariant();
- return {mEntries[index * 2], mEntries[index * 2 + 1]};
- }
-
- std::pair<std::unique_ptr<Item>&, std::unique_ptr<Item>&> operator[](size_t index) {
- assertInvariant();
- return {mEntries[index * 2], mEntries[index * 2 + 1]};
- }
-
- MajorType type() const override { return kMajorType; }
- const Map* asMap() const override { return this; }
-
- virtual std::unique_ptr<Item> clone() const override;
-
- uint64_t addlInfo() const override { return size(); }
-
- private:
- void assertInvariant() const;
-};
-
-class Semantic : public CompoundItem {
- public:
- static constexpr MajorType kMajorType = SEMANTIC;
-
- template <typename T>
- explicit Semantic(uint64_t value, T&& child);
-
- Semantic(const Semantic& other) = delete;
- Semantic(Semantic&&) = default;
- Semantic& operator=(const Semantic& other) = delete;
- Semantic& operator=(Semantic&&) = default;
-
- size_t size() const override {
- assertInvariant();
- return 1;
- }
-
- size_t encodedSize() const override {
- return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(mValue),
- [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
- }
-
- MajorType type() const override { return kMajorType; }
- const Semantic* asSemantic() const override { return this; }
-
- const std::unique_ptr<Item>& child() const {
- assertInvariant();
- return mEntries[0];
- }
-
- std::unique_ptr<Item>& child() {
- assertInvariant();
- return mEntries[0];
- }
-
- uint64_t value() const { return mValue; }
-
- uint64_t addlInfo() const override { return value(); }
-
- virtual std::unique_ptr<Item> clone() const override {
- assertInvariant();
- return std::make_unique<Semantic>(mValue, mEntries[0]->clone());
- }
-
- protected:
- Semantic() = default;
- Semantic(uint64_t value) : mValue(value) {}
- uint64_t mValue;
-
- private:
- void assertInvariant() const;
-};
-
-/**
- * Simple is abstract Item that implements CBOR major type 7. It is intended to be subclassed to
- * create concrete Simple types. At present only Bool is provided.
- */
-class Simple : public Item {
- public:
- static constexpr MajorType kMajorType = SIMPLE;
-
- bool operator==(const Simple& other) const&;
-
- virtual SimpleType simpleType() const = 0;
- MajorType type() const override { return kMajorType; }
-
- const Simple* asSimple() const override { return this; }
-
- virtual const Bool* asBool() const { return nullptr; };
- virtual const Null* asNull() const { return nullptr; };
-};
-
-/**
- * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE
- * and FALSE.
- */
-class Bool : public Simple {
- public:
- static constexpr SimpleType kSimpleType = BOOLEAN;
-
- explicit Bool(bool v) : mValue(v) {}
-
- bool operator==(const Bool& other) const& { return mValue == other.mValue; }
-
- SimpleType simpleType() const override { return kSimpleType; }
- const Bool* asBool() const override { return this; }
-
- size_t encodedSize() const override { return 1; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(mValue ? TRUE : FALSE, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(mValue ? TRUE : FALSE, encodeCallback);
- }
-
- bool value() const { return mValue; }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); }
-
- private:
- bool mValue;
-};
-
-/**
- * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL
- */
-class Null : public Simple {
- public:
- static constexpr SimpleType kSimpleType = NULL_T;
-
- explicit Null() {}
-
- SimpleType simpleType() const override { return kSimpleType; }
- const Null* asNull() const override { return this; }
-
- size_t encodedSize() const override { return 1; }
-
- using Item::encode;
- uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
- return encodeHeader(NULL_V, pos, end);
- }
- void encode(EncodeCallback encodeCallback) const override {
- encodeHeader(NULL_V, encodeCallback);
- }
-
- virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); }
-};
-
-template <typename T>
-std::unique_ptr<T> downcastItem(std::unique_ptr<Item>&& v) {
- static_assert(std::is_base_of_v<Item, T> && !std::is_abstract_v<T>,
- "returned type is not an Item or is an abstract class");
- if (v && T::kMajorType == v->type()) {
- if constexpr (std::is_base_of_v<Simple, T>) {
- if (T::kSimpleType != v->asSimple()->simpleType()) {
- return nullptr;
- }
- }
- return std::unique_ptr<T>(static_cast<T*>(v.release()));
- } else {
- return nullptr;
- }
-}
-
-/**
- * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem.
- */
-namespace details {
-
-template <typename T, typename V, typename Enable = void>
-struct is_iterator_pair_over : public std::false_type {};
-
-template <typename I1, typename I2, typename V>
-struct is_iterator_pair_over<
- std::pair<I1, I2>, V,
- typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>>
- : public std::true_type {};
-
-template <typename T, typename V, typename Enable = void>
-struct is_unique_ptr_of_subclass_of_v : public std::false_type {};
-
-template <typename T, typename P>
-struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>,
- typename std::enable_if_t<std::is_base_of_v<T, P>>>
- : public std::true_type {};
-
-/* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair
- * of iterators (4)*/
-template <typename T, typename Enable = void>
-struct is_text_type_v : public std::false_type {};
-
-template <typename T>
-struct is_text_type_v<
- T, typename std::enable_if_t<
- /* case 1 */ //
- std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string>
- /* case 2 */ //
- || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view>
- /* case 3 */ //
- || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*> //
- || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*>
- /* case 4 */
- || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {};
-
-/**
- * Construct a unique_ptr<Item> from many argument types. Accepts:
- *
- * (a) booleans;
- * (b) integers, all sizes and signs;
- * (c) text strings, as defined by is_text_type_v above;
- * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T>
- * (d3); and
- * (e) Item subclass instances, including Array and Map. Items may be provided by naked pointer
- * (e1), unique_ptr (e2), reference (e3) or value (e3). If provided by reference or value, will
- * be moved if possible. If provided by pointer, ownership is taken.
- * (f) null pointer;
- */
-template <typename T>
-std::unique_ptr<Item> makeItem(T v) {
- Item* p = nullptr;
- if constexpr (/* case a */ std::is_same_v<T, bool>) {
- p = new Bool(v);
- } else if constexpr (/* case b */ std::is_integral_v<T>) { // b
- if (v < 0) {
- p = new Nint(v);
- } else {
- p = new Uint(static_cast<uint64_t>(v));
- }
- } else if constexpr (/* case c */ //
- details::is_text_type_v<T>::value) {
- p = new Tstr(v);
- } else if constexpr (/* case d1 */ //
- std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
- std::vector<uint8_t>>
- /* case d2 */ //
- || details::is_iterator_pair_over<T, uint8_t>::value
- /* case d3 */ //
- || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
- std::pair<uint8_t*, size_t>>) {
- p = new Bstr(v);
- } else if constexpr (/* case e1 */ //
- std::is_pointer_v<T> &&
- std::is_base_of_v<Item, std::remove_pointer_t<T>>) {
- p = v;
- } else if constexpr (/* case e2 */ //
- details::is_unique_ptr_of_subclass_of_v<Item, T>::value) {
- p = v.release();
- } else if constexpr (/* case e3 */ //
- std::is_base_of_v<Item, T>) {
- p = new T(std::move(v));
- } else if constexpr (/* case f */ std::is_null_pointer_v<T>) {
- p = new Null();
- } else {
- // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one
- // of the above ifs matches. But static_assert(false) always triggers.
- static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type");
- }
- return std::unique_ptr<Item>(p);
-}
-
-} // namespace details
-
-template <typename... Args,
- /* Prevent use as copy ctor */ typename = std::enable_if_t<
- (sizeof...(Args)) != 1 ||
- !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>>
-Array::Array(Args&&... args) {
- mEntries.reserve(sizeof...(args));
- (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename T>
-Array& Array::add(T&& v) & {
- mEntries.push_back(details::makeItem(std::forward<T>(v)));
- return *this;
-}
-
-template <typename T>
-Array&& Array::add(T&& v) && {
- mEntries.push_back(details::makeItem(std::forward<T>(v)));
- return std::move(*this);
-}
-
-template <typename... Args,
- /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
-Map::Map(Args&&... args) {
- static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries");
- mEntries.reserve(sizeof...(args));
- (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename Key, typename Value>
-Map& Map::add(Key&& key, Value&& value) & {
- mEntries.push_back(details::makeItem(std::forward<Key>(key)));
- mEntries.push_back(details::makeItem(std::forward<Value>(value)));
- return *this;
-}
-
-template <typename Key, typename Value>
-Map&& Map::add(Key&& key, Value&& value) && {
- this->add(std::forward<Key>(key), std::forward<Value>(value));
- return std::move(*this);
-}
-
-template <typename Key, typename = std::enable_if_t<std::is_integral_v<Key> ||
- details::is_text_type_v<Key>::value>>
-std::pair<std::unique_ptr<Item>&, bool> Map::get(Key key) {
- assertInvariant();
- auto keyItem = details::makeItem(key);
- for (size_t i = 0; i < mEntries.size(); i += 2) {
- if (*keyItem == *mEntries[i]) {
- return {mEntries[i + 1], true};
- }
- }
- return {keyItem, false};
-}
-
-template <typename T>
-Semantic::Semantic(uint64_t value, T&& child) : mValue(value) {
- mEntries.reserve(1);
- mEntries.push_back(details::makeItem(std::forward<T>(child)));
-}
-
-} // namespace cppbor
diff --git a/identity/support/include/cppbor/cppbor_parse.h b/identity/support/include/cppbor/cppbor_parse.h
deleted file mode 100644
index 66cd5a3..0000000
--- a/identity/support/include/cppbor/cppbor_parse.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "cppbor.h"
-
-namespace cppbor {
-
-using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>;
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, end).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-ParseResult parse(const uint8_t* begin, const uint8_t* end);
-
-/**
- * Parse the first CBOR data item (possibly compound) from the byte vector.
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const std::vector<uint8_t>& encoding) {
- return parse(encoding.data(), encoding.data() + encoding.size());
-}
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty. If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const uint8_t* begin, size_t size) {
- return parse(begin, begin + size);
-}
-
-class ParseClient;
-
-/**
- * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
-
-/**
- * Parse the CBOR data in the vector in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) {
- return parse(encoding.data(), encoding.data() + encoding.size(), parseClient);
-}
-
-/**
- * A pure interface that callers of the streaming parse functions must implement.
- */
-class ParseClient {
- public:
- virtual ~ParseClient() {}
-
- /**
- * Called when an item is found. The Item pointer points to the found item; use type() and
- * the appropriate as*() method to examine the value. hdrBegin points to the first byte of the
- * header, valueBegin points to the first byte of the value and end points one past the end of
- * the item. In the case of header-only items, such as integers, and compound items (ARRAY,
- * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to
- * the byte past the header.
- *
- * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content. For
- * Map and Array items, the size() method will return a correct value, but the index operators
- * are unsafe, and the object cannot be safely compared with another Array/Map.
- *
- * The method returns a ParseClient*. In most cases "return this;" will be the right answer,
- * but a different ParseClient may be returned, which the parser will begin using. If the method
- * returns nullptr, parsing will be aborted immediately.
- */
- virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end) = 0;
-
- /**
- * Called when the end of a compound item (MAP or ARRAY) is found. The item argument will be
- * the same one passed to the item() call -- and may be empty if item() moved its value out.
- * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the
- * first contained value, and one past the end of the last contained value, respectively.
- *
- * Note that the Item will have no content.
- *
- * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the
- * parsing by returning nullptr;
- */
- virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end) = 0;
-
- /**
- * Called when parsing encounters an error. position is set to the first unparsed byte (one
- * past the last successfully-parsed byte) and errorMessage contains an message explaining what
- * sort of error occurred.
- */
- virtual void error(const uint8_t* position, const std::string& errorMessage) = 0;
-};
-
-} // namespace cppbor
diff --git a/identity/support/src/cppbor.cpp b/identity/support/src/cppbor.cpp
deleted file mode 100644
index d289985..0000000
--- a/identity/support/src/cppbor.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
-Iterator writeBigEndian(T value, Iterator pos) {
- for (unsigned i = 0; i < sizeof(value); ++i) {
- *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
- value = static_cast<T>(value << 8);
- }
- return pos;
-}
-
-template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
-void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
- for (unsigned i = 0; i < sizeof(value); ++i) {
- cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
- value = static_cast<T>(value << 8);
- }
-}
-
-} // namespace
-
-size_t headerSize(uint64_t addlInfo) {
- if (addlInfo < ONE_BYTE_LENGTH) return 1;
- if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
- if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
- if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
- return 9;
-}
-
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
- size_t sz = headerSize(addlInfo);
- if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
- switch (sz) {
- case 1:
- *pos++ = type | static_cast<uint8_t>(addlInfo);
- return pos;
- case 2:
- *pos++ = type | ONE_BYTE_LENGTH;
- *pos++ = static_cast<uint8_t>(addlInfo);
- return pos;
- case 3:
- *pos++ = type | TWO_BYTE_LENGTH;
- return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
- case 5:
- *pos++ = type | FOUR_BYTE_LENGTH;
- return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
- case 9:
- *pos++ = type | EIGHT_BYTE_LENGTH;
- return writeBigEndian(addlInfo, pos);
- default:
- CHECK(false); // Impossible to get here.
- return nullptr;
- }
-}
-
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
- size_t sz = headerSize(addlInfo);
- switch (sz) {
- case 1:
- encodeCallback(type | static_cast<uint8_t>(addlInfo));
- break;
- case 2:
- encodeCallback(type | ONE_BYTE_LENGTH);
- encodeCallback(static_cast<uint8_t>(addlInfo));
- break;
- case 3:
- encodeCallback(type | TWO_BYTE_LENGTH);
- writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
- break;
- case 5:
- encodeCallback(type | FOUR_BYTE_LENGTH);
- writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
- break;
- case 9:
- encodeCallback(type | EIGHT_BYTE_LENGTH);
- writeBigEndian(addlInfo, encodeCallback);
- break;
- default:
- CHECK(false); // Impossible to get here.
- }
-}
-
-bool Item::operator==(const Item& other) const& {
- if (type() != other.type()) return false;
- switch (type()) {
- case UINT:
- return *asUint() == *(other.asUint());
- case NINT:
- return *asNint() == *(other.asNint());
- case BSTR:
- return *asBstr() == *(other.asBstr());
- case TSTR:
- return *asTstr() == *(other.asTstr());
- case ARRAY:
- return *asArray() == *(other.asArray());
- case MAP:
- return *asMap() == *(other.asMap());
- case SIMPLE:
- return *asSimple() == *(other.asSimple());
- case SEMANTIC:
- return *asSemantic() == *(other.asSemantic());
- default:
- CHECK(false); // Impossible to get here.
- return false;
- }
-}
-
-Nint::Nint(int64_t v) : mValue(v) {
- CHECK(v < 0) << "Only negative values allowed";
-}
-
-bool Simple::operator==(const Simple& other) const& {
- if (simpleType() != other.simpleType()) return false;
-
- switch (simpleType()) {
- case BOOLEAN:
- return *asBool() == *(other.asBool());
- case NULL_T:
- return true;
- default:
- CHECK(false); // Impossible to get here.
- return false;
- }
-}
-
-uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(mValue.size(), pos, end);
- if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
- return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Bstr::encodeValue(EncodeCallback encodeCallback) const {
- for (auto c : mValue) {
- encodeCallback(c);
- }
-}
-
-uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(mValue.size(), pos, end);
- if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
- return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Tstr::encodeValue(EncodeCallback encodeCallback) const {
- for (auto c : mValue) {
- encodeCallback(static_cast<uint8_t>(c));
- }
-}
-
-bool CompoundItem::operator==(const CompoundItem& other) const& {
- return type() == other.type() //
- && addlInfo() == other.addlInfo() //
- // Can't use vector::operator== because the contents are pointers. std::equal lets us
- // provide a predicate that does the dereferencing.
- && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
- [](auto& a, auto& b) -> bool { return *a == *b; });
-}
-
-uint8_t* CompoundItem::encode(uint8_t* pos, const uint8_t* end) const {
- pos = encodeHeader(addlInfo(), pos, end);
- if (!pos) return nullptr;
- for (auto& entry : mEntries) {
- pos = entry->encode(pos, end);
- if (!pos) return nullptr;
- }
- return pos;
-}
-
-void CompoundItem::encode(EncodeCallback encodeCallback) const {
- encodeHeader(addlInfo(), encodeCallback);
- for (auto& entry : mEntries) {
- entry->encode(encodeCallback);
- }
-}
-
-void Map::assertInvariant() const {
- CHECK(mEntries.size() % 2 == 0);
-}
-
-std::unique_ptr<Item> Map::clone() const {
- assertInvariant();
- auto res = std::make_unique<Map>();
- for (size_t i = 0; i < mEntries.size(); i += 2) {
- res->add(mEntries[i]->clone(), mEntries[i + 1]->clone());
- }
- return res;
-}
-
-std::unique_ptr<Item> Array::clone() const {
- auto res = std::make_unique<Array>();
- for (size_t i = 0; i < mEntries.size(); i++) {
- res->add(mEntries[i]->clone());
- }
- return res;
-}
-
-void Semantic::assertInvariant() const {
- CHECK(mEntries.size() == 1);
-}
-
-} // namespace cppbor
diff --git a/identity/support/src/cppbor_parse.cpp b/identity/support/src/cppbor_parse.cpp
deleted file mode 100644
index c9ebb8a..0000000
--- a/identity/support/src/cppbor_parse.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cppbor_parse.h"
-
-#include <sstream>
-#include <stack>
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
- const std::string& type) {
- std::stringstream errStream;
- errStream << "Need " << bytesNeeded << " byte(s) for " << type << ", have " << bytesAvail
- << ".";
- return errStream.str();
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
- ParseClient* parseClient) {
- if (pos + sizeof(T) > end) {
- parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
- return {false, 0, pos};
- }
-
- const uint8_t* intEnd = pos + sizeof(T);
- T result = 0;
- do {
- result = static_cast<T>((result << 8) | *pos++);
- } while (pos < intEnd);
- return {true, result, pos};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient);
-
-std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Uint>(value);
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- if (value > std::numeric_limits<int64_t>::max()) {
- parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
- return {hdrBegin, nullptr /* end parsing */};
- }
- std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<uint64_t>(value));
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
- const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
- ParseClient* parseClient) {
- std::unique_ptr<Item> item = std::make_unique<Null>();
- return {hdrEnd,
- parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-template <typename T>
-std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end,
- const std::string& errLabel,
- ParseClient* parseClient) {
- if (end - valueBegin < static_cast<ssize_t>(length)) {
- parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
- return {hdrBegin, nullptr /* end parsing */};
- }
-
- std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
- return {valueBegin + length,
- parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
-}
-
-class IncompleteItem {
- public:
- virtual ~IncompleteItem() {}
- virtual void add(std::unique_ptr<Item> item) = 0;
-};
-
-class IncompleteArray : public Array, public IncompleteItem {
- public:
- IncompleteArray(size_t size) : mSize(size) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return mSize; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(mSize);
- mEntries.push_back(std::move(item));
- }
-
- private:
- size_t mSize;
-};
-
-class IncompleteMap : public Map, public IncompleteItem {
- public:
- IncompleteMap(size_t size) : mSize(size) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return mSize; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(mSize * 2);
- mEntries.push_back(std::move(item));
- }
-
- private:
- size_t mSize;
-};
-
-class IncompleteSemantic : public Semantic, public IncompleteItem {
- public:
- IncompleteSemantic(uint64_t value) : Semantic(value) {}
-
- // We return the "complete" size, rather than the actual size.
- size_t size() const override { return 1; }
-
- void add(std::unique_ptr<Item> item) override {
- mEntries.reserve(1);
- mEntries.push_back(std::move(item));
- }
-};
-
-std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
- const uint8_t* pos, const uint8_t* end,
- const std::string& typeName,
- ParseClient* parseClient) {
- while (entryCount > 0) {
- --entryCount;
- if (pos == end) {
- parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
- return {hdrBegin, nullptr /* end parsing */};
- }
- std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
- if (!parseClient) return {hdrBegin, nullptr};
- }
- return {pos, parseClient};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleCompound(
- std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
- ParseClient* parseClient) {
- parseClient =
- parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
- if (!parseClient) return {hdrBegin, nullptr};
-
- const uint8_t* pos;
- std::tie(pos, parseClient) =
- handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
- if (!parseClient) return {hdrBegin, nullptr};
-
- return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient) {
- const uint8_t* pos = begin;
-
- MajorType type = static_cast<MajorType>(*pos & 0xE0);
- uint8_t tagInt = *pos & 0x1F;
- ++pos;
-
- bool success = true;
- uint64_t addlData;
- if (tagInt < ONE_BYTE_LENGTH || tagInt > EIGHT_BYTE_LENGTH) {
- addlData = tagInt;
- } else {
- switch (tagInt) {
- case ONE_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
- break;
-
- case TWO_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
- break;
-
- case FOUR_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
- break;
-
- case EIGHT_BYTE_LENGTH:
- std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
- break;
-
- default:
- CHECK(false); // It's impossible to get here
- break;
- }
- }
-
- if (!success) return {begin, nullptr};
-
- switch (type) {
- case UINT:
- return handleUint(addlData, begin, pos, parseClient);
-
- case NINT:
- return handleNint(addlData, begin, pos, parseClient);
-
- case BSTR:
- return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
-
- case TSTR:
- return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
-
- case ARRAY:
- return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
- end, "array", parseClient);
-
- case MAP:
- return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
- pos, end, "map", parseClient);
-
- case SEMANTIC:
- return handleCompound(std::make_unique<IncompleteSemantic>(addlData), 1, begin, pos,
- end, "semantic", parseClient);
-
- case SIMPLE:
- switch (addlData) {
- case TRUE:
- case FALSE:
- return handleBool(addlData, begin, pos, parseClient);
- case NULL_V:
- return handleNull(begin, pos, parseClient);
- }
- }
- CHECK(false); // Impossible to get here.
- return {};
-}
-
-class FullParseClient : public ParseClient {
- public:
- virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
- const uint8_t* end) override {
- if (mParentStack.empty() && !item->isCompound()) {
- // This is the first and only item.
- mTheItem = std::move(item);
- mPosition = end;
- return nullptr; // We're done.
- }
-
- if (item->isCompound()) {
- // Starting a new compound data item, i.e. a new parent. Save it on the parent stack.
- // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
- // existence until the corresponding itemEnd() call.
- assert(dynamic_cast<CompoundItem*>(item.get()));
- mParentStack.push(static_cast<CompoundItem*>(item.get()));
- return this;
- } else {
- appendToLastParent(std::move(item));
- return this;
- }
- }
-
- virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
- const uint8_t* end) override {
- CHECK(item->isCompound() && item.get() == mParentStack.top());
- mParentStack.pop();
-
- if (mParentStack.empty()) {
- mTheItem = std::move(item);
- mPosition = end;
- return nullptr; // We're done
- } else {
- appendToLastParent(std::move(item));
- return this;
- }
- }
-
- virtual void error(const uint8_t* position, const std::string& errorMessage) override {
- mPosition = position;
- mErrorMessage = errorMessage;
- }
-
- std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>
- parseResult() {
- std::unique_ptr<Item> p = std::move(mTheItem);
- return {std::move(p), mPosition, std::move(mErrorMessage)};
- }
-
- private:
- void appendToLastParent(std::unique_ptr<Item> item) {
- auto parent = mParentStack.top();
- assert(dynamic_cast<IncompleteItem*>(parent));
- if (parent->type() == ARRAY) {
- static_cast<IncompleteArray*>(parent)->add(std::move(item));
- } else if (parent->type() == MAP) {
- static_cast<IncompleteMap*>(parent)->add(std::move(item));
- } else if (parent->type() == SEMANTIC) {
- static_cast<IncompleteSemantic*>(parent)->add(std::move(item));
- } else {
- CHECK(false); // Impossible to get here.
- }
- }
-
- std::unique_ptr<Item> mTheItem;
- std::stack<CompoundItem*> mParentStack;
- const uint8_t* mPosition = nullptr;
- std::string mErrorMessage;
-};
-
-} // anonymous namespace
-
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
- parseRecursively(begin, end, parseClient);
-}
-
-std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
- std::string /* errMsg */>
-parse(const uint8_t* begin, const uint8_t* end) {
- FullParseClient parseClient;
- parse(begin, end, &parseClient);
- return parseClient.parseResult();
-}
-
-} // namespace cppbor
diff --git a/identity/support/tests/cppbor_test.cpp b/identity/support/tests/cppbor_test.cpp
deleted file mode 100644
index 3eb5598..0000000
--- a/identity/support/tests/cppbor_test.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <iomanip>
-#include <sstream>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-using namespace cppbor;
-using namespace std;
-
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::ByRef;
-using ::testing::InSequence;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::Truly;
-using ::testing::Unused;
-
-string hexDump(const string& str) {
- stringstream s;
- for (auto c : str) {
- s << setfill('0') << setw(2) << hex << (static_cast<unsigned>(c) & 0xff);
- }
- return s.str();
-}
-
-TEST(SimpleValueTest, UnsignedValueSizes) {
- // Check that unsigned integers encode to correct lengths, and that encodedSize() is correct.
- vector<pair<uint64_t /* value */, size_t /* expected encoded size */>> testCases{
- {0, 1},
- {1, 1},
- {23, 1},
- {24, 2},
- {255, 2},
- {256, 3},
- {65535, 3},
- {65536, 5},
- {4294967295, 5},
- {4294967296, 9},
- {std::numeric_limits<uint64_t>::max(), 9},
- };
- for (auto& testCase : testCases) {
- Uint val(testCase.first);
- EXPECT_EQ(testCase.second, val.encodedSize()) << "Wrong size for value " << testCase.first;
- EXPECT_EQ(val.encodedSize(), val.toString().size())
- << "encodedSize and encoding disagree for value " << testCase.first;
- }
-}
-
-TEST(SimpleValueTest, UnsignedValueEncodings) {
- EXPECT_EQ("\x00"s, Uint(0u).toString());
- EXPECT_EQ("\x01"s, Uint(1u).toString());
- EXPECT_EQ("\x0a"s, Uint(10u).toString());
- EXPECT_EQ("\x17"s, Uint(23u).toString());
- EXPECT_EQ("\x18\x18"s, Uint(24u).toString());
- EXPECT_EQ("\x18\x19"s, Uint(25u).toString());
- EXPECT_EQ("\x18\x64"s, Uint(100u).toString());
- EXPECT_EQ("\x19\x03\xe8"s, Uint(1000u).toString());
- EXPECT_EQ("\x1a\x00\x0f\x42\x40"s, Uint(1000000u).toString());
- EXPECT_EQ("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"s, Uint(1000000000000u).toString());
- EXPECT_EQ("\x1B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
- Uint(std::numeric_limits<int64_t>::max()).toString());
-}
-
-TEST(SimpleValueTest, NegativeValueEncodings) {
- EXPECT_EQ("\x20"s, Nint(-1).toString());
- EXPECT_EQ("\x28"s, Nint(-9).toString());
- EXPECT_EQ("\x29"s, Nint(-10).toString());
- EXPECT_EQ("\x36"s, Nint(-23).toString());
- EXPECT_EQ("\x37"s, Nint(-24).toString());
- EXPECT_EQ("\x38\x18"s, Nint(-25).toString());
- EXPECT_EQ("\x38\x62"s, Nint(-99).toString());
- EXPECT_EQ("\x38\x63"s, Nint(-100).toString());
- EXPECT_EQ("\x39\x03\xe6"s, Nint(-999).toString());
- EXPECT_EQ("\x39\x03\xe7"s, Nint(-1000).toString());
- EXPECT_EQ("\x3a\x00\x0f\x42\x3F"s, Nint(-1000000).toString());
- EXPECT_EQ("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"s, Nint(-1000000000000).toString());
- EXPECT_EQ("\x3B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
- Nint(std::numeric_limits<int64_t>::min()).toString());
-}
-
-TEST(SimpleValueDeathTest, NegativeValueEncodings) {
- EXPECT_DEATH(Nint(0), "");
- EXPECT_DEATH(Nint(1), "");
-}
-
-TEST(SimpleValueTest, BooleanEncodings) {
- EXPECT_EQ("\xf4"s, Bool(false).toString());
- EXPECT_EQ("\xf5"s, Bool(true).toString());
-}
-
-TEST(SimpleValueTest, ByteStringEncodings) {
- EXPECT_EQ("\x40", Bstr("").toString());
- EXPECT_EQ("\x41\x61", Bstr("a").toString());
- EXPECT_EQ("\x41\x41", Bstr("A").toString());
- EXPECT_EQ("\x44\x49\x45\x54\x46", Bstr("IETF").toString());
- EXPECT_EQ("\x42\x22\x5c", Bstr("\"\\").toString());
- EXPECT_EQ("\x42\xc3\xbc", Bstr("\xc3\xbc").toString());
- EXPECT_EQ("\x43\xe6\xb0\xb4", Bstr("\xe6\xb0\xb4").toString());
- EXPECT_EQ("\x44\xf0\x90\x85\x91", Bstr("\xf0\x90\x85\x91").toString());
- EXPECT_EQ("\x44\x01\x02\x03\x04", Bstr("\x01\x02\x03\x04").toString());
- EXPECT_EQ("\x44\x40\x40\x40\x40", Bstr("@@@@").toString());
-}
-
-TEST(SimpleValueTest, TextStringEncodings) {
- EXPECT_EQ("\x60"s, Tstr("").toString());
- EXPECT_EQ("\x61\x61"s, Tstr("a").toString());
- EXPECT_EQ("\x61\x41"s, Tstr("A").toString());
- EXPECT_EQ("\x64\x49\x45\x54\x46"s, Tstr("IETF").toString());
- EXPECT_EQ("\x62\x22\x5c"s, Tstr("\"\\").toString());
- EXPECT_EQ("\x62\xc3\xbc"s, Tstr("\xc3\xbc").toString());
- EXPECT_EQ("\x63\xe6\xb0\xb4"s, Tstr("\xe6\xb0\xb4").toString());
- EXPECT_EQ("\x64\xf0\x90\x85\x91"s, Tstr("\xf0\x90\x85\x91").toString());
- EXPECT_EQ("\x64\x01\x02\x03\x04"s, Tstr("\x01\x02\x03\x04").toString());
-}
-
-TEST(IsIteratorPairOverTest, All) {
- EXPECT_TRUE((
- details::is_iterator_pair_over<pair<string::iterator, string::iterator>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<string::const_iterator, string::iterator>,
- char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<string::iterator, string::const_iterator>,
- char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, char*>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<const char*, char*>, char>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, const char*>, char>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<string::iterator, string::iterator>,
- uint8_t>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<char*, char*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::const_iterator, vector<uint8_t>::iterator>,
- uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::const_iterator>,
- uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, uint8_t*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<const uint8_t*, uint8_t*>, uint8_t>::value));
- EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, uint8_t>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<
- pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, char>::value));
- EXPECT_FALSE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, char>::value));
-}
-
-TEST(MakeEntryTest, Boolean) {
- EXPECT_EQ("\xf4"s, details::makeItem(false)->toString());
-}
-
-TEST(MakeEntryTest, Integers) {
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint8_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint16_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint32_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint64_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int8_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int16_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int32_t>(0))->toString());
- EXPECT_EQ("\x00"s, details::makeItem(static_cast<int64_t>(0))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int8_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int16_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int32_t>(-1))->toString());
- EXPECT_EQ("\x20"s, details::makeItem(static_cast<int64_t>(-1))->toString());
-
- EXPECT_EQ("\x1b\xff\xff\xff\xff\xff\xff\xff\xff"s,
- details::makeItem(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()))
- ->toString());
-}
-
-TEST(MakeEntryTest, StdStrings) {
- string s1("hello");
- const string s2("hello");
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString()); // copy of string
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
- details::makeItem(s2)->toString()); // copy of const string
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
- details::makeItem(std::move(s1))->toString()); // move string
- EXPECT_EQ(0U, s1.size()); // Prove string was moved, not copied.
-}
-
-TEST(MakeEntryTest, StdStringViews) {
- string_view s1("hello");
- const string_view s2("hello");
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-}
-
-TEST(MakeEntryTest, CStrings) {
- char s1[] = "hello";
- const char s2[] = "hello";
- const char* s3 = "hello";
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s3)->toString());
-}
-
-TEST(MakeEntryTest, StringIteratorPairs) {
- // Use iterators from string to prove that "real" iterators work
- string s1 = "hello"s;
- pair<string::iterator, string::iterator> p1 = make_pair(s1.begin(), s1.end());
-
- const pair<string::iterator, string::iterator> p2 = p1;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p2)->toString());
-
- // Use char*s as iterators
- const char* s2 = "hello";
- pair p3 = make_pair(s2, s2 + 5);
- const pair p4 = p3;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p3)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p4)->toString());
-}
-
-TEST(MakeEntryTest, ByteStrings) {
- vector<uint8_t> v1 = {0x00, 0x01, 0x02};
- const vector<uint8_t> v2 = {0x00, 0x01, 0x02};
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v1)->toString()); // copy of vector
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v2)->toString()); // copy of const vector
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(std::move(v1))->toString()); // move vector
- EXPECT_EQ(0U, v1.size()); // Prove vector was moved, not copied.
-}
-
-TEST(MakeEntryTest, ByteStringIteratorPairs) {
- using vec = vector<uint8_t>;
- using iter = vec::iterator;
- vec v1 = {0x00, 0x01, 0x02};
- pair<iter, iter> p1 = make_pair(v1.begin(), v1.end());
- const pair<iter, iter> p2 = make_pair(v1.begin(), v1.end());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p2)->toString());
-
- // Use uint8_t*s as iterators
- uint8_t v2[] = {0x00, 0x01, 0x02};
- uint8_t* v3 = v2;
- pair<uint8_t*, uint8_t*> p3 = make_pair(v2, v2 + 3);
- const pair<uint8_t*, uint8_t*> p4 = make_pair(v2, v2 + 3);
- pair<uint8_t*, uint8_t*> p5 = make_pair(v3, v3 + 3);
- const pair<uint8_t*, uint8_t*> p6 = make_pair(v3, v3 + 3);
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p3)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p4)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p5)->toString());
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p6)->toString());
-}
-
-TEST(MakeEntryTest, ByteStringBuffers) {
- uint8_t v1[] = {0x00, 0x01, 0x02};
- EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(make_pair(v1, 3))->toString());
-}
-
-TEST(MakeEntryTest, ItemPointer) {
- Uint* p1 = new Uint(0);
- EXPECT_EQ("\x00"s, details::makeItem(p1)->toString());
- EXPECT_EQ("\x60"s, details::makeItem(new Tstr(string()))->toString());
-}
-
-TEST(MakeEntryTest, ItemReference) {
- Tstr str("hello"s);
- Tstr& strRef = str;
- const Tstr& strConstRef = str;
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(str)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strRef)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strConstRef)->toString());
- EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(std::move(str))->toString());
- EXPECT_EQ("\x60"s, details::makeItem(str)->toString()); // Prove that it moved
-
- EXPECT_EQ("\x00"s, details::makeItem(Uint(0))->toString());
-
- EXPECT_EQ("\x43\x00\x01\x02"s,
- details::makeItem(Bstr(vector<uint8_t>{0x00, 0x01, 0x02}))->toString());
-
- EXPECT_EQ("\x80"s, details::makeItem(Array())->toString());
- EXPECT_EQ("\xa0"s, details::makeItem(Map())->toString());
-}
-
-TEST(CompoundValueTest, ArrayOfInts) {
- EXPECT_EQ("\x80"s, Array().toString());
- Array(Uint(0)).toString();
-
- EXPECT_EQ("\x81\x00"s, Array(Uint(0U)).toString());
- EXPECT_EQ("\x82\x00\x01"s, Array(Uint(0), Uint(1)).toString());
- EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(Uint(0), Uint(1), Nint(-99)).toString());
-
- EXPECT_EQ("\x81\x00"s, Array(0).toString());
- EXPECT_EQ("\x82\x00\x01"s, Array(0, 1).toString());
- EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(0, 1, -99).toString());
-}
-
-TEST(CompoundValueTest, MapOfInts) {
- EXPECT_EQ("\xA0"s, Map().toString());
- EXPECT_EQ("\xA1\x00\x01"s, Map(Uint(0), Uint(1)).toString());
- // Maps with an odd number of arguments will fail to compile. Uncomment the next lines to test.
- // EXPECT_EQ("\xA1\x00"s, Map(Int(0)).toString());
- // EXPECT_EQ("\xA1\x00\x01\x02"s, Map(Int(0), Int(1), Int(2)).toString());
-}
-
-TEST(CompoundValueTest, MixedArray) {
- vector<uint8_t> vec = {3, 2, 1};
- EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Array(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
- EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Array(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, MixedMap) {
- vector<uint8_t> vec = {3, 2, 1};
- EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Map(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
- EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
- Map(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, NestedStructures) {
- vector<uint8_t> vec = {3, 2, 1};
-
- string expectedEncoding =
- "\xA2\x66\x4F\x75\x74\x65\x72\x31\x82\xA2\x66\x49\x6E\x6E\x65\x72\x31\x18\x63\x66\x49"
- "\x6E"
- "\x6E\x65\x72\x32\x43\x03\x02\x01\x63\x66\x6F\x6F\x66\x4F\x75\x74\x65\x72\x32\x0A"s;
-
- // Do it with explicitly-created Items
- EXPECT_EQ(expectedEncoding,
- Map(Tstr("Outer1"),
- Array( //
- Map(Tstr("Inner1"), Uint(99), Tstr("Inner2"), Bstr(vec)), Tstr("foo")),
- Tstr("Outer2"), //
- Uint(10))
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Now just use convertible types
- EXPECT_EQ(expectedEncoding, Map("Outer1",
- Array(Map("Inner1", 99, //
- "Inner2", vec),
- "foo"),
- "Outer2", 10)
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Finally, do it with the .add() method. This is slightly less efficient, but has the
- // advantage you can build a structure up incrementally, or somewhat fluently if you like.
- // First, fluently.
- EXPECT_EQ(expectedEncoding, Map().add("Outer1", Array().add(Map() //
- .add("Inner1", 99)
- .add("Inner2", vec))
- .add("foo"))
- .add("Outer2", 10)
- .toString());
- EXPECT_EQ(3U, vec.size());
-
- // Next, more incrementally
- Array arr;
- arr.add(Map() //
- .add("Inner1", 99)
- .add("Inner2", vec))
- .add("foo");
- EXPECT_EQ(3U, vec.size());
-
- Map m;
- m.add("Outer1", std::move(arr)); // Moving is necessary; Map and Array cannot be copied.
- m.add("Outer2", 10);
- auto s = m.toString();
- EXPECT_EQ(expectedEncoding, s);
-}
-
-TEST(EncodingMethodsTest, AllVariants) {
- Map map;
- map.add("key1", Array().add(Map() //
- .add("key_a", 9999999)
- .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03})
- .add("key_c", std::numeric_limits<uint64_t>::max())
- .add("key_d", std::numeric_limits<int16_t>::min()))
- .add("foo"))
- .add("key2", true);
-
- std::vector<uint8_t> buf;
- buf.resize(map.encodedSize());
-
- EXPECT_EQ(buf.data() + buf.size(), map.encode(buf.data(), buf.data() + buf.size()));
-
- EXPECT_EQ(buf, map.encode());
-
- std::vector<uint8_t> buf2;
- map.encode(std::back_inserter(buf2));
- EXPECT_EQ(buf, buf2);
-
- auto iter = buf.begin();
- map.encode([&](uint8_t c) { EXPECT_EQ(c, *iter++); });
-}
-
-TEST(EncodingMethodsTest, UintWithTooShortBuf) {
- Uint val(100000);
- vector<uint8_t> buf(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, TstrWithTooShortBuf) {
- Tstr val("01234567890123456789012345"s);
- vector<uint8_t> buf(1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
- buf.resize(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, BstrWithTooShortBuf) {
- Bstr val("01234567890123456789012345"s);
- vector<uint8_t> buf(1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
- buf.resize(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, ArrayWithTooShortBuf) {
- Array val("a", 5, -100);
-
- std::vector<uint8_t> buf(val.encodedSize() - 1);
- EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, MapWithTooShortBuf) {
- Map map;
- map.add("key1", Array().add(Map() //
- .add("key_a", 99)
- .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03}))
- .add("foo"))
- .add("key2", true);
-
- std::vector<uint8_t> buf(map.encodedSize() - 1);
- EXPECT_EQ(nullptr, map.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EqualityTest, Uint) {
- Uint val(99);
- EXPECT_EQ(val, Uint(99));
-
- EXPECT_NE(val, Uint(98));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Nint) {
- Nint val(-1);
- EXPECT_EQ(val, Nint(-1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Tstr) {
- Tstr val("99");
- EXPECT_EQ(val, Tstr("99"));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("98"));
- EXPECT_NE(val, Bstr("99"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bstr) {
- Bstr val("99");
- EXPECT_EQ(val, Bstr("99"));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(false));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bool) {
- Bool val(false);
- EXPECT_EQ(val, Bool(false));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Array) {
- Array val(99, 1);
- EXPECT_EQ(val, Array(99, 1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 2));
- EXPECT_NE(val, Array(98, 1));
- EXPECT_NE(val, Array(99, 1, 2));
- EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Map) {
- Map val(99, 1);
- EXPECT_EQ(val, Map(99, 1));
-
- EXPECT_NE(val, Uint(99));
- EXPECT_NE(val, Nint(-1));
- EXPECT_NE(val, Nint(-4));
- EXPECT_NE(val, Tstr("99"));
- EXPECT_NE(val, Bstr("98"));
- EXPECT_NE(val, Bool(true));
- EXPECT_NE(val, Array(99, 1));
- EXPECT_NE(val, Map(99, 2));
- EXPECT_NE(val, Map(99, 1, 99, 2));
-}
-
-TEST(ConvertTest, Uint) {
- unique_ptr<Item> item = details::makeItem(10);
-
- EXPECT_EQ(UINT, item->type());
- EXPECT_NE(nullptr, item->asInt());
- EXPECT_NE(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(10, item->asInt()->value());
- EXPECT_EQ(10, item->asUint()->value());
-}
-
-TEST(ConvertTest, Nint) {
- unique_ptr<Item> item = details::makeItem(-10);
-
- EXPECT_EQ(NINT, item->type());
- EXPECT_NE(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_NE(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(-10, item->asInt()->value());
- EXPECT_EQ(-10, item->asNint()->value());
-}
-
-TEST(ConvertTest, Tstr) {
- unique_ptr<Item> item = details::makeItem("hello");
-
- EXPECT_EQ(TSTR, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_NE(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ("hello"s, item->asTstr()->value());
-}
-
-TEST(ConvertTest, Bstr) {
- vector<uint8_t> vec{0x23, 0x24, 0x22};
- unique_ptr<Item> item = details::makeItem(vec);
-
- EXPECT_EQ(BSTR, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_NE(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(vec, item->asBstr()->value());
-}
-
-TEST(ConvertTest, Bool) {
- unique_ptr<Item> item = details::makeItem(false);
-
- EXPECT_EQ(SIMPLE, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_NE(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(BOOLEAN, item->asSimple()->simpleType());
- EXPECT_NE(nullptr, item->asSimple()->asBool());
-
- EXPECT_FALSE(item->asSimple()->asBool()->value());
-}
-
-TEST(ConvertTest, Map) {
- unique_ptr<Item> item(new Map);
-
- EXPECT_EQ(MAP, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_NE(nullptr, item->asMap());
- EXPECT_EQ(nullptr, item->asArray());
-
- EXPECT_EQ(0U, item->asMap()->size());
-}
-
-TEST(ConvertTest, Array) {
- unique_ptr<Item> item(new Array);
-
- EXPECT_EQ(ARRAY, item->type());
- EXPECT_EQ(nullptr, item->asInt());
- EXPECT_EQ(nullptr, item->asUint());
- EXPECT_EQ(nullptr, item->asNint());
- EXPECT_EQ(nullptr, item->asTstr());
- EXPECT_EQ(nullptr, item->asBstr());
- EXPECT_EQ(nullptr, item->asSimple());
- EXPECT_EQ(nullptr, item->asMap());
- EXPECT_NE(nullptr, item->asArray());
-
- EXPECT_EQ(0U, item->asArray()->size());
-}
-
-class MockParseClient : public ParseClient {
- public:
- MOCK_METHOD4(item, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end));
- MOCK_METHOD4(itemEnd, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
- const uint8_t* valueBegin, const uint8_t* end));
- MOCK_METHOD2(error, void(const uint8_t* position, const std::string& errorMessage));
-};
-
-MATCHER_P(IsType, value, std::string("Type ") + (negation ? "doesn't match" : "matches")) {
- return arg->type() == value;
-}
-
-MATCHER_P(MatchesItem, value, "") {
- return arg && *arg == value;
-}
-
-MATCHER_P(IsArrayOfSize, value, "") {
- return arg->type() == ARRAY && arg->asArray()->size() == value;
-}
-
-MATCHER_P(IsMapOfSize, value, "") {
- return arg->type() == MAP && arg->asMap()->size() == value;
-}
-
-TEST(StreamParseTest, Uint) {
- MockParseClient mpc;
-
- Uint val(100);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Nint) {
- MockParseClient mpc;
-
- Nint val(-10);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bool) {
- MockParseClient mpc;
-
- Bool val(true);
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Tstr) {
- MockParseClient mpc;
-
- Tstr val("Hello");
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bstr) {
- MockParseClient mpc;
-
- Bstr val("Hello");
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(_, _)).Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Array) {
- MockParseClient mpc;
-
- Array val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
- ASSERT_NE(val[2]->asArray(), nullptr);
- const Array& interior = *(val[2]->asArray());
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- {
- InSequence s;
- const uint8_t* pos = encBegin;
- EXPECT_CALL(mpc, item(IsArrayOfSize(val.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0])), pos, pos + 1, pos + 6))
- .WillOnce(Return(&mpc));
- pos += 6;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- const uint8_t* innerArrayBegin = pos;
- EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
- .WillOnce(Return(&mpc));
- pos += 8;
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
- innerArrayBegin + 1, pos))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[3])), pos, pos + 9, pos + 9))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(val.size()), encBegin, encBegin + 1, encEnd))
- .WillOnce(Return(&mpc));
- }
-
- EXPECT_CALL(mpc, error(_, _)) //
- .Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Map) {
- MockParseClient mpc;
-
- Map val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
- ASSERT_NE(val[1].first->asArray(), nullptr);
- const Array& interior = *(val[1].first->asArray());
- auto encoded = val.encode();
- uint8_t* encBegin = encoded.data();
- uint8_t* encEnd = encoded.data() + encoded.size();
-
- {
- InSequence s;
- const uint8_t* pos = encBegin;
- EXPECT_CALL(mpc, item(_, pos, pos + 1, pos + 1)).WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].first)), pos, pos + 1, pos + 6))
- .WillOnce(Return(&mpc));
- pos += 6;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].second)), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- const uint8_t* innerArrayBegin = pos;
- EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
- .WillOnce(Return(&mpc));
- ++pos;
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
- .WillOnce(Return(&mpc));
- pos += 8;
- EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
- innerArrayBegin + 1, pos))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1].second)), pos, pos + 9, pos + 9))
- .WillOnce(Return(&mpc));
- EXPECT_CALL(mpc, itemEnd(IsMapOfSize(val.size()), encBegin, encBegin + 1, encEnd))
- .WillOnce(Return(&mpc));
- }
-
- EXPECT_CALL(mpc, error(_, _)) //
- .Times(0);
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Semantic) {
- MockParseClient mpc;
-
- vector<uint8_t> encoded;
- auto iter = back_inserter(encoded);
- encodeHeader(SEMANTIC, 0, iter);
- Uint(999).encode(iter);
-
- EXPECT_CALL(mpc, item(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
- EXPECT_CALL(mpc, error(encoded.data(), "Semantic tags not supported"));
-
- parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(FullParserTest, Uint) {
- Uint val(10);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Nint) {
- Nint val(-10);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-
- vector<uint8_t> minNint = {0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
- std::tie(item, pos, message) = parse(minNint);
- EXPECT_THAT(item, NotNull());
- EXPECT_EQ(item->asNint()->value(), std::numeric_limits<int64_t>::min());
-}
-
-TEST(FullParserTest, NintOutOfRange) {
- vector<uint8_t> outOfRangeNint = {0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
- auto [item, pos, message] = parse(outOfRangeNint);
- EXPECT_THAT(item, IsNull());
- EXPECT_EQ(pos, outOfRangeNint.data());
- EXPECT_EQ(message, "NINT values that don't fit in int64_t are not supported.");
-}
-
-TEST(FullParserTest, Tstr) {
- Tstr val("Hello");
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Bstr) {
- Bstr val("\x00\x01\0x02"s);
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Array) {
- Array val("hello", -4, 3);
-
- auto encoded = val.encode();
- auto [item, pos, message] = parse(encoded);
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
- EXPECT_EQ(pos, encoded.data() + encoded.size());
- EXPECT_EQ("", message);
-
- // We've already checked it all, but walk it just for fun.
- ASSERT_NE(nullptr, item->asArray());
- const Array& arr = *(item->asArray());
- ASSERT_EQ(arr[0]->type(), TSTR);
- EXPECT_EQ(arr[0]->asTstr()->value(), "hello");
-}
-
-TEST(FullParserTest, Map) {
- Map val("hello", -4, 3, Bstr("hi"));
-
- auto [item, pos, message] = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, Complex) {
- vector<uint8_t> vec = {0x01, 0x02, 0x08, 0x03};
- Map val("Outer1",
- Array(Map("Inner1", 99, //
- "Inner2", vec),
- "foo"),
- "Outer2", 10);
-
- std::unique_ptr<Item> item;
- const uint8_t* pos;
- std::string message;
- std::tie(item, pos, message) = parse(val.encode());
- EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, IncompleteUint) {
- Uint val(1000);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Need 2 byte(s) for length field, have 1.", message);
-}
-
-TEST(FullParserTest, IncompleteString) {
- Tstr val("hello");
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Need 5 byte(s) for text string, have 3.", message);
-}
-
-TEST(FullParserTest, ArrayWithInsufficientEntries) {
- Array val(1, 2, 3, 4);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data(), pos);
- EXPECT_EQ("Not enough entries for array.", message);
-}
-
-TEST(FullParserTest, ArrayWithTruncatedEntry) {
- Array val(1, 2, 3, 400000);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data() + encoding.size() - 5, pos);
- EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-
-TEST(FullParserTest, MapWithTruncatedEntry) {
- Map val(1, 2, 300000, 4);
-
- auto encoding = val.encode();
- auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
- EXPECT_EQ(nullptr, item.get());
- EXPECT_EQ(encoding.data() + 3, pos);
- EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 95a14b2..5aa820c 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -12,6 +12,7 @@
host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/common/*.aidl"],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 98eafc1..0088264 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -12,6 +12,7 @@
vendor_available: true,
host_supported: true,
srcs: ["android/hardware/radio/*.aidl"],
+ frozen: true,
stability: "vintf",
backend: {
cpp: {
@@ -35,6 +36,7 @@
vendor_available: true,
host_supported: true,
srcs: ["android/hardware/radio/config/*.aidl"],
+ frozen: true,
stability: "vintf",
imports: ["android.hardware.radio"],
backend: {
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index cb1c692..aebcf67 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -783,4 +783,20 @@
INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
+using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
+
+INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
+
+TEST_P(VsrRequirementTest, VsrEnforcementTest) {
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+ int vsr_api_level = get_vsr_api_level();
+ if (vsr_api_level < 34) {
+ GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
+ << vsr_api_level;
+ }
+ EXPECT_GE(hwInfo.versionNumber, 3)
+ << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
+}
+
} // namespace aidl::android::hardware::security::keymint::test