[automerger skipped] identity: Fix attestation and documentation problems. am: e4f58f898f -s ours
am skip reason: Change-Id I2f8bd772de078556733f769cec2021918d1d7de6 with SHA-1 34abaaefcb is in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/13036974
Change-Id: Ie81f83da014f88616ce2dfc1e621508da5b37a7c
diff --git a/Android.bp b/Android.bp
index 9e1df13..00ba1e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,7 +15,6 @@
cc_defaults {
name: "VtsHalTargetTestDefaults",
defaults: [
- "vts_target_tests_defaults",
"hidl_defaults",
],
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+ license_type: NOTICE
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/atrace/1.0/Android.bp b/atrace/1.0/Android.bp
index c7e8d04..5290a9a 100644
--- a/atrace/1.0/Android.bp
+++ b/atrace/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.atrace@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAtraceDevice.hal",
diff --git a/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp
index 2eaa03e..d7a9e08 100644
--- a/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp
+++ b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp
@@ -93,6 +93,7 @@
EXPECT_EQ(Status::SUCCESS, ret);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtraceHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, AtraceHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAtraceDevice::descriptor)),
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
index 02f8b40..35f6803 100644
--- a/audio/2.0/Android.bp
+++ b/audio/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
index bc695c8..4957a14 100644
--- a/audio/4.0/Android.bp
+++ b/audio/4.0/Android.bp
@@ -5,9 +5,6 @@
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/audio/5.0/Android.bp b/audio/5.0/Android.bp
index 9b28497..365a654 100644
--- a/audio/5.0/Android.bp
+++ b/audio/5.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio@5.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/audio/6.0/Android.bp b/audio/6.0/Android.bp
index 16abc52..d7880b6 100644
--- a/audio/6.0/Android.bp
+++ b/audio/6.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio@6.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/audio/7.0/Android.bp b/audio/7.0/Android.bp
new file mode 100644
index 0000000..d07ce12
--- /dev/null
+++ b/audio/7.0/Android.bp
@@ -0,0 +1,25 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio@7.0",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IDevice.hal",
+ "IDevicesFactory.hal",
+ "IPrimaryDevice.hal",
+ "IStream.hal",
+ "IStreamIn.hal",
+ "IStreamOut.hal",
+ "IStreamOutCallback.hal",
+ "IStreamOutEventCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.effect@7.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
diff --git a/audio/7.0/IDevice.hal b/audio/7.0/IDevice.hal
new file mode 100644
index 0000000..e30e545
--- /dev/null
+++ b/audio/7.0/IDevice.hal
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import IStreamIn;
+import IStreamOut;
+
+interface IDevice {
+ /**
+ * Returns whether the audio hardware interface has been initialized.
+ *
+ * @return retval OK on success, NOT_INITIALIZED on failure.
+ */
+ initCheck() generates (Result retval);
+
+ /**
+ * Sets the audio volume for all audio activities other than voice call. If
+ * NOT_SUPPORTED is returned, the software mixer will emulate this
+ * capability.
+ *
+ * @param volume 1.0f means unity, 0.0f is zero.
+ * @return retval operation completion status.
+ */
+ setMasterVolume(float volume) generates (Result retval);
+
+ /**
+ * Get the current master volume value for the HAL, if the HAL supports
+ * master volume control. For example, AudioFlinger will query this value
+ * from the primary audio HAL when the service starts and use the value for
+ * setting the initial master volume across all HALs. HALs which do not
+ * support this method must return NOT_SUPPORTED in 'retval'.
+ *
+ * @return retval operation completion status.
+ * @return volume 1.0f means unity, 0.0f is zero.
+ */
+ getMasterVolume() generates (Result retval, float volume);
+
+ /**
+ * Sets microphone muting state.
+ *
+ * @param mute whether microphone is muted.
+ * @return retval operation completion status.
+ */
+ setMicMute(bool mute) generates (Result retval);
+
+ /**
+ * Gets whether microphone is muted.
+ *
+ * @return retval operation completion status.
+ * @return mute whether microphone is muted.
+ */
+ getMicMute() generates (Result retval, bool mute);
+
+ /**
+ * Set the audio mute status for all audio activities. If the return value
+ * is NOT_SUPPORTED, the software mixer will emulate this capability.
+ *
+ * @param mute whether audio is muted.
+ * @return retval operation completion status.
+ */
+ setMasterMute(bool mute) generates (Result retval);
+
+ /**
+ * Get the current master mute status for the HAL, if the HAL supports
+ * master mute control. AudioFlinger will query this value from the primary
+ * audio HAL when the service starts and use the value for setting the
+ * initial master mute across all HALs. HAL must indicate that the feature
+ * is not supported by returning NOT_SUPPORTED status.
+ *
+ * @return retval operation completion status.
+ * @return mute whether audio is muted.
+ */
+ getMasterMute() generates (Result retval, bool mute);
+
+ /**
+ * Returns audio input buffer size according to parameters passed or
+ * INVALID_ARGUMENTS if one of the parameters is not supported.
+ *
+ * @param config audio configuration.
+ * @return retval operation completion status.
+ * @return bufferSize input buffer size in bytes.
+ */
+ getInputBufferSize(AudioConfig config)
+ generates (Result retval, uint64_t bufferSize);
+
+ /**
+ * This method creates and opens the audio hardware output stream.
+ * If the stream can not be opened with the proposed audio config,
+ * HAL must provide suggested values for the audio config.
+ *
+ * @param ioHandle handle assigned by AudioFlinger.
+ * @param device device type and (if needed) address.
+ * @param config stream configuration.
+ * @param flags additional flags.
+ * @param sourceMetadata Description of the audio that will be played.
+ May be used by implementations to configure hardware effects.
+ * @return retval operation completion status.
+ * @return outStream created output stream.
+ * @return suggestedConfig in case of invalid parameters, suggested config.
+ */
+ openOutputStream(
+ AudioIoHandle ioHandle,
+ DeviceAddress device,
+ AudioConfig config,
+ vec<AudioInOutFlag> flags,
+ SourceMetadata sourceMetadata) generates (
+ Result retval,
+ IStreamOut outStream,
+ AudioConfig suggestedConfig);
+
+ /**
+ * This method creates and opens the audio hardware input stream.
+ * If the stream can not be opened with the proposed audio config,
+ * HAL must provide suggested values for the audio config.
+ *
+ * @param ioHandle handle assigned by AudioFlinger.
+ * @param device device type and (if needed) address.
+ * @param config stream configuration.
+ * @param flags additional flags.
+ * @param sinkMetadata Description of the audio that is suggested by the client.
+ * May be used by implementations to configure processing effects.
+ * @return retval operation completion status.
+ * @return inStream in case of success, created input stream.
+ * @return suggestedConfig in case of invalid parameters, suggested config.
+ */
+ openInputStream(
+ AudioIoHandle ioHandle,
+ DeviceAddress device,
+ AudioConfig config,
+ vec<AudioInOutFlag> flags,
+ SinkMetadata sinkMetadata) generates (
+ Result retval,
+ IStreamIn inStream,
+ AudioConfig suggestedConfig);
+
+ /**
+ * Returns whether HAL supports audio patches. Patch represents a connection
+ * between signal source(s) and signal sink(s). If HAL doesn't support
+ * patches natively (in hardware) then audio system will need to establish
+ * them in software.
+ *
+ * @return supports true if audio patches are supported.
+ */
+ supportsAudioPatches() generates (bool supports);
+
+ /**
+ * Creates an audio patch between several source and sink ports. The handle
+ * is allocated by the HAL and must be unique for this audio HAL module.
+ *
+ * @param sources patch sources.
+ * @param sinks patch sinks.
+ * @return retval operation completion status.
+ * @return patch created patch handle.
+ */
+ createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
+ generates (Result retval, AudioPatchHandle patch);
+
+ /**
+ * Updates an audio patch.
+ *
+ * Use of this function is preferred to releasing and re-creating a patch
+ * as the HAL module can figure out a way of switching the route without
+ * causing audio disruption.
+ *
+ * @param previousPatch handle of the previous patch to update.
+ * @param sources new patch sources.
+ * @param sinks new patch sinks.
+ * @return retval operation completion status.
+ * @return patch updated patch handle.
+ */
+ updateAudioPatch(
+ AudioPatchHandle previousPatch,
+ vec<AudioPortConfig> sources,
+ vec<AudioPortConfig> sinks) generates (
+ Result retval, AudioPatchHandle patch);
+
+ /**
+ * Release an audio patch.
+ *
+ * @param patch patch handle.
+ * @return retval operation completion status.
+ */
+ releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
+
+ /**
+ * Returns the list of supported attributes for a given audio port.
+ *
+ * As input, 'port' contains the information (type, role, address etc...)
+ * needed by the HAL to identify the port.
+ *
+ * As output, 'resultPort' contains possible attributes (sampling rates,
+ * formats, channel masks, gain controllers...) for this port.
+ *
+ * @param port port identifier.
+ * @return retval operation completion status.
+ * @return resultPort port descriptor with all parameters filled up.
+ */
+ getAudioPort(AudioPort port)
+ generates (Result retval, AudioPort resultPort);
+
+ /**
+ * Set audio port configuration.
+ *
+ * @param config audio port configuration.
+ * @return retval operation completion status.
+ */
+ setAudioPortConfig(AudioPortConfig config) generates (Result retval);
+
+ /**
+ * Gets the HW synchronization source of the device. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_HW_AV_SYNC on the legacy HAL.
+ * Optional method
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ * @return hwAvSync HW synchronization source
+ */
+ getHwAvSync() generates (Result retval, AudioHwSync hwAvSync);
+
+ /**
+ * Sets whether the screen is on. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_KEY_SCREEN_STATE on the legacy HAL.
+ * Optional method
+ *
+ * @param turnedOn whether the screen is turned on.
+ * @return retval operation completion status.
+ */
+ setScreenState(bool turnedOn) generates (Result retval);
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be retrieved at the same time.
+ * The implementation should return as many requested parameters
+ * as possible, even if one or more is not supported
+ *
+ * @param context provides more information about the request
+ * @param keys keys of the requested parameters
+ * @return retval operation completion status.
+ * OK must be returned if keys is empty.
+ * NOT_SUPPORTED must be returned if at least one key is unknown.
+ * @return parameters parameter key value pairs.
+ * Must contain the value of all requested keys if retval == OK
+ */
+ getParameters(vec<ParameterValue> context, vec<string> keys)
+ generates (Result retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be set at the same time though this is
+ * discouraged as it make failure analysis harder.
+ *
+ * If possible, a failed setParameters should not impact the platform state.
+ *
+ * @param context provides more information about the request
+ * @param parameters parameter key value pairs.
+ * @return retval operation completion status.
+ * All parameters must be successfully set for OK to be returned
+ */
+ setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+ generates (Result retval);
+
+ /**
+ * Returns an array with available microphones in device.
+ *
+ * @return retval NOT_SUPPORTED if there are no microphones on this device
+ * INVALID_STATE if the call is not successful,
+ * OK otherwise.
+ *
+ * @return microphones array with microphones info
+ */
+ getMicrophones()
+ generates(Result retval, vec<MicrophoneInfo> microphones);
+
+ /**
+ * Notifies the device module about the connection state of an input/output
+ * device attached to it. Calling this method is equivalent to setting
+ * AUDIO_PARAMETER_DEVICE_[DIS]CONNECT on the legacy HAL.
+ *
+ * @param address audio device specification.
+ * @param connected whether the device is connected.
+ * @return retval operation completion status.
+ */
+ setConnectedState(DeviceAddress address, bool connected)
+ generates (Result retval);
+
+ /**
+ * Called by the framework to deinitialize the device and free up
+ * all currently allocated resources. It is recommended to close
+ * the device on the client side as soon as it is becomes unused.
+ *
+ * Note that all streams must be closed by the client before
+ * attempting to close the device they belong to.
+ *
+ * @return retval OK in case the success.
+ * INVALID_STATE if the device was already closed
+ * or there are streams currently opened.
+ */
+ close() generates (Result retval);
+
+ /**
+ * Applies an audio effect to an audio device. The effect is inserted
+ * according to its insertion preference specified by INSERT_... EffectFlags
+ * in the EffectDescriptor.
+ *
+ * @param device identifies the sink or source device this effect must be applied to.
+ * "device" is the AudioPortHandle indicated for the device when the audio
+ * patch connecting that device was created.
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect to add.
+ * @return retval operation completion status.
+ */
+ addDeviceEffect(AudioPortHandle device, uint64_t effectId) generates (Result retval);
+
+ /**
+ * Stops applying an audio effect to an audio device.
+ *
+ * @param device identifies the sink or source device this effect was applied to.
+ * "device" is the AudioPortHandle indicated for the device when the audio
+ * patch is created at the audio HAL.
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect.
+ * @return retval operation completion status.
+ */
+ removeDeviceEffect(AudioPortHandle device, uint64_t effectId) generates (Result retval);
+};
diff --git a/audio/7.0/IDevicesFactory.hal b/audio/7.0/IDevicesFactory.hal
new file mode 100644
index 0000000..03549b4
--- /dev/null
+++ b/audio/7.0/IDevicesFactory.hal
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import IDevice;
+import IPrimaryDevice;
+
+/** This factory allows a HAL implementation to be split in multiple independent
+ * devices (called module in the pre-treble API).
+ * Note that this division is arbitrary and implementation are free
+ * to only have a Primary.
+ * The framework will query the devices according to audio_policy_configuration.xml
+ *
+ * Each device name is arbitrary, provided by the vendor's audio_policy_configuration.xml
+ * and only used to identify a device in this factory.
+ * The framework must not interpret the name, treating it as a vendor opaque data
+ * with the following exception:
+ * - the "r_submix" device that must be present to support policyMixes (Eg: Android projected).
+ * Note that this Device is included by default in a build derived from AOSP.
+ *
+ * Note that on AOSP Oreo (including MR1) the "a2dp" module is not using this API
+ * but is loaded directly from the system partition using the legacy API
+ * due to limitations with the Bluetooth framework.
+ */
+interface IDevicesFactory {
+
+ /**
+ * Opens an audio device. To close the device, it is necessary to release
+ * references to the returned device object.
+ *
+ * @param device device name.
+ * @return retval operation completion status. Returns INVALID_ARGUMENTS
+ * if there is no corresponding hardware module found,
+ * NOT_INITIALIZED if an error occurred while opening the hardware
+ * module.
+ * @return result the interface for the created device.
+ */
+ openDevice(string device) generates (Result retval, IDevice result);
+
+ /**
+ * Opens the Primary audio device that must be present.
+ * This function is not optional and must return successfully the primary device.
+ *
+ * This device must have the name "primary".
+ *
+ * The telephony stack uses this device to control the audio during a voice call.
+ *
+ * @return retval operation completion status. Must be SUCCESS.
+ * For debugging, return INVALID_ARGUMENTS if there is no corresponding
+ * hardware module found, NOT_INITIALIZED if an error occurred
+ * while opening the hardware module.
+ * @return result the interface for the created device.
+ */
+ openPrimaryDevice() generates (Result retval, IPrimaryDevice result);
+};
diff --git a/audio/7.0/IPrimaryDevice.hal b/audio/7.0/IPrimaryDevice.hal
new file mode 100644
index 0000000..1427ae8
--- /dev/null
+++ b/audio/7.0/IPrimaryDevice.hal
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import IDevice;
+
+interface IPrimaryDevice extends IDevice {
+ /**
+ * Sets the audio volume of a voice call.
+ *
+ * @param volume 1.0f means unity, 0.0f is zero.
+ * @return retval operation completion status.
+ */
+ setVoiceVolume(float volume) generates (Result retval);
+
+ /**
+ * This method is used to notify the HAL about audio mode changes.
+ *
+ * @param mode new mode.
+ * @return retval operation completion status.
+ */
+ setMode(AudioMode mode) generates (Result retval);
+
+ /**
+ * Sets the name of the current BT SCO headset. Calling this method
+ * is equivalent to setting legacy "bt_headset_name" parameter.
+ * The BT SCO headset name must only be used for debugging purposes.
+ * Optional method
+ *
+ * @param name the name of the current BT SCO headset (can be empty).
+ * @return retval operation completion status.
+ */
+ setBtScoHeadsetDebugName(string name) generates (Result retval);
+
+ /**
+ * Gets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+ * Calling this method is equivalent to getting AUDIO_PARAMETER_KEY_BT_NREC
+ * on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether BT SCO NR + EC are enabled.
+ */
+ getBtScoNrecEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+ * Calling this method is equivalent to setting AUDIO_PARAMETER_KEY_BT_NREC
+ * on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether BT SCO NR + EC are enabled.
+ * @return retval operation completion status.
+ */
+ setBtScoNrecEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Gets whether BT SCO Wideband mode is enabled. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether BT Wideband is enabled.
+ */
+ getBtScoWidebandEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether BT SCO Wideband mode is enabled. Calling this method is
+ * equivalent to setting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether BT Wideband is enabled.
+ * @return retval operation completion status.
+ */
+ setBtScoWidebandEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Gets whether BT HFP (Hands-Free Profile) is enabled. Calling this method
+ * is equivalent to getting "hfp_enable" parameter value on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether BT HFP is enabled.
+ */
+ getBtHfpEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether BT HFP (Hands-Free Profile) is enabled. Calling this method
+ * is equivalent to setting "hfp_enable" parameter on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether BT HFP is enabled.
+ * @return retval operation completion status.
+ */
+ setBtHfpEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Sets the sampling rate of BT HFP (Hands-Free Profile). Calling this
+ * method is equivalent to setting "hfp_set_sampling_rate" parameter
+ * on the legacy HAL.
+ * Optional method
+ *
+ * @param sampleRateHz sample rate in Hz.
+ * @return retval operation completion status.
+ */
+ setBtHfpSampleRate(uint32_t sampleRateHz) generates (Result retval);
+
+ /**
+ * Sets the current output volume Hz for BT HFP (Hands-Free Profile).
+ * Calling this method is equivalent to setting "hfp_volume" parameter value
+ * on the legacy HAL (except that legacy HAL implementations expect
+ * an integer value in the range from 0 to 15.)
+ * Optional method
+ *
+ * @param volume 1.0f means unity, 0.0f is zero.
+ * @return retval operation completion status.
+ */
+ setBtHfpVolume(float volume) generates (Result retval);
+
+ enum TtyMode : int32_t {
+ OFF,
+ VCO,
+ HCO,
+ FULL
+ };
+
+ /**
+ * Gets current TTY mode selection. Calling this method is equivalent to
+ * getting AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return mode TTY mode.
+ */
+ getTtyMode() generates (Result retval, TtyMode mode);
+
+ /**
+ * Sets current TTY mode. Calling this method is equivalent to setting
+ * AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+ *
+ * @param mode TTY mode.
+ * @return retval operation completion status.
+ */
+ setTtyMode(TtyMode mode) generates (Result retval);
+
+ /**
+ * Gets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+ * enabled. Calling this method is equivalent to getting
+ * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+ *
+ * @return retval operation completion status.
+ * @return enabled whether HAC mode is enabled.
+ */
+ getHacEnabled() generates (Result retval, bool enabled);
+
+ /**
+ * Sets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+ * enabled. Calling this method is equivalent to setting
+ * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+ * Optional method
+ *
+ * @param enabled whether HAC mode is enabled.
+ * @return retval operation completion status.
+ */
+ setHacEnabled(bool enabled) generates (Result retval);
+
+ enum Rotation : int32_t {
+ DEG_0,
+ DEG_90,
+ DEG_180,
+ DEG_270
+ };
+
+ /**
+ * Updates HAL on the current rotation of the device relative to natural
+ * orientation. Calling this method is equivalent to setting legacy
+ * parameter "rotation".
+ *
+ * @param rotation rotation in degrees relative to natural device
+ * orientation.
+ * @return retval operation completion status.
+ */
+ updateRotation(Rotation rotation) generates (Result retval);
+};
diff --git a/audio/7.0/IStream.hal b/audio/7.0/IStream.hal
new file mode 100644
index 0000000..4fe8218
--- /dev/null
+++ b/audio/7.0/IStream.hal
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import android.hardware.audio.effect@7.0::IEffect;
+
+interface IStream {
+ /**
+ * Return the frame size (number of bytes per sample).
+ *
+ * @return frameSize frame size in bytes.
+ */
+ getFrameSize() generates (uint64_t frameSize);
+
+ /**
+ * Return the frame count of the buffer. Calling this method is equivalent
+ * to getting AUDIO_PARAMETER_STREAM_FRAME_COUNT on the legacy HAL.
+ *
+ * @return count frame count.
+ */
+ getFrameCount() generates (uint64_t count);
+
+ /**
+ * Return the size of input/output buffer in bytes for this stream.
+ * It must be a multiple of the frame size.
+ *
+ * @return buffer buffer size in bytes.
+ */
+ getBufferSize() generates (uint64_t bufferSize);
+
+ /**
+ * Return supported audio profiles for this particular stream. This method
+ * is normally called for streams opened on devices that use dynamic
+ * profiles, e.g. HDMI and USB interfaces. Please note that supported
+ * profiles of the stream may differ from the capabilities of the connected
+ * physical device.
+ *
+ * For devices with fixed configurations, e.g. built-in audio devices, all
+ * the profiles are specified in the audio_policy_configuration.xml
+ * file. For such devices, this method must return the configuration from
+ * the config file, or NOT_SUPPORTED retval.
+ *
+ * @return retval operation completion status.
+ * @return formats supported audio profiles.
+ * Must be non empty if retval is OK.
+ */
+ getSupportedProfiles()
+ generates (Result retval, vec<AudioProfile> profiles);
+
+ /**
+ * Retrieves basic stream configuration: sample rate, audio format,
+ * channel mask.
+ *
+ * @return config basic stream configuration.
+ */
+ getAudioProperties() generates (AudioConfigBase config);
+
+ /**
+ * Sets stream parameters. Only sets parameters that are specified.
+ * See the description of AudioConfigBase for the details.
+ *
+ * Optional method. If implemented, only called on a stopped stream.
+ *
+ * @param config basic stream configuration.
+ * @return retval operation completion status.
+ */
+ setAudioProperties(AudioConfigBase config) generates (Result retval);
+
+ /**
+ * Applies audio effect to the stream.
+ *
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect to apply.
+ * @return retval operation completion status.
+ */
+ addEffect(uint64_t effectId) generates (Result retval);
+
+ /**
+ * Stops application of the effect to the stream.
+ *
+ * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+ * the effect to remove.
+ * @return retval operation completion status.
+ */
+ removeEffect(uint64_t effectId) generates (Result retval);
+
+ /**
+ * Put the audio hardware input/output into standby mode.
+ * Driver must exit from standby mode at the next I/O operation.
+ *
+ * @return retval operation completion status.
+ */
+ standby() generates (Result retval);
+
+ /**
+ * Return the set of devices which this stream is connected to.
+ * Optional method
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ * @return device set of devices which this stream is connected to.
+ */
+ getDevices() generates (Result retval, vec<DeviceAddress> devices);
+
+ /**
+ * Connects the stream to one or multiple devices.
+ *
+ * This method must only be used for HALs that do not support
+ * 'IDevice.createAudioPatch' method. Calling this method is
+ * equivalent to setting AUDIO_PARAMETER_STREAM_ROUTING preceded
+ * with a device address in the legacy HAL interface.
+ *
+ * @param address device to connect the stream to.
+ * @return retval operation completion status.
+ */
+ setDevices(vec<DeviceAddress> devices) generates (Result retval);
+
+ /**
+ * Sets the HW synchronization source. Calling this method is equivalent to
+ * setting AUDIO_PARAMETER_STREAM_HW_AV_SYNC on the legacy HAL.
+ * Optional method
+ *
+ * @param hwAvSync HW synchronization source
+ * @return retval operation completion status.
+ */
+ setHwAvSync(AudioHwSync hwAvSync) generates (Result retval);
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be retrieved at the same time.
+ * The implementation should return as many requested parameters
+ * as possible, even if one or more is not supported
+ *
+ * @param context provides more information about the request
+ * @param keys keys of the requested parameters
+ * @return retval operation completion status.
+ * OK must be returned if keys is empty.
+ * NOT_SUPPORTED must be returned if at least one key is unknown.
+ * @return parameters parameter key value pairs.
+ * Must contain the value of all requested keys if retval == OK
+ */
+ getParameters(vec<ParameterValue> context, vec<string> keys)
+ generates (Result retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * Multiple parameters can be set at the same time though this is
+ * discouraged as it make failure analysis harder.
+ *
+ * If possible, a failed setParameters should not impact the platform state.
+ *
+ * @param context provides more information about the request
+ * @param parameters parameter key value pairs.
+ * @return retval operation completion status.
+ * All parameters must be successfully set for OK to be returned
+ */
+ setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+ generates (Result retval);
+
+ /**
+ * Called by the framework to start a stream operating in mmap mode.
+ * createMmapBuffer() must be called before calling start().
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ */
+ start() generates (Result retval);
+
+ /**
+ * Called by the framework to stop a stream operating in mmap mode.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ */
+ stop() generates (Result retval) ;
+
+ /**
+ * Called by the framework to retrieve information on the mmap buffer used for audio
+ * samples transfer.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @param minSizeFrames minimum buffer size requested. The actual buffer
+ * size returned in struct MmapBufferInfo can be larger.
+ * The size must be a positive value.
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * NOT_INITIALIZED in case of memory allocation error
+ * INVALID_ARGUMENTS if the requested buffer size is invalid
+ * INVALID_STATE if called out of sequence
+ * @return info a MmapBufferInfo struct containing information on the MMMAP buffer created.
+ */
+ createMmapBuffer(int32_t minSizeFrames)
+ generates (Result retval, MmapBufferInfo info);
+
+ /**
+ * Called by the framework to read current read/write position in the mmap buffer
+ * with associated time stamp.
+ * Function only implemented by streams operating in mmap mode.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED on non mmap mode streams
+ * INVALID_STATE if called out of sequence
+ * @return position a MmapPosition struct containing current HW read/write position in frames
+ * with associated time stamp.
+ */
+ getMmapPosition()
+ generates (Result retval, MmapPosition position);
+
+ /**
+ * Called by the framework to deinitialize the stream and free up
+ * all currently allocated resources. It is recommended to close
+ * the stream on the client side as soon as it is becomes unused.
+ *
+ * The client must ensure that this function is not called while
+ * audio data is being transferred through the stream's message queues.
+ *
+ * @return retval OK in case the success.
+ * NOT_SUPPORTED if called on IStream instead of input or
+ * output stream interface.
+ * INVALID_STATE if the stream was already closed.
+ */
+ close() generates (Result retval);
+};
diff --git a/audio/7.0/IStreamIn.hal b/audio/7.0/IStreamIn.hal
new file mode 100644
index 0000000..0a3f24b
--- /dev/null
+++ b/audio/7.0/IStreamIn.hal
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import IStream;
+
+interface IStreamIn extends IStream {
+ /**
+ * Returns the source descriptor of the input stream. Calling this method is
+ * equivalent to getting AUDIO_PARAMETER_STREAM_INPUT_SOURCE on the legacy
+ * HAL.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return source audio source.
+ */
+ getAudioSource() generates (Result retval, AudioSource source);
+
+ /**
+ * Set the input gain for the audio driver.
+ * Optional method
+ *
+ * @param gain 1.0f is unity, 0.0f is zero.
+ * @result retval operation completion status.
+ */
+ setGain(float gain) generates (Result retval);
+
+ /**
+ * Commands that can be executed on the driver reader thread.
+ */
+ enum ReadCommand : int32_t {
+ READ,
+ GET_CAPTURE_POSITION
+ };
+
+ /**
+ * Data structure passed to the driver for executing commands
+ * on the driver reader thread.
+ */
+ struct ReadParameters {
+ ReadCommand command; // discriminator
+ union Params {
+ uint64_t read; // READ command, amount of bytes to read, >= 0.
+ // No parameters for GET_CAPTURE_POSITION.
+ } params;
+ };
+
+ /**
+ * Data structure passed back to the client via status message queue
+ * of 'read' operation.
+ *
+ * Possible values of 'retval' field:
+ * - OK, read operation was successful;
+ * - INVALID_ARGUMENTS, stream was not configured properly;
+ * - INVALID_STATE, stream is in a state that doesn't allow reads.
+ */
+ struct ReadStatus {
+ Result retval;
+ ReadCommand replyTo; // discriminator
+ union Reply {
+ uint64_t read; // READ command, amount of bytes read, >= 0.
+ struct CapturePosition { // same as generated by getCapturePosition.
+ uint64_t frames;
+ uint64_t time;
+ } capturePosition;
+ } reply;
+ };
+
+ /**
+ * Called when the metadata of the stream's sink has been changed.
+ * @param sinkMetadata Description of the audio that is suggested by the clients.
+ */
+ updateSinkMetadata(SinkMetadata sinkMetadata);
+
+ /**
+ * Set up required transports for receiving audio buffers from the driver.
+ *
+ * The transport consists of three message queues:
+ * -- command queue is used to instruct the reader thread what operation
+ * to perform;
+ * -- data queue is used for passing audio data from the driver
+ * to the client;
+ * -- status queue is used for reporting operation status
+ * (e.g. amount of bytes actually read or error code).
+ *
+ * The driver operates on a dedicated thread. The client must ensure that
+ * the thread is given an appropriate priority and assigned to correct
+ * scheduler and cgroup. For this purpose, the method returns the identifier
+ * of the driver thread.
+ *
+ * @param frameSize the size of a single frame, in bytes.
+ * @param framesCount the number of frames in a buffer.
+ * @param threadPriority priority of the driver thread.
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queues.
+ * @return commandMQ a message queue used for passing commands.
+ * @return dataMQ a message queue used for passing audio data in the format
+ * specified at the stream opening.
+ * @return statusMQ a message queue used for passing status from the driver
+ * using ReadStatus structures.
+ * @return threadId identifier of the driver's dedicated thread; the caller
+ * may adjust the thread priority to match the priority
+ * of the thread that provides audio data.
+ */
+ prepareForReading(uint32_t frameSize, uint32_t framesCount)
+ generates (
+ Result retval,
+ fmq_sync<ReadParameters> commandMQ,
+ fmq_sync<uint8_t> dataMQ,
+ fmq_sync<ReadStatus> statusMQ,
+ int32_t threadId);
+
+ /**
+ * Return the amount of input frames lost in the audio driver since the last
+ * call of this function.
+ *
+ * Audio driver is expected to reset the value to 0 and restart counting
+ * upon returning the current value by this function call. Such loss
+ * typically occurs when the user space process is blocked longer than the
+ * capacity of audio driver buffers.
+ *
+ * @return framesLost the number of input audio frames lost.
+ */
+ getInputFramesLost() generates (uint32_t framesLost);
+
+ /**
+ * Return a recent count of the number of audio frames received and the
+ * clock time associated with that frame count.
+ *
+ * @return retval INVALID_STATE if the device is not ready/available,
+ * NOT_SUPPORTED if the command is not supported,
+ * OK otherwise.
+ * @return frames the total frame count received. This must be as early in
+ * the capture pipeline as possible. In general, frames
+ * must be non-negative and must not go "backwards".
+ * @return time is the clock monotonic time when frames was measured. In
+ * general, time must be a positive quantity and must not
+ * go "backwards".
+ */
+ getCapturePosition()
+ generates (Result retval, uint64_t frames, uint64_t time);
+
+ /**
+ * Returns an array with active microphones in the stream.
+ *
+ * @return retval INVALID_STATE if the call is not successful,
+ * OK otherwise.
+ *
+ * @return microphones array with microphones info
+ */
+ getActiveMicrophones()
+ generates(Result retval, vec<MicrophoneInfo> microphones);
+
+ /**
+ * Specifies the logical microphone (for processing).
+ *
+ * If the feature is not supported an error should be returned
+ * If multiple microphones are present, this should be treated as a preference
+ * for their combined direction.
+ *
+ * Optional method
+ *
+ * @param Direction constant
+ * @return retval OK if the call is successful, an error code otherwise.
+ */
+ setMicrophoneDirection(MicrophoneDirection direction)
+ generates(Result retval);
+
+ /**
+ * Specifies the zoom factor for the selected microphone (for processing).
+ *
+ * If the feature is not supported an error should be returned
+ * If multiple microphones are present, this should be treated as a preference
+ * for their combined field dimension.
+ *
+ * Optional method
+ *
+ * @param the desired field dimension of microphone capture. Range is from -1 (wide angle),
+ * though 0 (no zoom) to 1 (maximum zoom).
+ *
+ * @return retval OK if the call is not successful, an error code otherwise.
+ */
+ setMicrophoneFieldDimension(float zoom) generates(Result retval);
+};
diff --git a/audio/7.0/IStreamOut.hal b/audio/7.0/IStreamOut.hal
new file mode 100644
index 0000000..38d750f
--- /dev/null
+++ b/audio/7.0/IStreamOut.hal
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+import IStream;
+import IStreamOutCallback;
+import IStreamOutEventCallback;
+
+interface IStreamOut extends IStream {
+ /**
+ * Return the audio hardware driver estimated latency in milliseconds.
+ *
+ * @return latencyMs latency in milliseconds.
+ */
+ getLatency() generates (uint32_t latencyMs);
+
+ /**
+ * This method is used in situations where audio mixing is done in the
+ * hardware. This method serves as a direct interface with hardware,
+ * allowing to directly set the volume as apposed to via the framework.
+ * This method might produce multiple PCM outputs or hardware accelerated
+ * codecs, such as MP3 or AAC.
+ * Optional method
+ *
+ * @param left left channel attenuation, 1.0f is unity, 0.0f is zero.
+ * @param right right channel attenuation, 1.0f is unity, 0.0f is zero.
+ * @return retval operation completion status.
+ * If a volume is outside [0,1], return INVALID_ARGUMENTS
+ */
+ setVolume(float left, float right) generates (Result retval);
+
+ /**
+ * Commands that can be executed on the driver writer thread.
+ */
+ enum WriteCommand : int32_t {
+ WRITE,
+ GET_PRESENTATION_POSITION,
+ GET_LATENCY
+ };
+
+ /**
+ * Data structure passed back to the client via status message queue
+ * of 'write' operation.
+ *
+ * Possible values of 'retval' field:
+ * - OK, write operation was successful;
+ * - INVALID_ARGUMENTS, stream was not configured properly;
+ * - INVALID_STATE, stream is in a state that doesn't allow writes;
+ * - INVALID_OPERATION, retrieving presentation position isn't supported.
+ */
+ struct WriteStatus {
+ Result retval;
+ WriteCommand replyTo; // discriminator
+ union Reply {
+ uint64_t written; // WRITE command, amount of bytes written, >= 0.
+ struct PresentationPosition { // same as generated by
+ uint64_t frames; // getPresentationPosition.
+ TimeSpec timeStamp;
+ } presentationPosition;
+ uint32_t latencyMs; // Same as generated by getLatency.
+ } reply;
+ };
+
+ /**
+ * Called when the metadata of the stream's source has been changed.
+ * @param sourceMetadata Description of the audio that is played by the clients.
+ */
+ updateSourceMetadata(SourceMetadata sourceMetadata);
+
+ /**
+ * Set up required transports for passing audio buffers to the driver.
+ *
+ * The transport consists of three message queues:
+ * -- command queue is used to instruct the writer thread what operation
+ * to perform;
+ * -- data queue is used for passing audio data from the client
+ * to the driver;
+ * -- status queue is used for reporting operation status
+ * (e.g. amount of bytes actually written or error code).
+ *
+ * The driver operates on a dedicated thread. The client must ensure that
+ * the thread is given an appropriate priority and assigned to correct
+ * scheduler and cgroup. For this purpose, the method returns the identifier
+ * of the driver thread.
+ *
+ * @param frameSize the size of a single frame, in bytes.
+ * @param framesCount the number of frames in a buffer.
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queues.
+ * @return commandMQ a message queue used for passing commands.
+ * @return dataMQ a message queue used for passing audio data in the format
+ * specified at the stream opening.
+ * @return statusMQ a message queue used for passing status from the driver
+ * using WriteStatus structures.
+ * @return threadId identifier of the driver's dedicated thread; the caller
+ * may adjust the thread priority to match the priority
+ * of the thread that provides audio data.
+ */
+ prepareForWriting(uint32_t frameSize, uint32_t framesCount)
+ generates (
+ Result retval,
+ fmq_sync<WriteCommand> commandMQ,
+ fmq_sync<uint8_t> dataMQ,
+ fmq_sync<WriteStatus> statusMQ,
+ int32_t threadId);
+
+ /**
+ * Return the number of audio frames written by the audio DSP to DAC since
+ * the output has exited standby.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return dspFrames number of audio frames written.
+ */
+ getRenderPosition() generates (Result retval, uint32_t dspFrames);
+
+ /**
+ * Get the local time at which the next write to the audio driver will be
+ * presented. The units are microseconds, where the epoch is decided by the
+ * local audio HAL.
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return timestampUs time of the next write.
+ */
+ getNextWriteTimestamp() generates (Result retval, int64_t timestampUs);
+
+ /**
+ * Set the callback interface for notifying completion of non-blocking
+ * write and drain.
+ *
+ * Calling this function implies that all future 'write' and 'drain'
+ * must be non-blocking and use the callback to signal completion.
+ *
+ * 'clearCallback' method needs to be called in order to release the local
+ * callback proxy on the server side and thus dereference the callback
+ * implementation on the client side.
+ *
+ * @return retval operation completion status.
+ */
+ setCallback(IStreamOutCallback callback) generates (Result retval);
+
+ /**
+ * Clears the callback previously set via 'setCallback' method.
+ *
+ * Warning: failure to call this method results in callback implementation
+ * on the client side being held until the HAL server termination.
+ *
+ * If no callback was previously set, the method should be a no-op
+ * and return OK.
+ *
+ * @return retval operation completion status: OK or NOT_SUPPORTED.
+ */
+ clearCallback() generates (Result retval);
+
+ /**
+ * Set the callback interface for notifying about an output stream event.
+ *
+ * Calling this method with a null pointer will result in releasing
+ * the local callback proxy on the server side and thus dereference
+ * the callback implementation on the client side.
+ *
+ * @return retval operation completion status.
+ */
+ setEventCallback(IStreamOutEventCallback callback)
+ generates (Result retval);
+
+ /**
+ * Returns whether HAL supports pausing and resuming of streams.
+ *
+ * @return supportsPause true if pausing is supported.
+ * @return supportsResume true if resume is supported.
+ */
+ supportsPauseAndResume()
+ generates (bool supportsPause, bool supportsResume);
+
+ /**
+ * Notifies to the audio driver to stop playback however the queued buffers
+ * are retained by the hardware. Useful for implementing pause/resume. Empty
+ * implementation if not supported however must be implemented for hardware
+ * with non-trivial latency. In the pause state, some audio hardware may
+ * still be using power. Client code may consider calling 'suspend' after a
+ * timeout to prevent that excess power usage.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ pause() generates (Result retval);
+
+ /**
+ * Notifies to the audio driver to resume playback following a pause.
+ * Returns error INVALID_STATE if called without matching pause.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ resume() generates (Result retval);
+
+ /**
+ * Returns whether HAL supports draining of streams.
+ *
+ * @return supports true if draining is supported.
+ */
+ supportsDrain() generates (bool supports);
+
+ /**
+ * Requests notification when data buffered by the driver/hardware has been
+ * played. If 'setCallback' has previously been called to enable
+ * non-blocking mode, then 'drain' must not block, instead it must return
+ * quickly and completion of the drain is notified through the callback. If
+ * 'setCallback' has not been called, then 'drain' must block until
+ * completion.
+ *
+ * If 'type' is 'ALL', the drain completes when all previously written data
+ * has been played.
+ *
+ * If 'type' is 'EARLY_NOTIFY', the drain completes shortly before all data
+ * for the current track has played to allow time for the framework to
+ * perform a gapless track switch.
+ *
+ * Drain must return immediately on 'stop' and 'flush' calls.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @param type type of drain.
+ * @return retval operation completion status.
+ */
+ drain(AudioDrain type) generates (Result retval);
+
+ /**
+ * Notifies to the audio driver to flush the queued data. Stream must
+ * already be paused before calling 'flush'.
+ * Optional method
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ *
+ * @return retval operation completion status.
+ */
+ flush() generates (Result retval);
+
+ /**
+ * Return a recent count of the number of audio frames presented to an
+ * external observer. This excludes frames which have been written but are
+ * still in the pipeline. The count is not reset to zero when output enters
+ * standby. Also returns the value of CLOCK_MONOTONIC as of this
+ * presentation count. The returned count is expected to be 'recent', but
+ * does not need to be the most recent possible value. However, the
+ * associated time must correspond to whatever count is returned.
+ *
+ * Example: assume that N+M frames have been presented, where M is a 'small'
+ * number. Then it is permissible to return N instead of N+M, and the
+ * timestamp must correspond to N rather than N+M. The terms 'recent' and
+ * 'small' are not defined. They reflect the quality of the implementation.
+ *
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return frames count of presented audio frames.
+ * @return timeStamp associated clock time.
+ */
+ getPresentationPosition()
+ generates (Result retval, uint64_t frames, TimeSpec timeStamp);
+
+ /**
+ * Selects a presentation for decoding from a next generation media stream
+ * (as defined per ETSI TS 103 190-2) and a program within the presentation.
+ * Optional method
+ *
+ * @param presentationId selected audio presentation.
+ * @param programId refinement for the presentation.
+ * @return retval operation completion status.
+ */
+ selectPresentation(int32_t presentationId, int32_t programId)
+ generates (Result retval);
+
+ /**
+ * Returns the Dual Mono mode presentation setting.
+ *
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return mode current setting of Dual Mono mode.
+ */
+ getDualMonoMode() generates (Result retval, DualMonoMode mode);
+
+ /**
+ * Sets the Dual Mono mode presentation on the output device.
+ *
+ * The Dual Mono mode is generally applied to stereo audio streams
+ * where the left and right channels come from separate sources.
+ *
+ * Optional method
+ *
+ * @param mode selected Dual Mono mode.
+ * @return retval operation completion status.
+ */
+ setDualMonoMode(DualMonoMode mode) generates (Result retval);
+
+ /**
+ * Returns the Audio Description Mix level in dB.
+ *
+ * The level is applied to streams incorporating a secondary Audio
+ * Description stream. It specifies the relative level of mixing for
+ * the Audio Description with a reference to the Main Audio.
+ *
+ * Optional method
+ *
+ * The value of the relative level is in the range from negative infinity
+ * to +48.
+ *
+ * @return retval operation completion status.
+ * @return leveldB the current Audio Description Mix Level in dB.
+ */
+ getAudioDescriptionMixLevel() generates (Result retval, float leveldB);
+
+ /**
+ * Sets the Audio Description Mix level in dB.
+ *
+ * For streams incorporating a secondary Audio Description stream
+ * the relative level of mixing of the Audio Description to the Main Audio
+ * is controlled by this method.
+ *
+ * Optional method
+ *
+ * The value of the relative level must be in the range from negative
+ * infinity to +48.
+ *
+ * @param leveldB Audio Description Mix Level in dB
+ * @return retval operation completion status.
+ */
+ setAudioDescriptionMixLevel(float leveldB) generates (Result retval);
+
+ /**
+ * Retrieves current playback rate parameters.
+ *
+ * Optional method
+ *
+ * @return retval operation completion status.
+ * @return playbackRate current playback parameters
+ */
+ getPlaybackRateParameters()
+ generates (Result retval, PlaybackRate playbackRate);
+
+ /**
+ * Sets the playback rate parameters that control playback behavior.
+ * This is normally used when playing encoded content and decoding
+ * is performed in hardware. Otherwise, the framework can apply
+ * necessary transformations.
+ *
+ * Optional method
+ *
+ * If the HAL supports setting the playback rate, it is recommended
+ * to support speed and pitch values at least in the range
+ * from 0.5f to 2.0f, inclusive (see the definition of PlaybackRate struct).
+ *
+ * @param playbackRate playback parameters
+ * @return retval operation completion status.
+ */
+ setPlaybackRateParameters(PlaybackRate playbackRate)
+ generates (Result retval);
+};
diff --git a/audio/7.0/IStreamOutCallback.hal b/audio/7.0/IStreamOutCallback.hal
new file mode 100644
index 0000000..7b9d47f
--- /dev/null
+++ b/audio/7.0/IStreamOutCallback.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+/**
+ * Asynchronous write callback interface.
+ */
+interface IStreamOutCallback {
+ /**
+ * Non blocking write completed.
+ */
+ oneway onWriteReady();
+
+ /**
+ * Drain completed.
+ */
+ oneway onDrainReady();
+
+ /**
+ * Stream hit an error.
+ */
+ oneway onError();
+};
diff --git a/audio/7.0/IStreamOutEventCallback.hal b/audio/7.0/IStreamOutEventCallback.hal
new file mode 100644
index 0000000..52e65d3
--- /dev/null
+++ b/audio/7.0/IStreamOutEventCallback.hal
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+/**
+ * Asynchronous stream out event callback interface. The interface provides
+ * a way for the HAL to notify platform when there are changes, e.g. codec
+ * format change, from the lower layer.
+ */
+interface IStreamOutEventCallback {
+ /**
+ * Codec format changed.
+ *
+ * onCodecFormatChanged returns an AudioMetadata object in read-only ByteString format.
+ * It represents the most recent codec format decoded by a HW audio decoder.
+ *
+ * Codec format is an optional message from HW audio decoders. It serves to
+ * notify the application about the codec format and audio objects contained
+ * within the compressed audio stream for control, informational,
+ * and display purposes.
+ *
+ * audioMetadata ByteString is convertible to an AudioMetadata object through
+ * both a C++ and a C API present in Metadata.h [1], or through a Java API present
+ * in AudioMetadata.java [2].
+ *
+ * The ByteString format is a stable format used for parcelling (marshalling) across
+ * JNI, AIDL, and HIDL interfaces. The test for R compatibility for native marshalling
+ * is TEST(metadata_tests, compatibility_R) [3]. The test for R compatibility for JNI
+ * marshalling is android.media.cts.AudioMetadataTest#testCompatibilityR [4].
+ *
+ * R (audio HAL 7.0) defined keys are as follows [2]:
+ * "bitrate", int32
+ * "channel-mask", int32
+ * "mime", string
+ * "sample-rate", int32
+ * "bit-width", int32
+ * "has-atmos", int32
+ * "audio-encoding", int32
+ *
+ * Parceling Format:
+ * All values are native endian order. [1]
+ *
+ * using type_size_t = uint32_t;
+ * using index_size_t = uint32_t;
+ * using datum_size_t = uint32_t;
+ *
+ * Permitted type indexes are
+ * TYPE_NONE = 0, // Reserved
+ * TYPE_INT32 = 1,
+ * TYPE_INT64 = 2,
+ * TYPE_FLOAT = 3,
+ * TYPE_DOUBLE = 4,
+ * TYPE_STRING = 5,
+ * TYPE_DATA = 6, // A data table of <String, Datum>
+ *
+ * Datum = {
+ * (type_size_t) Type (the type index from type_as_value<T>.)
+ * (datum_size_t) Size (size of the Payload)
+ * (byte string) Payload<Type>
+ * }
+ *
+ * The data is specified in native endian order.
+ * Since the size of the Payload is always present, unknown types may be skipped.
+ *
+ * Payload<Fixed-size Primitive_Value>
+ * [ sizeof(Primitive_Value) in raw bytes ]
+ *
+ * Example of Payload<Int32> of 123:
+ * Payload<Int32>
+ * [ value of 123 ] = 0x7b 0x00 0x00 0x00 123
+ *
+ * Payload<String>
+ * [ (index_size_t) length, not including zero terminator.]
+ * [ (length) raw bytes ]
+ *
+ * Example of Payload<String> of std::string("hi"):
+ * [ (index_size_t) length ] = 0x02 0x00 0x00 0x00 2 strlen("hi")
+ * [ raw bytes "hi" ] = 0x68 0x69 "hi"
+ *
+ * Payload<Data>
+ * [ (index_size_t) entries ]
+ * [ raw bytes (entry 1) Key (Payload<String>)
+ * Value (Datum)
+ * ... (until #entries) ]
+ *
+ * Example of Payload<Data> of {{"hello", "world"},
+ * {"value", (int32_t)1000}};
+ * [ (index_size_t) #entries ] = 0x02 0x00 0x00 0x00 2 entries
+ * Key (Payload<String>)
+ * [ index_size_t length ] = 0x05 0x00 0x00 0x00 5 strlen("hello")
+ * [ raw bytes "hello" ] = 0x68 0x65 0x6c 0x6c 0x6f "hello"
+ * Value (Datum)
+ * [ (type_size_t) type ] = 0x05 0x00 0x00 0x00 5 (TYPE_STRING)
+ * [ (datum_size_t) size ] = 0x09 0x00 0x00 0x00 sizeof(index_size_t) +
+ * strlen("world")
+ * Payload<String>
+ * [ (index_size_t) length ] = 0x05 0x00 0x00 0x00 5 strlen("world")
+ * [ raw bytes "world" ] = 0x77 0x6f 0x72 0x6c 0x64 "world"
+ * Key (Payload<String>)
+ * [ index_size_t length ] = 0x05 0x00 0x00 0x00 5 strlen("value")
+ * [ raw bytes "value" ] = 0x76 0x61 0x6c 0x75 0x65 "value"
+ * Value (Datum)
+ * [ (type_size_t) type ] = 0x01 0x00 0x00 0x00 1 (TYPE_INT32)
+ * [ (datum_size_t) size ] = 0x04 0x00 0x00 0x00 4 sizeof(int32_t)
+ * Payload<Int32>
+ * [ raw bytes 1000 ] = 0xe8 0x03 0x00 0x00 1000
+ *
+ * The contents of audioMetadata is a Payload<Data>.
+ * An implementation dependent detail is that the Keys are always
+ * stored sorted, so the byte string representation generated is unique.
+ *
+ * Vendor keys are allowed for informational and debugging purposes.
+ * Vendor keys should consist of the vendor company name followed
+ * by a dot; for example, "vendorCompany.someVolume" [2].
+ *
+ * [1] system/media/audio_utils/include/audio_utils/Metadata.h
+ * [2] frameworks/base/media/java/android/media/AudioMetadata.java
+ * [3] system/media/audio_utils/tests/metadata_tests.cpp
+ * [4] cts/tests/tests/media/src/android/media/cts/AudioMetadataTest.java
+ *
+ * @param audioMetadata is a buffer containing decoded format changes
+ * reported by codec. The buffer contains data that can be transformed
+ * to audio metadata, which is a C++ object based map.
+ */
+ oneway onCodecFormatChanged(vec<uint8_t> audioMetadata);
+};
diff --git a/audio/7.0/config/Android.bp b/audio/7.0/config/Android.bp
new file mode 100644
index 0000000..015c424
--- /dev/null
+++ b/audio/7.0/config/Android.bp
@@ -0,0 +1,5 @@
+xsd_config {
+ name: "audio_policy_configuration_V7_0",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "audio.policy.configuration.V7_0",
+}
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
new file mode 100644
index 0000000..ac8dc8a
--- /dev/null
+++ b/audio/7.0/config/api/current.txt
@@ -0,0 +1,561 @@
+// Signature format: 2.0
+package audio.policy.configuration.V7_0 {
+
+ public class AttachedDevices {
+ ctor public AttachedDevices();
+ method public java.util.List<java.lang.String> getItem();
+ }
+
+ public enum AudioChannelMask {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_10;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_11;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_12;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_13;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_14;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_15;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_16;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_17;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_18;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_19;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_20;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_21;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_22;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_23;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_24;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_3;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_4;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_5;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_6;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_7;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_6;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT0POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT4;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_BACK;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_6POINT1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT4;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_HAPTIC_AB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_MONO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_A;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_PENTA;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_BACK;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_SIDE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioChannelMask AUDIO_CHANNEL_OUT_SURROUND;
+ }
+
+ public enum AudioContentType {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+ }
+
+ public enum AudioDevice {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_AUX_DIGITAL;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BACK_MIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BUILTIN_MIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_BUS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_DEFAULT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_IP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LINE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_PROXY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_SPDIF;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_STUB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_TELEPHONY_RX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_TV_TUNER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_USB_ACCESSORY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_USB_DEVICE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_USB_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_VOICE_CALL;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_WIRED_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_NONE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_BUS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_DEFAULT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_EARPIECE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_FM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_IP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_LINE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_PROXY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_SPEAKER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_STUB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_TELEPHONY_TX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_USB_DEVICE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_USB_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ }
+
+ public enum AudioFormat {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADIF;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_ELD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_ERLC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_LC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_LD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_LTP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_MAIN;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_SCALABLE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_SSR;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ADTS_XHE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ELD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_ERLC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_HE_V1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_HE_V2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LATM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LATM_LC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_LTP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_MAIN;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_SCALABLE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_SSR;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC_XHE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AC3;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AC4;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_ALAC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AMR_NB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AMR_WB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_APE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_APTX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_APTX_HD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_APTX_TWSP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_CELT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DEFAULT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DSD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS_HD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCNW;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCWB;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_E_AC3;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_E_AC3_JOC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_FLAC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_HE_AAC_V1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_HE_AAC_V2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_IEC61937;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_LDAC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_LHDC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_LHDC_LL;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_MAT_1_0;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_MAT_2_0;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_MAT_2_1;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_MP2;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_MP3;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_OPUS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_16_BIT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_32_BIT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_8_24_BIT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_8_BIT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_PCM_FLOAT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_QCELP;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_SBC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_VORBIS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_WMA;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_WMA_PRO;
+ }
+
+ public enum AudioInOutFlag {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_FAST;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
+ }
+
+ public class AudioPolicyConfiguration {
+ ctor public AudioPolicyConfiguration();
+ method public audio.policy.configuration.V7_0.GlobalConfiguration getGlobalConfiguration();
+ method public java.util.List<audio.policy.configuration.V7_0.Modules> getModules();
+ method public audio.policy.configuration.V7_0.SurroundSound getSurroundSound();
+ method public audio.policy.configuration.V7_0.Version getVersion();
+ method public java.util.List<audio.policy.configuration.V7_0.Volumes> getVolumes();
+ method public void setGlobalConfiguration(audio.policy.configuration.V7_0.GlobalConfiguration);
+ method public void setSurroundSound(audio.policy.configuration.V7_0.SurroundSound);
+ method public void setVersion(audio.policy.configuration.V7_0.Version);
+ }
+
+ public enum AudioSource {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_CAMCORDER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_DEFAULT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_ECHO_REFERENCE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_FM_TUNER;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_HOTWORD;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_MIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_UNPROCESSED;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_CALL;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_DOWNLINK;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_PERFORMANCE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_RECOGNITION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioSource AUDIO_SOURCE_VOICE_UPLINK;
+ }
+
+ public enum AudioStreamType {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_ACCESSIBILITY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_ALARM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_ASSISTANT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_BLUETOOTH_SCO;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_DTMF;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_ENFORCED_AUDIBLE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_MUSIC;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_NOTIFICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_PATCH;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_REROUTING;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_RING;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_SYSTEM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_TTS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioStreamType AUDIO_STREAM_VOICE_CALL;
+ }
+
+ public enum AudioUsage {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ALARM;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_ASSISTANT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_EMERGENCY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_GAME;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_MEDIA;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_NOTIFICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_SAFETY;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_UNKNOWN;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
+ enum_constant public static final audio.policy.configuration.V7_0.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ }
+
+ public enum DeviceCategory {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+ enum_constant public static final audio.policy.configuration.V7_0.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+ enum_constant public static final audio.policy.configuration.V7_0.DeviceCategory DEVICE_CATEGORY_HEADSET;
+ enum_constant public static final audio.policy.configuration.V7_0.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+ enum_constant public static final audio.policy.configuration.V7_0.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+ }
+
+ public class DevicePorts {
+ ctor public DevicePorts();
+ method public java.util.List<audio.policy.configuration.V7_0.DevicePorts.DevicePort> getDevicePort();
+ }
+
+ public static class DevicePorts.DevicePort {
+ ctor public DevicePorts.DevicePort();
+ method public String getAddress();
+ method public java.util.List<audio.policy.configuration.V7_0.AudioFormat> getEncodedFormats();
+ method public audio.policy.configuration.V7_0.Gains getGains();
+ method public java.util.List<audio.policy.configuration.V7_0.Profile> getProfile();
+ method public audio.policy.configuration.V7_0.Role getRole();
+ method public String getTagName();
+ method public String getType();
+ method public boolean get_default();
+ method public void setAddress(String);
+ method public void setEncodedFormats(java.util.List<audio.policy.configuration.V7_0.AudioFormat>);
+ method public void setGains(audio.policy.configuration.V7_0.Gains);
+ method public void setRole(audio.policy.configuration.V7_0.Role);
+ method public void setTagName(String);
+ method public void setType(String);
+ method public void set_default(boolean);
+ }
+
+ public enum EngineSuffix {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.EngineSuffix _default;
+ enum_constant public static final audio.policy.configuration.V7_0.EngineSuffix configurable;
+ }
+
+ public enum GainMode {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.GainMode AUDIO_GAIN_MODE_CHANNELS;
+ enum_constant public static final audio.policy.configuration.V7_0.GainMode AUDIO_GAIN_MODE_JOINT;
+ enum_constant public static final audio.policy.configuration.V7_0.GainMode AUDIO_GAIN_MODE_RAMP;
+ }
+
+ public class Gains {
+ ctor public Gains();
+ method public java.util.List<audio.policy.configuration.V7_0.Gains.Gain> getGain();
+ }
+
+ public static class Gains.Gain {
+ ctor public Gains.Gain();
+ method public audio.policy.configuration.V7_0.AudioChannelMask getChannel_mask();
+ method public int getDefaultValueMB();
+ method public int getMaxRampMs();
+ method public int getMaxValueMB();
+ method public int getMinRampMs();
+ method public int getMinValueMB();
+ method public audio.policy.configuration.V7_0.GainMode getMode();
+ method public String getName();
+ method public int getStepValueMB();
+ method public boolean getUseForVolume();
+ method public void setChannel_mask(audio.policy.configuration.V7_0.AudioChannelMask);
+ method public void setDefaultValueMB(int);
+ method public void setMaxRampMs(int);
+ method public void setMaxValueMB(int);
+ method public void setMinRampMs(int);
+ method public void setMinValueMB(int);
+ method public void setMode(audio.policy.configuration.V7_0.GainMode);
+ method public void setName(String);
+ method public void setStepValueMB(int);
+ method public void setUseForVolume(boolean);
+ }
+
+ public class GlobalConfiguration {
+ ctor public GlobalConfiguration();
+ method public boolean getCall_screen_mode_supported();
+ method public audio.policy.configuration.V7_0.EngineSuffix getEngine_library();
+ method public boolean getSpeaker_drc_enabled();
+ method public void setCall_screen_mode_supported(boolean);
+ method public void setEngine_library(audio.policy.configuration.V7_0.EngineSuffix);
+ method public void setSpeaker_drc_enabled(boolean);
+ }
+
+ public enum HalVersion {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.HalVersion _2_0;
+ enum_constant public static final audio.policy.configuration.V7_0.HalVersion _3_0;
+ }
+
+ public class MixPorts {
+ ctor public MixPorts();
+ method public java.util.List<audio.policy.configuration.V7_0.MixPorts.MixPort> getMixPort();
+ }
+
+ public static class MixPorts.MixPort {
+ ctor public MixPorts.MixPort();
+ method public java.util.List<audio.policy.configuration.V7_0.AudioInOutFlag> getFlags();
+ method public audio.policy.configuration.V7_0.Gains getGains();
+ method public long getMaxActiveCount();
+ method public long getMaxOpenCount();
+ method public String getName();
+ method public java.util.List<audio.policy.configuration.V7_0.AudioUsage> getPreferredUsage();
+ method public java.util.List<audio.policy.configuration.V7_0.Profile> getProfile();
+ method public audio.policy.configuration.V7_0.Role getRole();
+ method public void setFlags(java.util.List<audio.policy.configuration.V7_0.AudioInOutFlag>);
+ method public void setGains(audio.policy.configuration.V7_0.Gains);
+ method public void setMaxActiveCount(long);
+ method public void setMaxOpenCount(long);
+ method public void setName(String);
+ method public void setPreferredUsage(java.util.List<audio.policy.configuration.V7_0.AudioUsage>);
+ method public void setRole(audio.policy.configuration.V7_0.Role);
+ }
+
+ public enum MixType {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.MixType mix;
+ enum_constant public static final audio.policy.configuration.V7_0.MixType mux;
+ }
+
+ public class Modules {
+ ctor public Modules();
+ method public java.util.List<audio.policy.configuration.V7_0.Modules.Module> getModule();
+ }
+
+ public static class Modules.Module {
+ ctor public Modules.Module();
+ method public audio.policy.configuration.V7_0.AttachedDevices getAttachedDevices();
+ method public String getDefaultOutputDevice();
+ method public audio.policy.configuration.V7_0.DevicePorts getDevicePorts();
+ method public audio.policy.configuration.V7_0.HalVersion getHalVersion();
+ method public audio.policy.configuration.V7_0.MixPorts getMixPorts();
+ method public String getName();
+ method public audio.policy.configuration.V7_0.Routes getRoutes();
+ method public void setAttachedDevices(audio.policy.configuration.V7_0.AttachedDevices);
+ method public void setDefaultOutputDevice(String);
+ method public void setDevicePorts(audio.policy.configuration.V7_0.DevicePorts);
+ method public void setHalVersion(audio.policy.configuration.V7_0.HalVersion);
+ method public void setMixPorts(audio.policy.configuration.V7_0.MixPorts);
+ method public void setName(String);
+ method public void setRoutes(audio.policy.configuration.V7_0.Routes);
+ }
+
+ public class Profile {
+ ctor public Profile();
+ method public java.util.List<audio.policy.configuration.V7_0.AudioChannelMask> getChannelMasks();
+ method public String getFormat();
+ method public String getName();
+ method public java.util.List<java.math.BigInteger> getSamplingRates();
+ method public void setChannelMasks(java.util.List<audio.policy.configuration.V7_0.AudioChannelMask>);
+ method public void setFormat(String);
+ method public void setName(String);
+ method public void setSamplingRates(java.util.List<java.math.BigInteger>);
+ }
+
+ public class Reference {
+ ctor public Reference();
+ method public String getName();
+ method public java.util.List<java.lang.String> getPoint();
+ method public void setName(String);
+ }
+
+ public enum Role {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.Role sink;
+ enum_constant public static final audio.policy.configuration.V7_0.Role source;
+ }
+
+ public class Routes {
+ ctor public Routes();
+ method public java.util.List<audio.policy.configuration.V7_0.Routes.Route> getRoute();
+ }
+
+ public static class Routes.Route {
+ ctor public Routes.Route();
+ method public String getSink();
+ method public String getSources();
+ method public audio.policy.configuration.V7_0.MixType getType();
+ method public void setSink(String);
+ method public void setSources(String);
+ method public void setType(audio.policy.configuration.V7_0.MixType);
+ }
+
+ public class SurroundFormats {
+ ctor public SurroundFormats();
+ method public java.util.List<audio.policy.configuration.V7_0.SurroundFormats.Format> getFormat();
+ }
+
+ public static class SurroundFormats.Format {
+ ctor public SurroundFormats.Format();
+ method public audio.policy.configuration.V7_0.AudioFormat getName();
+ method public java.util.List<audio.policy.configuration.V7_0.AudioFormat> getSubformats();
+ method public void setName(audio.policy.configuration.V7_0.AudioFormat);
+ method public void setSubformats(java.util.List<audio.policy.configuration.V7_0.AudioFormat>);
+ }
+
+ public class SurroundSound {
+ ctor public SurroundSound();
+ method public audio.policy.configuration.V7_0.SurroundFormats getFormats();
+ method public void setFormats(audio.policy.configuration.V7_0.SurroundFormats);
+ }
+
+ public enum Version {
+ method public String getRawName();
+ enum_constant public static final audio.policy.configuration.V7_0.Version _1_0;
+ }
+
+ public class Volume {
+ ctor public Volume();
+ method public audio.policy.configuration.V7_0.DeviceCategory getDeviceCategory();
+ method public java.util.List<java.lang.String> getPoint();
+ method public String getRef();
+ method public audio.policy.configuration.V7_0.AudioStreamType getStream();
+ method public void setDeviceCategory(audio.policy.configuration.V7_0.DeviceCategory);
+ method public void setRef(String);
+ method public void setStream(audio.policy.configuration.V7_0.AudioStreamType);
+ }
+
+ public class Volumes {
+ ctor public Volumes();
+ method public java.util.List<audio.policy.configuration.V7_0.Reference> getReference();
+ method public java.util.List<audio.policy.configuration.V7_0.Volume> getVolume();
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static audio.policy.configuration.V7_0.AudioPolicyConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/tests/bar/1.0/.hidl_for_test b/audio/7.0/config/api/last_current.txt
similarity index 100%
rename from tests/bar/1.0/.hidl_for_test
rename to audio/7.0/config/api/last_current.txt
diff --git a/tests/bar/1.0/.hidl_for_test b/audio/7.0/config/api/last_removed.txt
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to audio/7.0/config/api/last_removed.txt
diff --git a/audio/7.0/config/api/removed.txt b/audio/7.0/config/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/7.0/config/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..20fe020
--- /dev/null
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -0,0 +1,773 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <!-- List the config versions supported by audio policy. -->
+ <xs:simpleType name="version">
+ <xs:restriction base="xs:decimal">
+ <xs:enumeration value="1.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="halVersion">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Version of the interface the hal implements. Note that this
+ relates to legacy HAL API versions since HIDL APIs are versioned
+ using other mechanisms.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:decimal">
+ <!-- List of HAL versions supported by the framework. -->
+ <xs:enumeration value="2.0"/>
+ <xs:enumeration value="3.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="audioPolicyConfiguration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="globalConfiguration" type="globalConfiguration"/>
+ <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+ <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+ <xs:element name="surroundSound" type="surroundSound" minOccurs="0" />
+ </xs:sequence>
+ <xs:attribute name="version" type="version"/>
+ </xs:complexType>
+ <xs:key name="moduleNameKey">
+ <xs:selector xpath="modules/module"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:unique name="volumeTargetUniqueness">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@stream"/>
+ <xs:field xpath="@deviceCategory"/>
+ </xs:unique>
+ <xs:key name="volumeCurveNameKey">
+ <xs:selector xpath="volumes/reference"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@ref"/>
+ </xs:keyref>
+ </xs:element>
+ <xs:complexType name="globalConfiguration">
+ <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+ <xs:attribute name="call_screen_mode_supported" type="xs:boolean" use="optional"/>
+ <xs:attribute name="engine_library" type="engineSuffix" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="modules">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ There should be one section per audio HW module present on the platform.
+ Each <module/> contains two mandatory tags: “halVersion” and “name”.
+ The module "name" is the same as in previous .conf file.
+ Each module must contain the following sections:
+ - <devicePorts/>: a list of device descriptors for all
+ input and output devices accessible via this module.
+ This contains both permanently attached devices and removable devices.
+ - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+ - <routes/>: list of possible connections between input
+ and output devices or between stream and devices.
+ A <route/> is defined by a set of 3 attributes:
+ -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via this route
+ - <attachedDevices/>: permanently attached devices.
+ The attachedDevices section is a list of devices names.
+ Their names correspond to device names defined in "devicePorts" section.
+ - <defaultOutputDevice/> is the device to be used when no policy rule applies
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="module" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+ <xs:unique name="attachedDevicesUniqueness">
+ <xs:selector xpath="item"/>
+ <xs:field xpath="."/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+ <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+ <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+ <xs:element name="routes" type="routes" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="halVersion" type="halVersion" use="required"/>
+ </xs:complexType>
+ <xs:unique name="mixPortNameUniqueness">
+ <xs:selector xpath="mixPorts/mixPort"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ <xs:key name="devicePortNameKey">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@tagName"/>
+ </xs:key>
+ <xs:unique name="devicePortUniqueness">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@type"/>
+ <xs:field xpath="@address"/>
+ </xs:unique>
+ <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="defaultOutputDevice"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="attachedDevices/item"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <!-- The following 3 constraints try to make sure each sink port
+ is reference in one an only one route. -->
+ <xs:key name="routeSinkKey">
+ <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+ <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+ <xs:field xpath="@tagName|@name"/>
+ </xs:key>
+ <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:keyref>
+ <xs:unique name="routeUniqueness">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="attachedDevices">
+ <xs:sequence>
+ <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="audioInOutFlag">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ The flags indicate suggested stream attributes supported by the profile.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_DEEP_BUFFER" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_NON_BLOCKING" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_TTS" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_RAW" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_SYNC" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT_PCM" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_MMAP_NOIRQ" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_SYNC" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_MMAP_NOIRQ" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_VOIP_TX" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_HW_AV_SYNC" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_DIRECT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioInOutFlags">
+ <xs:list itemType="audioInOutFlag" />
+ </xs:simpleType>
+ <xs:simpleType name="role">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="sink"/>
+ <xs:enumeration value="source"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="mixPorts">
+ <xs:sequence>
+ <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="flags" type="audioInOutFlags"/>
+ <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+ <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+ <xs:attribute name="preferredUsage" type="audioUsageList">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ When choosing the mixPort of an audio track, the audioPolicy
+ first considers the mixPorts with a preferredUsage including
+ the track AudioUsage preferred .
+ If non support the track format, the other mixPorts are considered.
+ Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+ the audio of all apps playing with a MEDIA usage.
+ It may receive audio from ALARM if there are no audio compatible
+ <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ <xs:unique name="mixPortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="mixPortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="audioDevice">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+ <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+ <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="vendorExtension">
+ <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from AOSP values.
+ Vendor are encouraged to namespace their module names to avoid conflicts.
+ Example for an hypothetical Google virtual reality device:
+ <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink">
+ -->
+ <xs:restriction base="xs:string">
+ <xs:pattern value="VX_[_a-zA-Z0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="extendableAudioDevice">
+ <xs:union memberTypes="audioDevice vendorExtension"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioFormat">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_FORMAT_DEFAULT" />
+ <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+ <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+ <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+ <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+ <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+ <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_2_0"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_2_1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_XHE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_XHE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_CELT"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE"/>
+ <xs:enumeration value="AUDIO_FORMAT_LHDC"/>
+ <xs:enumeration value="AUDIO_FORMAT_LHDC_LL"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_TWSP"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="extendableAudioFormat">
+ <xs:union memberTypes="audioFormat vendorExtension"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioUsage">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio usage specifies the intended use case for the sound being played.
+ Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+ <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ <xs:enumeration value="AUDIO_USAGE_ALARM" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_GAME" />
+ <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+ <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioUsageList">
+ <xs:list itemType="audioUsage"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioContentType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio content type expresses the general category of the content.
+ Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="samplingRates">
+ <xs:list itemType="xs:nonNegativeInteger" />
+ </xs:simpleType>
+ <xs:simpleType name="audioChannelMask">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio channel mask specifies presence of particular channels.
+ There are two representations:
+ - representation position (traditional discrete channel specification,
+ e.g. "left", "right");
+ - indexed (this is similar to "tracks" in audio mixing, channels
+ are represented using numbers).
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT0POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT0POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD_SIDE"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_SURROUND"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_PENTA"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1_SIDE"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1POINT4"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_6POINT1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_A"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_HAPTIC_AB"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_MONO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_STEREO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_6"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT0POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT0POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1POINT2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_5POINT1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_CALL_MONO"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_1"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_2"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_3"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_4"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_5"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_6"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_7"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_8"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_9"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_10"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_11"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_12"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_13"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_14"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_15"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_16"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_17"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_18"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_19"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_20"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_21"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_22"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_23"/>
+ <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_24"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="channelMasks">
+ <xs:list itemType="audioChannelMask" />
+ </xs:simpleType>
+ <xs:complexType name="profile">
+ <xs:attribute name="name" type="xs:token" use="optional"/>
+ <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
+ <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+ <xs:attribute name="channelMasks" type="channelMasks" use="optional"/>
+ </xs:complexType>
+ <xs:simpleType name="gainMode">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="gains">
+ <xs:sequence>
+ <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="mode" type="gainMode" use="required"/>
+ <xs:attribute name="channel_mask" type="audioChannelMask" use="optional"/>
+ <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+ <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+ <xs:attribute name="useForVolume" type="xs:boolean" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="devicePorts">
+ <xs:sequence>
+ <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="tagName" type="xs:token" use="required"/>
+ <xs:attribute name="type" type="extendableAudioDevice" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+ <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+ <xs:attribute name="default" type="xs:boolean" use="optional">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ The default device will be used if multiple have the same type
+ and no explicit route request exists for a specific device of
+ that type.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="encodedFormats" type="audioFormatsList" use="optional"
+ default="" />
+ </xs:complexType>
+ <xs:unique name="devicePortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="devicePortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="mixType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mix"/>
+ <xs:enumeration value="mux"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="routes">
+ <xs:sequence>
+ <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ List all available sources for a given sink.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="type" type="mixType" use="required"/>
+ <xs:attribute name="sink" type="xs:string" use="required"/>
+ <xs:attribute name="sources" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="volumes">
+ <xs:sequence>
+ <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- TODO: Always require a ref for better xsd validations.
+ Currently a volume could have no points nor ref
+ as it can not be forbidden by xsd 1.0.-->
+ <xs:simpleType name="volumePoint">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Comma separated pair of number.
+ The fist one is the framework level (between 0 and 100).
+ The second one is the volume to send to the HAL.
+ The framework will interpolate volumes not specified.
+ Their MUST be at least 2 points specified.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioStreamType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio stream type describing the intended use case of a stream.
+ Please consult frameworks/base/media/java/android/media/AudioSystem.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+ <xs:enumeration value="AUDIO_STREAM_RING"/>
+ <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+ <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+ <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+ <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+ <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+ <xs:enumeration value="AUDIO_STREAM_TTS"/>
+ <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+ <xs:enumeration value="AUDIO_STREAM_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+ <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioSource">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ An audio source defines the intended use case for the sound being recorded.
+ Please consult frameworks/base/media/java/android/media/MediaRecorder.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
+ <xs:enumeration value="AUDIO_SOURCE_MIC"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_UPLINK"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_DOWNLINK"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_SOURCE_CAMCORDER"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_RECOGNITION"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_SOURCE_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_SOURCE_UNPROCESSED"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+ <xs:enumeration value="AUDIO_SOURCE_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_SOURCE_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_SOURCE_HOTWORD"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of device_category from Volume.h. -->
+ <xs:simpleType name="deviceCategory">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+ <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+ <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="volume">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Volume section defines a volume curve for a given use case and device category.
+ It contains a list of points of this curve expressing the attenuation in Millibels
+ for a given volume index from 0 to 100.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </volume>
+
+ It may also reference a reference/@name to avoid duplicating curves.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+ ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+ <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </reference>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="stream" type="audioStreamType"/>
+ <xs:attribute name="deviceCategory" type="deviceCategory"/>
+ <xs:attribute name="ref" type="xs:token" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="reference">
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="surroundSound">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Surround Sound section provides configuration related to handling of
+ multi-channel formats.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="formats" type="surroundFormats"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="audioFormatsList">
+ <xs:list itemType="audioFormat" />
+ </xs:simpleType>
+ <xs:complexType name="surroundFormats">
+ <xs:sequence>
+ <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="audioFormat" use="required"/>
+ <xs:attribute name="subformats" type="audioFormatsList" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="engineSuffix">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="configurable"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/audio/7.0/config/update_audio_policy_config.sh b/audio/7.0/config/update_audio_policy_config.sh
new file mode 100755
index 0000000..051a0df
--- /dev/null
+++ b/audio/7.0/config/update_audio_policy_config.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script is used to update audio policy configuration files
+# to comply with the updated audio_policy_configuration.xsd from V7.0.
+#
+# The main difference is the separator used in lists for attributes.
+# Since the XML Schema Definition standard only allows space to be
+# used as a separator (see https://www.w3.org/TR/xmlschema11-2/#list-datatypes)
+# the previous versions used a regular expression to validate lists
+# in attribute values. E.g. the channel masks were validated using
+# the following regexp: [_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*
+# This has an obvious drawback of missing typos in the config file.
+#
+# The V7.0 has shifted to defining most of the frequently changed
+# types in the XSD schema only. This allows for verifying all the values
+# in lists, but in order to comply with XML Schema requirements
+# list elements must be separated by space.
+#
+# Since the APM config files typically use include directives,
+# the script must be pointed to the main APM config file and will
+# take care all the included files automatically.
+# If the included file is a shared version from 'frameworks/av',
+# instead of updating it the script checks if there is a newer
+# version with the corresponding name suffix (e.g.
+# 'a2dp_audio_policy_configuration_7_0.xml') and updates the include
+# path instead.
+
+set -euo pipefail
+
+if (echo "$@" | grep -qe -h); then
+ echo "This script will update Audio Policy Manager config file"
+ echo "to the format required by V7.0 XSD schema from a previous"
+ echo "version."
+ echo
+ echo "USAGE: $0 [APM_XML_FILE] [OLD_VERSION]"
+ echo " APM_XML_FILE specifies the path to audio_policy_configuration.xml"
+ echo " relative to Android repository root"
+ echo " OLD_VERSION specifies the version of schema currently used"
+ echo
+ echo "Example: $0 device/generic/goldfish/audio/policy/audio_policy_configuration.xml 6.0"
+ exit
+fi
+readonly HAL_DIRECTORY=hardware/interfaces/audio
+readonly SHARED_CONFIGS_DIRECTORY=frameworks/av/services/audiopolicy/config
+readonly OLD_VERSION=${2:-$(ls ${ANDROID_BUILD_TOP}/${HAL_DIRECTORY} | grep -E '[0-9]+\.[0-9]+' |
+ sort -n | tail -n1)}
+readonly NEW_VERSION=7.0
+readonly NEW_VERSION_UNDERSCORE=7_0
+
+readonly SOURCE_CONFIG=${ANDROID_BUILD_TOP}/$1
+
+# First, validate the input using the schema of the current version
+
+echo Validating the source against the $OLD_VERSION schema
+xmllint --noout --xinclude \
+ --nofixup-base-uris --path "$ANDROID_BUILD_TOP/$SHARED_CONFIGS_DIRECTORY" \
+ --schema ${ANDROID_BUILD_TOP}/${HAL_DIRECTORY}/${OLD_VERSION}/config/audio_policy_configuration.xsd \
+ ${SOURCE_CONFIG}
+if [ $? -ne 0 ]; then
+ echo
+ echo "Config file fails validation for the specified version $OLD_VERSION--unsafe to update"
+ exit 1
+fi
+
+# Find all the source files recursively
+
+SOURCE_FILES=${SOURCE_CONFIG}
+SHARED_FILES=
+findIncludes() {
+ local FILES_TO_CHECK=
+ for F in $1; do
+ local FOUND_INCLUDES=$(grep -Po '<xi:include href="\K[^"]+(?="\/>)' ${F})
+ for I in ${FOUND_INCLUDES}; do
+ SOURCE_FULL_PATH=$(dirname ${F})/${I}
+ SHARED_FULL_PATH=${ANDROID_BUILD_TOP}/${SHARED_CONFIGS_DIRECTORY}/${I}
+ if [ -f "$SOURCE_FULL_PATH" ]; then
+ # Device-specific file.
+ SOURCE_FILES+=$'\n'${SOURCE_FULL_PATH}
+ FILES_TO_CHECK+=$'\n'${SOURCE_FULL_PATH}
+ elif [ -f "$SHARED_FULL_PATH" ]; then
+ # Shared file from the frameworks repo.
+ SHARED_FILES+=$'\n'${I}
+ FILES_TO_CHECK+=$'\n'${SHARED_FULL_PATH}
+ else
+ echo
+ echo "Include file not found: $I"
+ exit 1
+ fi
+ done
+ done
+ if [ "$FILES_TO_CHECK" ]; then
+ findIncludes "$FILES_TO_CHECK"
+ fi
+}
+findIncludes ${SOURCE_FILES}
+
+echo "Will update $1 and included device-specific files in place."
+echo "Will update paths to shared included files."
+echo "Press Ctrl-C to cancel, Enter to continue"
+read
+
+updateFile() {
+ FILE=$1
+ ATTR=$2
+ SEPARATOR=$3
+ SRC_LINES=$(grep -nPo "$ATTR=\"[^\"]+\"" ${FILE} || true)
+ for S in $SRC_LINES; do
+ # Prepare instruction for 'sed' for in-place editing of specified line
+ R=$(echo ${S} | sed -e 's/^[0-9]\+:/\//' | sed -e "s/$SEPARATOR/ /g")
+ S=$(echo ${S} | sed -e 's/:/s\//')${R}/
+ echo ${S} | sed -i -f - ${FILE}
+ done
+}
+for F in $SOURCE_FILES; do
+ updateFile ${F} "channelMasks" ","
+ updateFile ${F} "samplingRates" ","
+ updateFile ${F} "flags" "|"
+done;
+
+updateIncludes() {
+ FILE=$1
+ for I in $SHARED_FILES; do
+ NEW_VERSION_I=${I%.*}_${NEW_VERSION_UNDERSCORE}.${I##*.}
+ if [ -e "$ANDROID_BUILD_TOP/$SHARED_CONFIGS_DIRECTORY/$NEW_VERSION_I" ]; then
+ echo "s/$I/$NEW_VERSION_I/g" | sed -i -f - ${FILE}
+ fi
+ done
+}
+for F in $SOURCE_FILES; do
+ updateIncludes ${F}
+done
+
+# Validate the results against the new schema
+
+echo Validating the result against the $NEW_VERSION schema
+xmllint --noout --xinclude \
+ --nofixup-base-uris --path "$ANDROID_BUILD_TOP/$SHARED_CONFIGS_DIRECTORY" \
+ --schema ${ANDROID_BUILD_TOP}/${HAL_DIRECTORY}/${NEW_VERSION}/config/audio_policy_configuration.xsd \
+ ${SOURCE_CONFIG}
+if [ $? -ne 0 ]; then
+ echo
+ echo "Config file fails validation for the specified version $NEW_VERSION--please check the changes"
+ exit 1
+fi
+echo
+echo "Please check the diff and update path to APM shared files in the device makefile!"
diff --git a/audio/7.0/types.hal b/audio/7.0/types.hal
new file mode 100644
index 0000000..4a9e289
--- /dev/null
+++ b/audio/7.0/types.hal
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.0;
+
+import android.hardware.audio.common@7.0;
+
+enum Result : int32_t {
+ OK,
+ NOT_INITIALIZED,
+ INVALID_ARGUMENTS,
+ INVALID_STATE,
+ /**
+ * Methods marked as "Optional method" must return this result value
+ * if the operation is not supported by HAL.
+ */
+ NOT_SUPPORTED
+};
+
+@export(name="audio_drain_type_t", value_prefix="AUDIO_DRAIN_")
+enum AudioDrain : int32_t {
+ /** drain() returns when all data has been played. */
+ ALL,
+ /**
+ * drain() returns a short time before all data from the current track has
+ * been played to give time for gapless track switch.
+ */
+ EARLY_NOTIFY
+};
+
+/**
+ * A substitute for POSIX timespec.
+ */
+struct TimeSpec {
+ uint64_t tvSec; // seconds
+ uint64_t tvNSec; // nanoseconds
+};
+
+struct ParameterValue {
+ string key;
+ string value;
+};
+
+enum MmapBufferFlag : uint32_t {
+ NONE = 0x0,
+ /**
+ * If the buffer can be securely shared to untrusted applications
+ * through the AAudio exclusive mode.
+ * Only set this flag if applications are restricted from accessing the
+ * memory surrounding the audio data buffer by a kernel mechanism.
+ * See Linux kernel's dma_buf.
+ */
+ APPLICATION_SHAREABLE = 0x1,
+};
+
+/**
+ * Mmap buffer descriptor returned by IStream.createMmapBuffer().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapBufferInfo {
+ /** Mmap memory buffer */
+ memory sharedMemory;
+ /** Total buffer size in frames */
+ uint32_t bufferSizeFrames;
+ /** Transfer size granularity in frames */
+ uint32_t burstSizeFrames;
+ /** Attributes describing the buffer. */
+ bitfield<MmapBufferFlag> flags;
+};
+
+/**
+ * Mmap buffer read/write position returned by IStream.getMmapPosition().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapPosition {
+ int64_t timeNanoseconds; // time stamp in ns, CLOCK_MONOTONIC
+ int32_t positionFrames; // increasing 32 bit frame count reset when IStream.stop() is called
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * message queues used by StreamIn and StreamOut.
+ */
+enum MessageQueueFlagBits : uint32_t {
+ NOT_EMPTY = 1 << 0,
+ NOT_FULL = 1 << 1
+};
+
+/*
+ * Microphone information
+ *
+ */
+
+/**
+ * A 3D point used to represent position or orientation of a microphone.
+ *
+ * Position: Coordinates of the microphone's capsule, in meters, from the
+ * bottom-left-back corner of the bounding box of android device in natural
+ * orientation (PORTRAIT for phones, LANDSCAPE for tablets, tvs, etc).
+ * The orientation musth match the reported by the api Display.getRotation().
+ *
+ * Orientation: Normalized vector to signal the main orientation of the
+ * microphone's capsule. Magnitude = sqrt(x^2 + y^2 + z^2) = 1
+ */
+struct AudioMicrophoneCoordinate {
+ float x;
+ float y;
+ float z;
+};
+
+/**
+ * Enum to identify the type of channel mapping for active microphones.
+ * Used channels further identify if the microphone has any significative
+ * process (e.g. High Pass Filtering, dynamic compression)
+ * Simple processing as constant gain adjustment must be DIRECT.
+ */
+enum AudioMicrophoneChannelMapping : uint32_t {
+ UNUSED = 0, /* Channel not used */
+ DIRECT = 1, /* Channel used and signal not processed */
+ PROCESSED = 2, /* Channel used and signal has some process */
+};
+
+/**
+ * Enum to identify locations of microphones in regards to the body of the
+ * android device.
+ */
+enum AudioMicrophoneLocation : uint32_t {
+ UNKNOWN = 0,
+ MAINBODY = 1,
+ MAINBODY_MOVABLE = 2,
+ PERIPHERAL = 3,
+};
+
+/**
+ * Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
+ */
+typedef int32_t AudioMicrophoneGroup;
+
+/**
+ * Enum with standard polar patterns of microphones
+ */
+enum AudioMicrophoneDirectionality : uint32_t {
+ UNKNOWN = 0,
+ OMNI = 1,
+ BI_DIRECTIONAL = 2,
+ CARDIOID = 3,
+ HYPER_CARDIOID = 4,
+ SUPER_CARDIOID = 5,
+};
+
+/**
+ * A (frequency, level) pair. Used to represent frequency response.
+ */
+struct AudioFrequencyResponsePoint {
+ /** In Hz */
+ float frequency;
+ /** In dB */
+ float level;
+};
+
+/**
+ * Structure used by the HAL to describe microphone's characteristics
+ * Used by StreamIn and Device
+ */
+struct MicrophoneInfo {
+ /** Unique alphanumeric id for microphone. Guaranteed to be the same
+ * even after rebooting.
+ */
+ string deviceId;
+ /**
+ * Device specific information
+ */
+ DeviceAddress deviceAddress;
+ /** Each element of the vector must describe the channel with the same
+ * index.
+ */
+ vec<AudioMicrophoneChannelMapping> channelMapping;
+ /** Location of the microphone in regard to the body of the device */
+ AudioMicrophoneLocation location;
+ /** Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
+ */
+ AudioMicrophoneGroup group;
+ /** Index of this microphone within the group.
+ * (group, index) must be unique within the same device.
+ */
+ uint32_t indexInTheGroup;
+ /** Level in dBFS produced by a 1000 Hz tone at 94 dB SPL */
+ float sensitivity;
+ /** Level in dB of the max SPL supported at 1000 Hz */
+ float maxSpl;
+ /** Level in dB of the min SPL supported at 1000 Hz */
+ float minSpl;
+ /** Standard polar pattern of the microphone */
+ AudioMicrophoneDirectionality directionality;
+ /** Vector with ordered frequency responses (from low to high frequencies)
+ * with the frequency response of the microphone.
+ * Levels are in dB, relative to level at 1000 Hz
+ */
+ vec<AudioFrequencyResponsePoint> frequencyResponse;
+ /** Position of the microphone's capsule in meters, from the
+ * bottom-left-back corner of the bounding box of device.
+ */
+ AudioMicrophoneCoordinate position;
+ /** Normalized point to signal the main orientation of the microphone's
+ * capsule. sqrt(x^2 + y^2 + z^2) = 1
+ */
+ AudioMicrophoneCoordinate orientation;
+};
+
+/**
+ * Constants used by the HAL to determine how to select microphones and process those inputs in
+ * order to optimize for capture in the specified direction.
+ *
+ * MicrophoneDirection Constants are defined in MicrophoneDirection.java.
+ */
+@export(name="audio_microphone_direction_t", value_prefix="MIC_DIRECTION_")
+enum MicrophoneDirection : int32_t {
+ /**
+ * Don't do any directionality processing of the activated microphone(s).
+ */
+ UNSPECIFIED = 0,
+ /**
+ * Optimize capture for audio coming from the screen-side of the device.
+ */
+ FRONT = 1,
+ /**
+ * Optimize capture for audio coming from the side of the device opposite the screen.
+ */
+ BACK = 2,
+ /**
+ * Optimize capture for audio coming from an off-device microphone.
+ */
+ EXTERNAL = 3,
+};
+
+
+/* Dual Mono handling is used when a stereo audio stream
+ * contains separate audio content on the left and right channels.
+ * Such information about the content of the stream may be found, for example,
+ * in ITU T-REC-J.94-201610 A.6.2.3 Component descriptor.
+ */
+@export(name="audio_dual_mono_mode_t", value_prefix="AUDIO_DUAL_MONO_MODE_")
+enum DualMonoMode : int32_t {
+ // Need to be in sync with DUAL_MONO_MODE* constants in
+ // frameworks/base/media/java/android/media/AudioTrack.java
+ /**
+ * Disable any Dual Mono presentation effect.
+ *
+ */
+ OFF = 0,
+ /**
+ * This mode indicates that a stereo stream should be presented
+ * with the left and right audio channels blended together
+ * and delivered to both channels.
+ *
+ * Behavior for non-stereo streams is implementation defined.
+ * A suggested guideline is that the left-right stereo symmetric
+ * channels are pairwise blended, the other channels such as center
+ * are left alone.
+ */
+ LR = 1,
+ /**
+ * This mode indicates that a stereo stream should be presented
+ * with the left audio channel replicated into the right audio channel.
+ *
+ * Behavior for non-stereo streams is implementation defined.
+ * A suggested guideline is that all channels with left-right
+ * stereo symmetry will have the left channel position replicated
+ * into the right channel position. The center channels (with no
+ * left/right symmetry) or unbalanced channels are left alone.
+ */
+ LL = 2,
+ /**
+ * This mode indicates that a stereo stream should be presented
+ * with the right audio channel replicated into the left audio channel.
+ *
+ * Behavior for non-stereo streams is implementation defined.
+ * A suggested guideline is that all channels with left-right
+ * stereo symmetry will have the right channel position replicated
+ * into the left channel position. The center channels (with no
+ * left/right symmetry) or unbalanced channels are left alone.
+ */
+ RR = 3,
+};
+
+/**
+ * Algorithms used for timestretching (preserving pitch while playing audio
+ * content at different speed).
+ */
+@export(name="audio_timestretch_stretch_mode_t", value_prefix="AUDIO_TIMESTRETCH_STRETCH_")
+enum TimestretchMode : int32_t {
+ // Need to be in sync with AUDIO_STRETCH_MODE_* constants in
+ // frameworks/base/media/java/android/media/PlaybackParams.java
+ DEFAULT = 0,
+ /** Selects timestretch algorithm best suitable for voice (speech) content. */
+ VOICE = 1,
+};
+
+/**
+ * Behavior when the values for speed and / or pitch are out
+ * of applicable range.
+ */
+@export(name="audio_timestretch_fallback_mode_t", value_prefix="AUDIO_TIMESTRETCH_FALLBACK_")
+enum TimestretchFallbackMode : int32_t {
+ // Need to be in sync with AUDIO_FALLBACK_MODE_* constants in
+ // frameworks/base/media/java/android/media/PlaybackParams.java
+ /** Play silence for parameter values that are out of range. */
+ MUTE = 1,
+ /** Return an error while trying to set the parameters. */
+ FAIL = 2,
+};
+
+/**
+ * Parameters determining playback behavior. They are used to speed up or
+ * slow down playback and / or change the tonal frequency of the audio content
+ * (pitch).
+ */
+struct PlaybackRate {
+ /**
+ * Speed factor (multiplier). Normal speed has the value of 1.0f.
+ * Values less than 1.0f slow down playback, value greater than 1.0f
+ * speed it up.
+ */
+ float speed;
+ /**
+ * Pitch factor (multiplier). Setting pitch value to 1.0f together
+ * with changing playback speed preserves the pitch, this is often
+ * called "timestretching." Setting the pitch value equal to speed produces
+ * the same effect as playing audio content at different sampling rate.
+ */
+ float pitch;
+ /**
+ * Selects the algorithm used for timestretching (preserving pitch while
+ * playing audio at different speed).
+ */
+ TimestretchMode timestretchMode;
+ /**
+ * Selects the behavior when the specified values for speed and / or pitch
+ * are out of applicable range.
+ */
+ TimestretchFallbackMode fallbackMode;
+};
+
+/**
+ * The audio flags serve two purposes:
+ *
+ * - when a stream is created they indicate its attributes;
+ *
+ * - when present in a profile descriptor listed for a particular audio
+ * hardware module, they indicate that a stream can be opened that
+ * supports the attributes indicated by the flags.
+ *
+ * See 'audioIoFlag' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioInOutFlag;
diff --git a/audio/README b/audio/README
deleted file mode 100644
index afafbe3..0000000
--- a/audio/README
+++ /dev/null
@@ -1,36 +0,0 @@
-Directory structure of the audio HIDL related code.
-
-Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
-based on an existing one.
-
-audio
-|-- 2.0 <== core 2.0 HIDL API. .hal can not be moved into the core directory
-| because that would change its namespace and include path
-|-- 4.0 <== Version 4.0 of the core API
-|
-|-- ...
-|
-|-- common <== code common to audio core and effect API
-| |-- 2.0 <== HIDL API of V2
-| |-- 4.0
-| |-- ...
-| `-- all-versions <== code common to all version of both core and effect API
-| |-- default <== implementation shared code between core and effect impl
-| |-- test <== utilities used by tests
-| `-- util <== utilities used by both implementation and tests
-|
-|-- core <== VTS and default implementation of the core API (not HIDL, see /audio/2.0))
-| `-- all-versions <== Code is version independent through #if and separate files
-| |-- default <== code that wraps the legacy API
-| `-- vts <== vts of core API
-| |-- 2.0 <== 2.0 specific tests and helpers
-| |-- 4.0
-| |-- ...
-|
-`-- effect <== idem for the effect API
- |-- 2.0
- |-- 4.0
- |-- ...
- `-- all-versions
- |-- default
- `-- vts
diff --git a/audio/README.md b/audio/README.md
new file mode 100644
index 0000000..b77b9ba
--- /dev/null
+++ b/audio/README.md
@@ -0,0 +1,53 @@
+# Audio HAL
+
+Directory structure of the audio HAL related code.
+
+Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
+based on an existing one.
+
+## Directory Structure
+
+* `2.0` -- version 2.0 of the core HIDL API. Note that `.hal` files
+ can not be moved into the `core` directory because that would change
+ its namespace and include path.
+ - `config` -- the XSD schema for the Audio Policy Manager
+ configuration file.
+* `4.0` -- version 4.0 of the core HIDL API.
+* ...
+* `common` -- common types for audio core and effect HIDL API.
+ - `2.0` -- version 2.0 of the common types HIDL API.
+ - `4.0` -- version 4.0.
+ - ...
+ - `7.0` -- version 7.0.
+ - `example` -- example implementation of the core and effect
+ V7.0 API. It represents a "fake" audio HAL that doesn't
+ actually communicate with hardware.
+ - `all-versions` -- code common to all version of both core and effect API.
+ - `default` -- shared code of the default implementation.
+ - `service` -- vendor HAL service for hosting the default
+ implementation.
+ - `test` -- utilities used by tests.
+ - `util` -- utilities used by both implementation and tests.
+* `core` -- VTS tests and the default implementation of the core API
+ (not HIDL API, it's in `audio/N.M`).
+ - `7.0` -- code specific to version V7.0 of the core HIDL API
+ - `all-versions` -- the code is common between all versions,
+ version-specific parts are enclosed into conditional directives
+ of preprocessor or reside in dedicated files.
+ - `default` -- code that wraps the legacy API (from
+ `hardware/libhardware`).
+ - `vts` VTS tests for the core HIDL API.
+* `effect` -- same for the effect HIDL API.
+ - `2.0`
+ - `config` -- the XSD schema for the Audio Effects configuration
+ file.
+ - `4.0`
+ - ...
+ - `all-versions`
+ - `default`
+ - `vts`
+* `policy` -- Configurable Audio Policy schemes.
+ - `1.0` -- note that versions of CAP are not linked to the versions
+ of audio HAL.
+ - `vts` -- VTS tests for validating actual configuration files.
+ - `xml` -- XSD schemas for CAP configuration files.
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
index e4676ec..dc4bca4 100644
--- a/audio/common/4.0/Android.bp
+++ b/audio/common/4.0/Android.bp
@@ -5,9 +5,6 @@
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index 761c171..bf265a5 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio.common@5.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/audio/common/6.0/Android.bp b/audio/common/6.0/Android.bp
index 94f1cf8..caeee6f 100644
--- a/audio/common/6.0/Android.bp
+++ b/audio/common/6.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio.common@6.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/audio/common/7.0/Android.bp b/audio/common/7.0/Android.bp
new file mode 100644
index 0000000..1c016b4
--- /dev/null
+++ b/audio/common/7.0/Android.bp
@@ -0,0 +1,30 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio.common@7.0",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ ],
+ interfaces: [
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: true,
+ gen_java_constants: true,
+}
+
+cc_library {
+ name: "android.hardware.audio.common@7.0-enums",
+ vendor_available: true,
+ generated_headers: ["audio_policy_configuration_V7_0"],
+ generated_sources: ["audio_policy_configuration_V7_0"],
+ header_libs: ["libxsdc-utils"],
+ export_generated_headers: ["audio_policy_configuration_V7_0"],
+ export_header_lib_headers: ["libxsdc-utils"],
+ export_include_dirs: ["enums/include"],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libxml2",
+ ],
+}
diff --git a/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h
new file mode 100644
index 0000000..d5fedce
--- /dev/null
+++ b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+#define AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+
+#include <sys/types.h>
+
+#include <audio_policy_configuration_V7_0.h>
+
+namespace audio::policy::configuration::V7_0 {
+
+static inline size_t getChannelCount(AudioChannelMask mask) {
+ switch (mask) {
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_MONO:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_1:
+ return 1;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_A:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_HAPTIC_AB:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_STEREO:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_FRONT_BACK:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_CALL_MONO:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_2:
+ return 2;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3:
+ return 3;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_BACK:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_SIDE:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_SURROUND:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT0POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_4:
+ return 4;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT0POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_PENTA:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT0POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_5:
+ return 5;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_BACK:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_SIDE:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_6:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_IN_5POINT1:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_6:
+ return 6;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_6POINT1:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_7:
+ return 7;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_8:
+ return 8;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_9:
+ return 9;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT4:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_10:
+ return 10;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_11:
+ return 11;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12:
+ return 12;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
+ return 13;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
+ return 14;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15:
+ return 15;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16:
+ return 16;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17:
+ return 17;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_18:
+ return 18;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_19:
+ return 19;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_20:
+ return 20;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_21:
+ return 21;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_22:
+ return 22;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23:
+ return 23;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24:
+ return 24;
+ case AudioChannelMask::UNKNOWN:
+ return 0;
+ // No default to make sure all cases are covered.
+ }
+ // This is to avoid undefined behavior if 'mask' isn't a valid enum value.
+ return 0;
+}
+
+static inline ssize_t getChannelCount(const std::string& mask) {
+ return getChannelCount(stringToAudioChannelMask(mask));
+}
+
+static inline bool isOutputDevice(AudioDevice device) {
+ switch (device) {
+ case AudioDevice::UNKNOWN:
+ case AudioDevice::AUDIO_DEVICE_NONE:
+ return false;
+ case AudioDevice::AUDIO_DEVICE_OUT_EARPIECE:
+ case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER:
+ case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ case AudioDevice::AUDIO_DEVICE_OUT_AUX_DIGITAL:
+ case AudioDevice::AUDIO_DEVICE_OUT_HDMI:
+ case AudioDevice::AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_USB_ACCESSORY:
+ case AudioDevice::AUDIO_DEVICE_OUT_USB_DEVICE:
+ case AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+ case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
+ case AudioDevice::AUDIO_DEVICE_OUT_LINE:
+ case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
+ case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
+ case AudioDevice::AUDIO_DEVICE_OUT_FM:
+ case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
+ case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER_SAFE:
+ case AudioDevice::AUDIO_DEVICE_OUT_IP:
+ case AudioDevice::AUDIO_DEVICE_OUT_BUS:
+ case AudioDevice::AUDIO_DEVICE_OUT_PROXY:
+ case AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_HEARING_AID:
+ case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER:
+ case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT:
+ case AudioDevice::AUDIO_DEVICE_OUT_STUB:
+ return true;
+ case AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION:
+ case AudioDevice::AUDIO_DEVICE_IN_AMBIENT:
+ case AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
+ case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_IN_WIRED_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_IN_AUX_DIGITAL:
+ case AudioDevice::AUDIO_DEVICE_IN_HDMI:
+ case AudioDevice::AUDIO_DEVICE_IN_VOICE_CALL:
+ case AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
+ case AudioDevice::AUDIO_DEVICE_IN_BACK_MIC:
+ case AudioDevice::AUDIO_DEVICE_IN_REMOTE_SUBMIX:
+ case AudioDevice::AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_IN_USB_ACCESSORY:
+ case AudioDevice::AUDIO_DEVICE_IN_USB_DEVICE:
+ case AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
+ case AudioDevice::AUDIO_DEVICE_IN_TV_TUNER:
+ case AudioDevice::AUDIO_DEVICE_IN_LINE:
+ case AudioDevice::AUDIO_DEVICE_IN_SPDIF:
+ case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_A2DP:
+ case AudioDevice::AUDIO_DEVICE_IN_LOOPBACK:
+ case AudioDevice::AUDIO_DEVICE_IN_IP:
+ case AudioDevice::AUDIO_DEVICE_IN_BUS:
+ case AudioDevice::AUDIO_DEVICE_IN_PROXY:
+ case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
+ case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
+ case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
+ case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
+ case AudioDevice::AUDIO_DEVICE_IN_STUB:
+ return false;
+ // No default to make sure all cases are covered.
+ }
+ // This is to avoid undefined behavior if 'device' isn't a valid enum value.
+ return false;
+}
+
+static inline bool isOutputDevice(const std::string& device) {
+ return isOutputDevice(stringToAudioDevice(device));
+}
+
+} // namespace audio::policy::configuration::V7_0
+
+#endif // AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
diff --git a/audio/common/7.0/example/Android.bp b/audio/common/7.0/example/Android.bp
new file mode 100644
index 0000000..03c1cd8
--- /dev/null
+++ b/audio/common/7.0/example/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+ name: "android.hardware.audio@7.0-service.example",
+ vendor: true,
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.audio@7.0-service.example.rc"],
+ vintf_fragments: ["android.hardware.audio@7.0-service.example.xml"],
+ srcs: [
+ "DevicesFactory.cpp",
+ "Effect.cpp",
+ "EffectsFactory.cpp",
+ "EqualizerEffect.cpp",
+ "LoudnessEnhancerEffect.cpp",
+ "service.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libxml2",
+ "libutils",
+ "android.hardware.audio@7.0",
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.effect@7.0",
+ ],
+}
diff --git a/audio/common/7.0/example/DevicesFactory.cpp b/audio/common/7.0/example/DevicesFactory.cpp
new file mode 100644
index 0000000..ddd5fef
--- /dev/null
+++ b/audio/common/7.0/example/DevicesFactory.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DevicesFactory7.0"
+#include <log/log.h>
+
+#include "DevicesFactory.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+namespace android::hardware::audio::V7_0::implementation {
+
+Return<void> DevicesFactory::openDevice(const hidl_string& device, openDevice_cb _hidl_cb) {
+ (void)device;
+ _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+ return Void();
+}
+
+Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
+ _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+ return Void();
+}
+
+} // namespace android::hardware::audio::V7_0::implementation
diff --git a/audio/common/7.0/example/DevicesFactory.h b/audio/common/7.0/example/DevicesFactory.h
new file mode 100644
index 0000000..00f665c
--- /dev/null
+++ b/audio/common/7.0/example/DevicesFactory.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/7.0/IDevicesFactory.h>
+
+namespace android::hardware::audio::V7_0::implementation {
+
+class DevicesFactory : public IDevicesFactory {
+ public:
+ DevicesFactory() = default;
+
+ ::android::hardware::Return<void> openDevice(const ::android::hardware::hidl_string& device,
+ openDevice_cb _hidl_cb) override;
+
+ ::android::hardware::Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
+};
+
+} // namespace android::hardware::audio::V7_0::implementation
diff --git a/audio/common/7.0/example/Effect.cpp b/audio/common/7.0/example/Effect.cpp
new file mode 100644
index 0000000..423754d
--- /dev/null
+++ b/audio/common/7.0/example/Effect.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactory7.0"
+#include <log/log.h>
+
+#include <audio_policy_configuration_V7_0.h>
+
+#include "Effect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::V7_0;
+}
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+Return<Result> Effect::init() {
+ return Result::OK;
+}
+
+Return<Result> Effect::setConfig(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+ (void)config;
+ (void)inputBufferProvider;
+ (void)outputBufferProvider;
+ return Result::OK;
+}
+
+Return<Result> Effect::reset() {
+ return Result::OK;
+}
+
+Return<Result> Effect::enable() {
+ if (!mEnabled) {
+ mEnabled = true;
+ return Result::OK;
+ } else {
+ return Result::NOT_SUPPORTED;
+ }
+}
+
+Return<Result> Effect::disable() {
+ if (mEnabled) {
+ mEnabled = false;
+ return Result::OK;
+ } else {
+ return Result::NOT_SUPPORTED;
+ }
+}
+
+Return<Result> Effect::setDevice(const DeviceAddress& device) {
+ (void)device;
+ return Result::OK;
+}
+
+Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
+ setAndGetVolume_cb _hidl_cb) {
+ (void)volumes;
+ _hidl_cb(Result::OK, hidl_vec<uint32_t>{});
+ return Void();
+}
+
+Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
+ (void)volumes;
+ return Result::OK;
+}
+
+Return<Result> Effect::setAudioMode(AudioMode mode) {
+ (void)mode;
+ return Result::OK;
+}
+
+Return<Result> Effect::setConfigReverse(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+ (void)config;
+ (void)inputBufferProvider;
+ (void)outputBufferProvider;
+ return Result::OK;
+}
+
+Return<Result> Effect::setInputDevice(const DeviceAddress& device) {
+ (void)device;
+ return Result::OK;
+}
+
+Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
+ const EffectConfig config = {{} /* inputCfg */,
+ // outputCfg
+ {{} /* buffer */,
+ 48000 /* samplingRateHz */,
+ toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+ toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT),
+ EffectBufferAccess::ACCESS_ACCUMULATE,
+ 0 /* mask */}};
+ _hidl_cb(Result::OK, config);
+ return Void();
+}
+
+Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+ _hidl_cb(Result::OK, EffectConfig{});
+ return Void();
+}
+
+Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
+ getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+ (void)maxConfigs;
+ _hidl_cb(Result::OK, hidl_vec<EffectAuxChannelsConfig>{});
+ return Void();
+}
+
+Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+ _hidl_cb(Result::OK, EffectAuxChannelsConfig{});
+ return Void();
+}
+
+Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
+ (void)config;
+ return Result::OK;
+}
+
+Return<Result> Effect::setAudioSource(const hidl_string& source) {
+ (void)source;
+ return Result::OK;
+}
+
+Return<Result> Effect::offload(const EffectOffloadParameter& param) {
+ (void)param;
+ return Result::OK;
+}
+
+Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
+ _hidl_cb(Result::OK, mDescriptor);
+ return Void();
+}
+
+Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+ _hidl_cb(Result::OK, MQDescriptor<Result, kSynchronizedReadWrite>{});
+ return Void();
+}
+
+Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
+ const AudioBuffer& outBuffer) {
+ (void)inBuffer;
+ (void)outBuffer;
+ return Result::OK;
+}
+
+Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
+ uint32_t resultMaxSize, command_cb _hidl_cb) {
+ (void)commandId;
+ (void)data;
+ (void)resultMaxSize;
+ _hidl_cb(-EINVAL, hidl_vec<uint8_t>{});
+ return Void();
+}
+
+Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
+ const hidl_vec<uint8_t>& value) {
+ (void)parameter;
+ (void)value;
+ return Result::OK;
+}
+
+Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+ getParameter_cb _hidl_cb) {
+ (void)parameter;
+ (void)valueMaxSize;
+ _hidl_cb(Result::OK, hidl_vec<uint8_t>{});
+ return Void();
+}
+
+Return<void> Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs,
+ uint32_t configSize,
+ getSupportedConfigsForFeature_cb _hidl_cb) {
+ (void)featureId;
+ (void)maxConfigs;
+ (void)configSize;
+ _hidl_cb(Result::OK, 0, hidl_vec<uint8_t>{});
+ return Void();
+}
+
+Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
+ getCurrentConfigForFeature_cb _hidl_cb) {
+ (void)featureId;
+ (void)configSize;
+ _hidl_cb(Result::OK, hidl_vec<uint8_t>{});
+ return Void();
+}
+
+Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
+ const hidl_vec<uint8_t>& configData) {
+ (void)featureId;
+ (void)configData;
+ return Result::OK;
+}
+
+Return<Result> Effect::close() {
+ return Result::OK;
+}
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/Effect.h b/audio/common/7.0/example/Effect.h
new file mode 100644
index 0000000..fa7f41b
--- /dev/null
+++ b/audio/common/7.0/example/Effect.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEffect.h>
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class Effect : public IEffect {
+ public:
+ explicit Effect(const EffectDescriptor& descriptor) : mDescriptor(descriptor) {}
+
+ ::android::hardware::Return<Result> init() override;
+ ::android::hardware::Return<Result> setConfig(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+ ::android::hardware::Return<Result> reset() override;
+ ::android::hardware::Return<Result> enable() override;
+ ::android::hardware::Return<Result> disable() override;
+ ::android::hardware::Return<Result> setDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
+ ::android::hardware::Return<void> setAndGetVolume(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes,
+ setAndGetVolume_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> volumeChangeNotification(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes) override;
+ ::android::hardware::Return<Result> setAudioMode(
+ ::android::hardware::audio::common::V7_0::AudioMode mode) override;
+ ::android::hardware::Return<Result> setConfigReverse(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
+ ::android::hardware::Return<Result> setInputDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
+ ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+ uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getAuxChannelsConfig(
+ getAuxChannelsConfig_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setAuxChannelsConfig(
+ const EffectAuxChannelsConfig& config) override;
+ ::android::hardware::Return<Result> setAudioSource(
+ const ::android::hardware::hidl_string& source) override;
+ ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override;
+ ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
+ ::android::hardware::Return<void> prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+ const AudioBuffer& outBuffer) override;
+ ::android::hardware::Return<void> command(uint32_t commandId,
+ const ::android::hardware::hidl_vec<uint8_t>& data,
+ uint32_t resultMaxSize, command_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter,
+ const ::android::hardware::hidl_vec<uint8_t>& value) override;
+ ::android::hardware::Return<void> getParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+ getParameter_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getSupportedConfigsForFeature(
+ uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+ getSupportedConfigsForFeature_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getCurrentConfigForFeature(
+ uint32_t featureId, uint32_t configSize,
+ getCurrentConfigForFeature_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setCurrentConfigForFeature(
+ uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override;
+ ::android::hardware::Return<Result> close() override;
+
+ private:
+ const EffectDescriptor mDescriptor;
+ bool mEnabled = false;
+};
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EffectsFactory.cpp b/audio/common/7.0/example/EffectsFactory.cpp
new file mode 100644
index 0000000..7d333ae
--- /dev/null
+++ b/audio/common/7.0/example/EffectsFactory.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "EffectsFactory.h"
+#include "EqualizerEffect.h"
+#include "LoudnessEnhancerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) {
+ hidl_vec<EffectDescriptor> descriptors;
+ descriptors.resize(2);
+ descriptors[0] = EqualizerEffect::getDescriptor();
+ descriptors[1] = LoudnessEnhancerEffect::getDescriptor();
+ _hidl_cb(Result::OK, descriptors);
+ return Void();
+}
+
+Return<void> EffectsFactory::getDescriptor(const Uuid& uuid, getDescriptor_cb _hidl_cb) {
+ if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) {
+ _hidl_cb(Result::OK, desc);
+ } else if (auto desc = LoudnessEnhancerEffect::getDescriptor();
+ uuid == desc.type || uuid == desc.uuid) {
+ _hidl_cb(Result::OK, desc);
+ } else {
+ _hidl_cb(Result::INVALID_ARGUMENTS, EffectDescriptor{});
+ }
+ return Void();
+}
+
+Return<void> EffectsFactory::createEffect(const Uuid& uuid, int32_t session, int32_t ioHandle,
+ int32_t device, createEffect_cb _hidl_cb) {
+ (void)session;
+ (void)ioHandle;
+ (void)device;
+ if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) {
+ _hidl_cb(Result::OK, new EqualizerEffect(), 0);
+ } else if (auto desc = LoudnessEnhancerEffect::getDescriptor();
+ uuid == desc.type || uuid == desc.uuid) {
+ _hidl_cb(Result::OK, new LoudnessEnhancerEffect(), 0);
+ } else {
+ _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, 0);
+ }
+ return Void();
+}
+
+Return<void> EffectsFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ (void)fd;
+ (void)options;
+ return Void();
+}
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EffectsFactory.h b/audio/common/7.0/example/EffectsFactory.h
new file mode 100644
index 0000000..8fec70c
--- /dev/null
+++ b/audio/common/7.0/example/EffectsFactory.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEffectsFactory.h>
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class EffectsFactory : public IEffectsFactory {
+ public:
+ EffectsFactory() = default;
+
+ ::android::hardware::Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getDescriptor(
+ const ::android::hardware::audio::common::V7_0::Uuid& uuid,
+ getDescriptor_cb _hidl_cb) override;
+ ::android::hardware::Return<void> createEffect(
+ const ::android::hardware::audio::common::V7_0::Uuid& uuid, int32_t session,
+ int32_t ioHandle, int32_t device, createEffect_cb _hidl_cb) override;
+ ::android::hardware::Return<void>
+ debug(const ::android::hardware::hidl_handle& fd,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& options) override;
+};
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EqualizerEffect.cpp b/audio/common/7.0/example/EqualizerEffect.cpp
new file mode 100644
index 0000000..c93c5a9
--- /dev/null
+++ b/audio/common/7.0/example/EqualizerEffect.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits>
+
+#define LOG_TAG "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "EqualizerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+const EffectDescriptor& EqualizerEffect::getDescriptor() {
+ // Note: for VTS tests only 'type' and 'uuid' fields are required.
+ // The actual implementation must provide meaningful values
+ // for all fields of the descriptor.
+ static const EffectDescriptor descriptor = {
+ .type =
+ {// Same UUID as AudioEffect.EFFECT_TYPE_EQUALIZER in Java.
+ 0x0bed4300, 0xddd6, 0x11db, 0x8f34,
+ std::array<uint8_t, 6>{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}},
+ .uuid = {0, 0, 0, 1, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
+ return descriptor;
+}
+
+EqualizerEffect::EqualizerEffect() : mEffect(new Effect(getDescriptor())) {
+ mProperties.bandLevels.resize(kNumBands);
+}
+
+Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
+ _hidl_cb(Result::OK, kNumBands);
+ return Void();
+}
+
+Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb) {
+ _hidl_cb(Result::OK, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max());
+ return Void();
+}
+
+Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level) {
+ if (band < kNumBands) {
+ mProperties.bandLevels[band] = level;
+ return Result::OK;
+ } else {
+ return Result::INVALID_ARGUMENTS;
+ }
+}
+
+Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb) {
+ if (band < kNumBands) {
+ _hidl_cb(Result::OK, mProperties.bandLevels[band]);
+ } else {
+ _hidl_cb(Result::INVALID_ARGUMENTS, 0);
+ }
+ return Void();
+}
+
+Return<void> EqualizerEffect::getBandCenterFrequency(uint16_t band,
+ getBandCenterFrequency_cb _hidl_cb) {
+ (void)band;
+ _hidl_cb(Result::OK, 0);
+ return Void();
+}
+
+Return<void> EqualizerEffect::getBandFrequencyRange(uint16_t band,
+ getBandFrequencyRange_cb _hidl_cb) {
+ (void)band;
+ _hidl_cb(Result::OK, 0, 1);
+ return Void();
+}
+
+Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) {
+ (void)freq;
+ _hidl_cb(Result::OK, 0);
+ return Void();
+}
+
+Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb) {
+ hidl_vec<hidl_string> presetNames;
+ presetNames.resize(kNumPresets);
+ presetNames[0] = "default";
+ _hidl_cb(Result::OK, presetNames);
+ return Void();
+}
+
+Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset) {
+ if (preset < kNumPresets) {
+ mProperties.curPreset = preset;
+ return Result::OK;
+ } else {
+ return Result::INVALID_ARGUMENTS;
+ }
+}
+
+Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb) {
+ _hidl_cb(Result::OK, mProperties.curPreset);
+ return Void();
+}
+
+Return<Result> EqualizerEffect::setAllProperties(
+ const IEqualizerEffect::AllProperties& properties) {
+ mProperties = properties;
+ return Result::OK;
+}
+
+Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
+ _hidl_cb(Result::OK, mProperties);
+ return Void();
+}
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/EqualizerEffect.h b/audio/common/7.0/example/EqualizerEffect.h
new file mode 100644
index 0000000..11853c3
--- /dev/null
+++ b/audio/common/7.0/example/EqualizerEffect.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/IEqualizerEffect.h>
+
+#include "Effect.h"
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class EqualizerEffect : public IEqualizerEffect {
+ public:
+ static const EffectDescriptor& getDescriptor();
+
+ EqualizerEffect();
+
+ // Methods from IEffect interface.
+ ::android::hardware::Return<Result> init() override { return mEffect->init(); }
+ ::android::hardware::Return<Result> setConfig(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+ return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+ }
+ ::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
+ ::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
+ ::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
+ ::android::hardware::Return<Result> setDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+ return mEffect->setDevice(device);
+ }
+ ::android::hardware::Return<void> setAndGetVolume(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes,
+ setAndGetVolume_cb _hidl_cb) override {
+ return mEffect->setAndGetVolume(volumes, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> volumeChangeNotification(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
+ return mEffect->volumeChangeNotification(volumes);
+ }
+ ::android::hardware::Return<Result> setAudioMode(
+ ::android::hardware::audio::common::V7_0::AudioMode mode) override {
+ return mEffect->setAudioMode(mode);
+ }
+ ::android::hardware::Return<Result> setConfigReverse(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+ return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+ }
+ ::android::hardware::Return<Result> setInputDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+ return mEffect->setInputDevice(device);
+ }
+ ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
+ return mEffect->getConfig(_hidl_cb);
+ }
+ ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
+ return mEffect->getConfigReverse(_hidl_cb);
+ }
+ ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+ uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
+ return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getAuxChannelsConfig(
+ getAuxChannelsConfig_cb _hidl_cb) override {
+ return mEffect->getAuxChannelsConfig(_hidl_cb);
+ }
+ ::android::hardware::Return<Result> setAuxChannelsConfig(
+ const EffectAuxChannelsConfig& config) override {
+ return mEffect->setAuxChannelsConfig(config);
+ }
+ ::android::hardware::Return<Result> setAudioSource(
+ const ::android::hardware::hidl_string& source) override {
+ return mEffect->setAudioSource(source);
+ }
+ ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
+ return mEffect->offload(param);
+ }
+ ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
+ return mEffect->getDescriptor(_hidl_cb);
+ }
+ ::android::hardware::Return<void> prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) override {
+ return mEffect->prepareForProcessing(_hidl_cb);
+ }
+ ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+ const AudioBuffer& outBuffer) override {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
+ }
+ ::android::hardware::Return<void> command(uint32_t commandId,
+ const ::android::hardware::hidl_vec<uint8_t>& data,
+ uint32_t resultMaxSize,
+ command_cb _hidl_cb) override {
+ return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> setParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter,
+ const ::android::hardware::hidl_vec<uint8_t>& value) override {
+ return mEffect->setParameter(parameter, value);
+ }
+ ::android::hardware::Return<void> getParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+ getParameter_cb _hidl_cb) override {
+ return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getSupportedConfigsForFeature(
+ uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+ getSupportedConfigsForFeature_cb _hidl_cb) override {
+ return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getCurrentConfigForFeature(
+ uint32_t featureId, uint32_t configSize,
+ getCurrentConfigForFeature_cb _hidl_cb) override {
+ return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> setCurrentConfigForFeature(
+ uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
+ return mEffect->setCurrentConfigForFeature(featureId, configData);
+ }
+ ::android::hardware::Return<Result> close() override { return mEffect->close(); }
+
+ // Methods from IEqualizerEffect interface.
+ ::android::hardware::Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getLevelRange(getLevelRange_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setBandLevel(uint16_t band, int16_t level) override;
+ ::android::hardware::Return<void> getBandLevel(uint16_t band,
+ getBandLevel_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getBandCenterFrequency(
+ uint16_t band, getBandCenterFrequency_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getBandFrequencyRange(
+ uint16_t band, getBandFrequencyRange_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getBandForFrequency(uint32_t freq,
+ getBandForFrequency_cb _hidl_cb) override;
+ ::android::hardware::Return<void> getPresetNames(getPresetNames_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setCurrentPreset(uint16_t preset) override;
+ ::android::hardware::Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb) override;
+ ::android::hardware::Return<Result> setAllProperties(
+ const IEqualizerEffect::AllProperties& properties) override;
+ ::android::hardware::Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
+
+ private:
+ static constexpr size_t kNumBands = 1;
+ static constexpr size_t kNumPresets = 1;
+ sp<Effect> mEffect;
+ IEqualizerEffect::AllProperties mProperties{};
+};
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.cpp b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp
new file mode 100644
index 0000000..38269b3
--- /dev/null
+++ b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactory7.0"
+#include <log/log.h>
+
+#include "LoudnessEnhancerEffect.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using namespace ::android::hardware::audio::common::V7_0;
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+const EffectDescriptor& LoudnessEnhancerEffect::getDescriptor() {
+ // Note: for VTS tests only 'type' and 'uuid' fields are required.
+ // The actual implementation must provide meaningful values
+ // for all fields of the descriptor.
+ static const EffectDescriptor descriptor = {
+ .type =
+ {// Same UUID as AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER in Java.
+ 0xfe3199be, 0xaed0, 0x413f, 0x87bb,
+ std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}},
+ .uuid = {0, 0, 0, 2, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
+ return descriptor;
+} // namespace android::hardware::audio::effect::V7_0::implementation
+
+LoudnessEnhancerEffect::LoudnessEnhancerEffect() : mEffect(new Effect(getDescriptor())) {}
+
+Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
+ mTargetGainMb = targetGainMb;
+ return Result::OK;
+}
+
+Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb) {
+ _hidl_cb(Result::OK, mTargetGainMb);
+ return Void();
+}
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.h b/audio/common/7.0/example/LoudnessEnhancerEffect.h
new file mode 100644
index 0000000..1af0d9f
--- /dev/null
+++ b/audio/common/7.0/example/LoudnessEnhancerEffect.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/audio/effect/7.0/ILoudnessEnhancerEffect.h>
+
+#include "Effect.h"
+
+namespace android::hardware::audio::effect::V7_0::implementation {
+
+class LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
+ public:
+ static const EffectDescriptor& getDescriptor();
+
+ LoudnessEnhancerEffect();
+
+ // Methods from IEffect interface.
+ ::android::hardware::Return<Result> init() override { return mEffect->init(); }
+ ::android::hardware::Return<Result> setConfig(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+ return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+ }
+ ::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
+ ::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
+ ::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
+ ::android::hardware::Return<Result> setDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+ return mEffect->setDevice(device);
+ }
+ ::android::hardware::Return<void> setAndGetVolume(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes,
+ setAndGetVolume_cb _hidl_cb) override {
+ return mEffect->setAndGetVolume(volumes, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> volumeChangeNotification(
+ const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
+ return mEffect->volumeChangeNotification(volumes);
+ }
+ ::android::hardware::Return<Result> setAudioMode(
+ ::android::hardware::audio::common::V7_0::AudioMode mode) override {
+ return mEffect->setAudioMode(mode);
+ }
+ ::android::hardware::Return<Result> setConfigReverse(
+ const EffectConfig& config,
+ const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
+ const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
+ return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+ }
+ ::android::hardware::Return<Result> setInputDevice(
+ const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
+ return mEffect->setInputDevice(device);
+ }
+ ::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
+ return mEffect->getConfig(_hidl_cb);
+ }
+ ::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
+ return mEffect->getConfigReverse(_hidl_cb);
+ }
+ ::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
+ uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
+ return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getAuxChannelsConfig(
+ getAuxChannelsConfig_cb _hidl_cb) override {
+ return mEffect->getAuxChannelsConfig(_hidl_cb);
+ }
+ ::android::hardware::Return<Result> setAuxChannelsConfig(
+ const EffectAuxChannelsConfig& config) override {
+ return mEffect->setAuxChannelsConfig(config);
+ }
+ ::android::hardware::Return<Result> setAudioSource(
+ const ::android::hardware::hidl_string& source) override {
+ return mEffect->setAudioSource(source);
+ }
+ ::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
+ return mEffect->offload(param);
+ }
+ ::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
+ return mEffect->getDescriptor(_hidl_cb);
+ }
+ ::android::hardware::Return<void> prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) override {
+ return mEffect->prepareForProcessing(_hidl_cb);
+ }
+ ::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
+ const AudioBuffer& outBuffer) override {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
+ }
+ ::android::hardware::Return<void> command(uint32_t commandId,
+ const ::android::hardware::hidl_vec<uint8_t>& data,
+ uint32_t resultMaxSize,
+ command_cb _hidl_cb) override {
+ return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> setParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter,
+ const ::android::hardware::hidl_vec<uint8_t>& value) override {
+ return mEffect->setParameter(parameter, value);
+ }
+ ::android::hardware::Return<void> getParameter(
+ const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
+ getParameter_cb _hidl_cb) override {
+ return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getSupportedConfigsForFeature(
+ uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
+ getSupportedConfigsForFeature_cb _hidl_cb) override {
+ return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+ }
+ ::android::hardware::Return<void> getCurrentConfigForFeature(
+ uint32_t featureId, uint32_t configSize,
+ getCurrentConfigForFeature_cb _hidl_cb) override {
+ return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+ }
+ ::android::hardware::Return<Result> setCurrentConfigForFeature(
+ uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
+ return mEffect->setCurrentConfigForFeature(featureId, configData);
+ }
+ ::android::hardware::Return<Result> close() override { return mEffect->close(); }
+
+ // Methods from ILoudnessEnhancerEffect interface.
+ ::android::hardware::Return<Result> setTargetGain(int32_t targetGainMb) override;
+ ::android::hardware::Return<void> getTargetGain(getTargetGain_cb _hidl_cb) override;
+
+ private:
+ sp<Effect> mEffect;
+ int32_t mTargetGainMb = 0;
+};
+
+} // namespace android::hardware::audio::effect::V7_0::implementation
diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc
new file mode 100644
index 0000000..cf8b51f
--- /dev/null
+++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc
@@ -0,0 +1,7 @@
+service vendor.audio-hal-7-0 /vendor/bin/hw/android.hardware.audio@7.0-service.example
+ class hal
+ user audioserver
+ group audio
+ capabilities BLOCK_SUSPEND
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml
new file mode 100644
index 0000000..b91b061
--- /dev/null
+++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.audio</name>
+ <transport>hwbinder</transport>
+ <version>7.0</version>
+ <interface>
+ <name>IDevicesFactory</name>
+ <instance>example</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.audio.effect</name>
+ <transport>hwbinder</transport>
+ <version>7.0</version>
+ <interface>
+ <name>IEffectsFactory</name>
+ <instance>example</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/audio/common/7.0/example/service.cpp b/audio/common/7.0/example/service.cpp
new file mode 100644
index 0000000..641e2c9
--- /dev/null
+++ b/audio/common/7.0/example/service.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.audio@7.0-service.example"
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "DevicesFactory.h"
+#include "EffectsFactory.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using namespace android;
+
+status_t registerDevicesFactoryService() {
+ sp<::android::hardware::audio::V7_0::IDevicesFactory> devicesFactory =
+ new ::android::hardware::audio::V7_0::implementation::DevicesFactory();
+ status_t status = devicesFactory->registerAsService("example");
+ ALOGE_IF(status != OK, "Error registering devices factory as service: %d", status);
+ return status;
+}
+
+status_t registerEffectsFactoryService() {
+ sp<::android::hardware::audio::effect::V7_0::IEffectsFactory> devicesFactory =
+ new ::android::hardware::audio::effect::V7_0::implementation::EffectsFactory();
+ status_t status = devicesFactory->registerAsService("example");
+ ALOGE_IF(status != OK, "Error registering effects factory as service: %d", status);
+ return status;
+}
+
+int main() {
+ configureRpcThreadpool(1, true);
+ status_t status = registerDevicesFactoryService();
+ if (status != OK) {
+ return status;
+ }
+ status = registerEffectsFactoryService();
+ if (status != OK) {
+ return status;
+ }
+ joinRpcThreadpool();
+
+ return 1;
+}
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
new file mode 100644
index 0000000..31c7388
--- /dev/null
+++ b/audio/common/7.0/types.hal
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common@7.0;
+
+import android.hidl.safe_union@1.0;
+
+/**
+ * Handle type for identifying audio resources. Handles are allocated by the framework.
+ */
+typedef int32_t AudioIoHandle;
+
+/**
+ * Each port has a unique ID or handle allocated by policy manager.
+ */
+typedef int32_t AudioPortHandle;
+
+/**
+ * Each patch is identified by a handle allocated by the HAL.
+ */
+typedef int32_t AudioPatchHandle;
+
+/**
+ * A HW synchronization source returned by the audio HAL.
+ */
+typedef uint32_t AudioHwSync;
+
+/**
+ * Commonly used structure for passing unique identifieds (UUID).
+ * For the definition of UUID, refer to ITU-T X.667 spec.
+ */
+struct Uuid {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t versionAndTimeHigh;
+ uint16_t variantAndClockSeqHigh;
+ uint8_t[6] node;
+};
+
+
+/*
+ *
+ * Audio streams
+ *
+ */
+
+/**
+ * Audio stream type describing the intended use case of a stream.
+ * See 'audioStreamType' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioStreamType;
+
+/**
+ * An audio source defines the intended use case for the sound being recorded.
+ * See 'audioSource' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioSource;
+
+/**
+ * An audio session identifier is used to designate the particular
+ * playback or recording session (e.g. playback performed by a certain
+ * application).
+ */
+typedef int32_t AudioSession;
+
+enum AudioSessionConsts : int32_t {
+ /**
+ * Session for effects attached to a particular sink or source audio device
+ * (e.g an effect only applied to a speaker)
+ */
+ DEVICE = -2,
+ /**
+ * Session for effects attached to a particular output stream
+ * (value must be less than 0)
+ */
+ OUTPUT_STAGE = -1,
+ /**
+ * Session for effects applied to output mix. These effects can
+ * be moved by audio policy manager to another output stream
+ * (value must be 0)
+ */
+ OUTPUT_MIX = 0,
+};
+
+/**
+ * Audio format indicates audio codec type.
+ * See 'audioFormat' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioFormat;
+
+/**
+ * Audio channel mask indicates presence of particular channels.
+ * See 'audioChannelMask' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioChannelMask;
+
+/**
+ * Base configuration attributes applicable to any stream of audio.
+ */
+struct AudioConfigBase {
+ AudioFormat format; // 'DEFAULT' means 'unspecified'
+ uint32_t sampleRateHz; // 0 means 'unspecified'
+ vec<AudioChannelMask> channelMask; // empty means 'unspecified'
+};
+
+/**
+ * Configurations supported for a certain audio format.
+ */
+struct AudioProfile {
+ AudioFormat format;
+ /** List of the sample rates (in Hz) supported by the profile. */
+ vec<uint32_t> sampleRates;
+ /**
+ * List of channel masks supported by the profile. Every subvector might be
+ * comprised of several individual channel mask entries for non-traditional
+ * channel masks, e.g. a combination "OUT_FRONT_LEFT,OUT_FRONT_CENTER" which
+ * doesn't have a corresponding predefined channel mask.
+ */
+ vec<vec<AudioChannelMask>> channelMasks;
+};
+
+/**
+ * Major modes for a mobile device. The current mode setting affects audio
+ * routing.
+ */
+@export(name="audio_mode_t", value_prefix="AUDIO_MODE_")
+enum AudioMode : int32_t {
+ NORMAL = 0,
+ RINGTONE = 1,
+ /** Calls handled by the telephony stack (Eg: PSTN). */
+ IN_CALL = 2,
+ /** Calls handled by apps (Eg: Hangout). */
+ IN_COMMUNICATION = 3,
+ /** Call screening in progress. */
+ CALL_SCREEN = 4,
+};
+
+/**
+ * Audio device specifies type (or category) of audio I/O device
+ * (e.g. speaker or headphones).
+ * See 'audioDevice' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioDevice;
+
+/**
+ * Specifies a device address in case when several devices of the same type
+ * can be connected (e.g. BT A2DP, USB).
+ */
+struct DeviceAddress {
+ /** The type of the device. */
+ AudioDevice deviceType;
+ safe_union Address {
+ /**
+ * The address may be left unspecified if 'device' specifies
+ * a physical device unambiguously.
+ */
+ Monostate unspecified;
+ /** IEEE 802 MAC address. Set for Bluetooth devices. */
+ uint8_t[6] mac;
+ /** IPv4 Address. Set for IPv4 devices. */
+ uint8_t[4] ipv4;
+ /** IPv6 Address. Set for IPv6 devices. */
+ uint16_t[8] ipv6;
+ /** PCI bus Address. Set for USB devices. */
+ struct Alsa {
+ int32_t card;
+ int32_t device;
+ } alsa;
+ /** Arbitrary BUS device unique address. Not interpreted by the framework. */
+ string bus;
+ /** Arbitrary REMOTE_SUBMIX device unique address. Not interpreted by the HAL. */
+ string rSubmix;
+ } address;
+};
+
+/**
+ * Audio usage specifies the intended use case for the sound being played.
+ * See 'audioUsage' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioUsage;
+
+/**
+ * Audio content type expresses the general category of the content.
+ * See 'audioContentType' in audio_policy_configuration.xsd for the
+ * list of allowed values.
+ */
+typedef string AudioContentType;
+
+/** Encapsulation mode used for sending audio compressed data. */
+@export(name="audio_encapsulation_mode_t", value_prefix="AUDIO_ENCAPSULATION_MODE_")
+enum AudioEncapsulationMode : int32_t {
+ // Do not change these values without updating their counterparts
+ // in frameworks/base/media/java/android/media/AudioTrack.java
+ /**
+ * No encapsulation mode for metadata.
+ */
+ NONE = 0,
+ /**
+ * Elementary stream payload with metadata
+ */
+ ELEMENTARY_STREAM = 1,
+ /**
+ * Handle-based payload with metadata
+ */
+ HANDLE = 2,
+};
+
+/**
+ * Additional information about the stream passed to hardware decoders.
+ */
+struct AudioOffloadInfo {
+ AudioConfigBase base;
+ AudioStreamType streamType;
+ uint32_t bitRatePerSecond;
+ int64_t durationMicroseconds; // -1 if unknown
+ bool hasVideo;
+ bool isStreaming;
+ uint32_t bitWidth;
+ uint32_t bufferSize;
+ AudioUsage usage;
+ AudioEncapsulationMode encapsulationMode;
+ int32_t contentId;
+ int32_t syncId;
+};
+
+/**
+ * Commonly used audio stream configuration parameters.
+ */
+struct AudioConfig {
+ AudioConfigBase base;
+ AudioOffloadInfo offloadInfo;
+ uint64_t frameCount;
+};
+
+/** Metadata of a playback track for a StreamOut. */
+struct PlaybackTrackMetadata {
+ AudioUsage usage;
+ AudioContentType contentType;
+ /**
+ * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+ * 2 means double amplification...
+ * Must not be negative.
+ */
+ float gain;
+};
+
+/** Metadatas of the source of a StreamOut. */
+struct SourceMetadata {
+ vec<PlaybackTrackMetadata> tracks;
+};
+
+/** Metadata of a record track for a StreamIn. */
+struct RecordTrackMetadata {
+ AudioSource source;
+ /**
+ * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+ * 2 means double amplification...
+ * Must not be negative.
+ */
+ float gain;
+ /**
+ * Indicates the destination of an input stream, can be left unspecified.
+ */
+ safe_union Destination {
+ Monostate unspecified;
+ DeviceAddress device;
+ } destination;
+};
+
+/** Metadatas of the sink of a StreamIn. */
+struct SinkMetadata {
+ vec<RecordTrackMetadata> tracks;
+};
+
+/*
+ *
+ * Volume control
+ *
+ */
+
+/**
+ * Type of gain control exposed by an audio port.
+ */
+@export(name="", value_prefix="AUDIO_GAIN_MODE_")
+enum AudioGainMode : uint32_t {
+ JOINT = 0x1, // supports joint channel gain control
+ CHANNELS = 0x2, // supports separate channel gain control
+ RAMP = 0x4 // supports gain ramps
+};
+
+/**
+ * An audio_gain struct is a representation of a gain stage.
+ * A gain stage is always attached to an audio port.
+ */
+struct AudioGain {
+ bitfield<AudioGainMode> mode;
+ vec<AudioChannelMask> channelMask; // channels which gain an be controlled
+ int32_t minValue; // minimum gain value in millibels
+ int32_t maxValue; // maximum gain value in millibels
+ int32_t defaultValue; // default gain value in millibels
+ uint32_t stepValue; // gain step in millibels
+ uint32_t minRampMs; // minimum ramp duration in ms
+ uint32_t maxRampMs; // maximum ramp duration in ms
+};
+
+/**
+ * The gain configuration structure is used to get or set the gain values of a
+ * given port.
+ */
+struct AudioGainConfig {
+ int32_t index; // index of the corresponding AudioGain in AudioPort.gains
+ AudioGainMode mode;
+ vec<AudioChannelMask> channelMask; // channels which gain value follows
+ /**
+ * Gain values in millibels for each channel ordered from LSb to MSb in
+ * channel mask. The number of values is 1 in joint mode or
+ * popcount(channel_mask).
+ */
+ int32_t[4 * 8] values;
+ uint32_t rampDurationMs; // ramp duration in ms
+};
+
+
+/*
+ *
+ * Routing control
+ *
+ */
+
+/*
+ * Types defined here are used to describe an audio source or sink at internal
+ * framework interfaces (audio policy, patch panel) or at the audio HAL.
+ * Sink and sources are grouped in a concept of “audio port” representing an
+ * audio end point at the edge of the system managed by the module exposing
+ * the interface.
+ */
+
+/**
+ * A helper aggregate structure providing parameters that depend on the
+ * port role.
+ */
+safe_union AudioPortExtendedInfo {
+ /** Set when no information is provided. */
+ Monostate unspecified;
+ /** Set when the audio port is an audio device. */
+ DeviceAddress device;
+ /** Set when the audio port is a mix. The handle is of a stream. */
+ struct AudioPortMixExt {
+ /** I/O handle of the input/output stream. */
+ AudioIoHandle ioHandle;
+ safe_union UseCase {
+ /** Specified when the port is in the SOURCE role. */
+ AudioStreamType stream;
+ /** Specified when the port is in the SINK role. */
+ AudioSource source;
+ } useCase;
+ } mix;
+ /** Set when the audio port is an audio session. */
+ AudioSession session;
+};
+
+/**
+ * Audio port configuration structure used to specify a particular configuration
+ * of an audio port.
+ */
+struct AudioPortConfig {
+ /**
+ * The 'id' field is set when it is needed to select the port and
+ * apply new configuration for it.
+ */
+ AudioPortHandle id;
+ /**
+ * Basic parameters: sampling rate, format, channel mask. Only some of the
+ * parameters (or none) may be set. See the documentation of the
+ * AudioConfigBase struct.
+ */
+ AudioConfigBase config;
+ /** Associated gain control. */
+ safe_union OptionalGain {
+ Monostate unspecified;
+ AudioGainConfig config;
+ } gain;
+ /** Parameters that depend on the actual port role. */
+ AudioPortExtendedInfo ext;
+};
+
+/**
+ * Audio port structure describes the capabilities of an audio port
+ * as well as its current configuration.
+ */
+struct AudioPort {
+ /**
+ * Unique identifier of the port within this HAL service. When calling
+ * from the client side functions like IDevice.getAudioPort is it allowed
+ * to only specify the 'id' and leave the other fields unspecified.
+ */
+ AudioPortHandle id;
+ /**
+ * Human-readable name describing the function of the port.
+ * E.g. "telephony_tx" or "fm_tuner".
+ */
+ string name;
+ /** List of audio profiles supported by the port. */
+ vec<AudioProfile> profiles;
+ /** List of gain controls attached to the port. */
+ vec<AudioGain> gains;
+ /**
+ * Current configuration of the audio port, may have all the fields left
+ * unspecified.
+ */
+ AudioPortConfig activeConfig;
+};
diff --git a/audio/common/all-versions/copyHAL.sh b/audio/common/all-versions/copyHAL.sh
index 0a32a51..23e057a 100755
--- a/audio/common/all-versions/copyHAL.sh
+++ b/audio/common/all-versions/copyHAL.sh
@@ -16,6 +16,7 @@
readonly HAL_DIRECTORY=hardware/interfaces/audio
readonly HAL_VTS_DIRECTORY=core/all-versions/vts/functional
readonly HAL_VTS_FILE=AudioPrimaryHidlHalTest.cpp
+readonly HAL_EFFECT_VTS_DIRECTORY=effect/all-versions/vts/functional
readonly HAL_SERVICE_DIRECTORY=common/all-versions/default/service/
readonly HAL_SERVICE_CPP=service.cpp
@@ -25,7 +26,7 @@
readonly VTS_DIRECTORY=test/vts-testcase/hal/audio
readonly VTS_LIST=test/vts/tools/build/tasks/list/vts_test_lib_hidl_package_list.mk
-readonly WATCHDOG=frameworks/base/services/core/java/com/android/server/Watchdog.cpp
+readonly WATCHDOG=frameworks/base/services/core/java/com/android/server/Watchdog.java
readonly DUMP_UTILS=frameworks/native/libs/dumputils/dump_utils.cpp
readonly GSI_CURRENT=build/make/target/product/gsi/current.txt
@@ -45,6 +46,9 @@
readonly BASE_VERSION_ESCAPE="${BASE_MAJOR_VERSION}\.${BASE_MINOR_VERSION}"
readonly BASE_VERSION_UNDERSCORE="${BASE_MAJOR_VERSION}_${BASE_MINOR_VERSION}"
readonly NEW_VERSION_UNDERSCORE="${NEW_MAJOR_VERSION}_${NEW_MINOR_VERSION}"
+
+readonly HAL_VTS_CONFIG_FILE_GLOB="*Audio*V${BASE_VERSION_UNDERSCORE}*Test.xml"
+
updateVersion() {
if [ $1 == "-e" ]; then
local -r REGEX="$2"; shift 2
@@ -71,6 +75,10 @@
updateVersion -e "audio.*$BASE_VERSION_REGEX" "$@"
}
+updateAudioVtsTargetVersion() {
+ updateVersion -e "Audio.*V$BASE_VERSION_REGEX" "$@"
+}
+
updateLicenceDates() {
# Update date on the 2 first lines
sed -i "1,2 s/20[0-9][0-9]/$(date +"%Y")/g" "$@"
@@ -101,9 +109,16 @@
cp -Tar $DIR/$BASE_VERSION $DIR/$NEW_VERSION
COPY+=" $DIR/$NEW_VERSION"
done
+ local COPY_FILES_TO=
+ for FILE_FROM in $(find . -type f -name "$HAL_VTS_CONFIG_FILE_GLOB"); do
+ local FILE_TO=${FILE_FROM/$BASE_VERSION_UNDERSCORE/$NEW_VERSION_UNDERSCORE}
+ cp "$FILE_FROM" "$FILE_TO"
+ COPY_FILES_TO+=" $FILE_TO"
+ done
echo "Replacing $BASE_VERSION by $NEW_VERSION in the copied files"
updateVersion $(find $COPY -type f)
+ updateVersion $COPY_FILES_TO
updateLicenceDates $(find $COPY -type f)
echo "Update implementation and VTS generic code"
@@ -156,18 +171,12 @@
echo "Now creating the framework adapter version"
runIfNeeded $FWK_DIRECTORY createFrameworkAdapter
-createVTSXML() {
- cp -Tar V$BASE_VERSION_UNDERSCORE V$NEW_VERSION_UNDERSCORE
- cp -Tar effect/{V$BASE_VERSION_UNDERSCORE,V$NEW_VERSION_UNDERSCORE}
- local -r FILES=$(find {.,effect}/V$NEW_VERSION_UNDERSCORE -type f)
- updateVersion $FILES
- updateLicenceDates $FILES
-}
-echo "Now update VTS XML"
-runIfNeeded $VTS_DIRECTORY createVTSXML
-
echo "Now register new VTS"
+PREV_MODIFIED="$MODIFIED"
runIfNeeded $(dirname $VTS_LIST) updateAudioVersion -v original_before=1 $(basename $VTS_LIST)
+if [[ "$PREV_MODIFIED" != "$MODIFIED" ]]; then
+ updateAudioVtsTargetVersion -v original_after=1 $(basename $VTS_LIST)
+fi
echo "Now update watchdog"
runIfNeeded $(dirname $WATCHDOG) updateAudioVersion -v original_before=1 $(basename $WATCHDOG)
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 0eb4a71..a72c8dc 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -36,7 +36,7 @@
],
export_header_lib_headers: [
"android.hardware.audio.common.util@all-versions",
- ]
+ ],
}
cc_defaults {
@@ -57,7 +57,7 @@
"android.hardware.audio.common-util",
],
export_shared_lib_headers: [
- "android.hardware.audio.common-util"
+ "android.hardware.audio.common-util",
],
header_libs: [
@@ -76,7 +76,7 @@
"-DMAJOR_VERSION=2",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -89,7 +89,7 @@
"-DMAJOR_VERSION=4",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -102,7 +102,7 @@
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -115,5 +115,19 @@
"-DMAJOR_VERSION=6",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
+}
+
+cc_library_shared {
+ enabled: false,
+ name: "android.hardware.audio.common@7.0-util",
+ defaults: ["android.hardware.audio.common-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
}
diff --git a/audio/common/all-versions/default/VersionUtils.h b/audio/common/all-versions/default/VersionUtils.h
index e7755b1..9bfca0c 100644
--- a/audio/common/all-versions/default/VersionUtils.h
+++ b/audio/common/all-versions/default/VersionUtils.h
@@ -31,7 +31,7 @@
typedef common::CPP_VERSION::AudioChannelMask AudioChannelBitfield;
typedef common::CPP_VERSION::AudioOutputFlag AudioOutputFlagBitfield;
typedef common::CPP_VERSION::AudioInputFlag AudioInputFlagBitfield;
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
typedef hidl_bitfield<common::CPP_VERSION::AudioDevice> AudioDeviceBitfield;
typedef hidl_bitfield<common::CPP_VERSION::AudioChannelMask> AudioChannelBitfield;
typedef hidl_bitfield<common::CPP_VERSION::AudioOutputFlag> AudioOutputFlagBitfield;
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 3e8b715..f163a2f 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -4,11 +4,11 @@
init_rc: ["android.hardware.audio.service.rc"],
relative_install_path: "hw",
vendor: true,
- // Only support 32 bit as the binary must always be installed at the same
+ // Prefer 32 bit as the binary must always be installed at the same
// location for init to start it and the build system does not support
// having two binaries installable to the same location even if they are
// not installed in the same build.
- compile_multilib: "32",
+ compile_multilib: "prefer32",
srcs: ["service.cpp"],
cflags: [
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 147d062..710ddce 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -87,7 +87,8 @@
},
{
"Bluetooth Audio API",
- "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory"
+ "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory",
+ "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory",
},
// remove the old HIDL when Bluetooth Audio Hal V2 has offloading supported
{
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 0af81b2..6be0628 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -1,8 +1,5 @@
-cc_defaults {
- name: "android.hardware.audio-impl_default",
- relative_install_path: "hw",
- proprietary: true,
- vendor: true,
+filegroup {
+ name: "android.hardware.audio-impl_srcs",
srcs: [
"Conversions.cpp",
"Device.cpp",
@@ -13,11 +10,24 @@
"StreamIn.cpp",
"StreamOut.cpp",
],
+}
+
+cc_library_headers {
+ name: "android.hardware.audio-impl_headers",
+ proprietary: true,
+ vendor: true,
+ export_include_dirs: ["include"],
+}
+
+cc_defaults {
+ name: "android.hardware.audio-impl_default",
+ relative_install_path: "hw",
+ proprietary: true,
+ vendor: true,
+ srcs: [":android.hardware.audio-impl_srcs"],
defaults: ["hidl_defaults"],
- export_include_dirs: ["include"],
-
static_libs: [
"libaudiofoundation",
],
@@ -35,12 +45,17 @@
],
header_libs: [
+ "android.hardware.audio-impl_headers",
"android.hardware.audio.common.util@all-versions",
"libaudioclient_headers",
"libaudio_system_headers",
"libhardware_headers",
"libmedia_headers",
],
+
+ export_header_lib_headers: [
+ "android.hardware.audio-impl_headers",
+ ],
}
cc_library_shared {
@@ -89,8 +104,8 @@
],
}
-cc_library_shared {
- name: "android.hardware.audio@6.0-impl",
+cc_defaults {
+ name: "android.hardware.audio@6.0-impl_default",
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@6.0",
@@ -103,3 +118,24 @@
"-include common/all-versions/VersionMacro.h",
],
}
+
+cc_library_shared {
+ name: "android.hardware.audio@6.0-impl",
+ defaults: ["android.hardware.audio@6.0-impl_default"],
+}
+
+cc_library_shared {
+ enabled: false,
+ name: "android.hardware.audio@7.0-impl",
+ defaults: ["android.hardware.audio-impl_default"],
+ shared_libs: [
+ "android.hardware.audio@7.0",
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-util",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index b0e72d9..907acd7 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -43,8 +43,10 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
+#if MAJOR_VERSION <= 6
using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
+#endif
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index b0eb2e0..2466fd1 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -16,6 +16,13 @@
#include "AudioPrimaryHidlHalTest.h"
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0.h>
+#include <xsdc/XsdcSupport.h>
+
+using android::xsdc_enum_range;
+#endif
+
TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
doc::test("Calling openDevice(\"primary\") should return the primary device.");
if (getDeviceName() != DeviceManager::kPrimaryDevice) {
@@ -53,14 +60,29 @@
"Make sure getMicrophones always succeeds"
"and getActiveMicrophones always succeeds when recording from these microphones.");
AudioConfig config{};
+#if MAJOR_VERSION <= 6
config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
config.sampleRateHz = 8000;
config.format = AudioFormat::PCM_16_BIT;
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+#elif MAJOR_VERSION >= 7
+ config.base.channelMask.resize(1);
+ config.base.channelMask[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
+ config.base.sampleRateHz = 8000;
+ config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ hidl_vec<hidl_string> flags;
+ const SinkMetadata initMetadata = {
+ {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+#endif
EventFlag* efGroup;
for (auto microphone : microphones) {
+#if MAJOR_VERSION <= 6
if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
+#elif MAJOR_VERSION >= 7
+ if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) !=
+ xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) {
+#endif
continue;
}
sp<IStreamIn> stream;
@@ -81,16 +103,16 @@
size_t frameSize = stream->getFrameSize();
size_t frameCount = stream->getBufferSize() / frameSize;
ASSERT_OK(stream->prepareForReading(
- frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto&) {
- readRes = r;
- if (readRes == Result::OK) {
- commandMQ.reset(new CommandMQ(c));
- dataMQ.reset(new DataMQ(d));
- if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
- EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
+ frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) {
+ readRes = r;
+ if (readRes == Result::OK) {
+ commandMQ.reset(new CommandMQ(c));
+ dataMQ.reset(new DataMQ(d));
+ if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
+ EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
+ }
}
- }
- }));
+ }));
ASSERT_OK(readRes);
IStreamIn::ReadParameters params;
params.command = IStreamIn::ReadCommand::READ;
@@ -116,13 +138,24 @@
TEST_P(AudioHidlDeviceTest, SetConnectedState) {
doc::test("Check that the HAL can be notified of device connection and deconnection");
+#if MAJOR_VERSION <= 6
using AD = AudioDevice;
for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+#elif MAJOR_VERSION >= 7
+ using AD = xsd::AudioDevice;
+ for (auto deviceType :
+ {toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+ toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) {
+#endif
SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
for (bool state : {true, false}) {
SCOPED_TRACE("state=" + ::testing::PrintToString(state));
DeviceAddress address = {};
+#if MAJOR_VERSION <= 6
address.device = deviceType;
+#elif MAJOR_VERSION >= 7
+ address.deviceType = deviceType;
+#endif
auto ret = getDevice()->setConnectedState(address, state);
ASSERT_TRUE(ret.isOk());
if (ret == Result::NOT_SUPPORTED) {
@@ -148,7 +181,11 @@
}
// The stream was constructed with one device, thus getDevices must only return one
ASSERT_EQ(1U, devices.size());
+#if MAJOR_VERSION <= 6
AudioDevice device = devices[0].device;
+#elif MAJOR_VERSION >= 7
+ auto device = devices[0].deviceType;
+#endif
ASSERT_TRUE(device == expectedDevice)
<< "Expected: " << ::testing::PrintToString(expectedDevice)
<< "\n Actual: " << ::testing::PrintToString(device);
@@ -156,12 +193,22 @@
TEST_IO_STREAM(GetDevices, "Check that the stream device == the one it was opened with",
areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
+#if MAJOR_VERSION <= 6
: testGetDevices(stream.get(), address.device))
+#elif MAJOR_VERSION >= 7
+ : testGetDevices(stream.get(), address.deviceType))
+#endif
static void testSetDevices(IStream* stream, const DeviceAddress& address) {
DeviceAddress otherAddress = address;
+#if MAJOR_VERSION <= 6
otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
: AudioDevice::IN_BUILTIN_MIC;
+#elif MAJOR_VERSION >= 7
+ otherAddress.deviceType = xsd::isOutputDevice(address.deviceType)
+ ? toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)
+ : toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
+#endif
EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress}));
ASSERT_RESULT(okOrNotSupported,
@@ -186,11 +233,19 @@
TEST_P(InputStreamTest, updateSinkMetadata) {
doc::test("The HAL should not crash on metadata change");
+#if MAJOR_VERSION <= 6
hidl_enum_range<AudioSource> range;
+#elif MAJOR_VERSION >= 7
+ xsdc_enum_range<audio::policy::configuration::V7_0::AudioSource> range;
+#endif
// Test all possible track configuration
- for (AudioSource source : range) {
+ for (auto source : range) {
for (float volume : {0.0, 0.5, 1.0}) {
+#if MAJOR_VERSION <= 6
const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
+#elif MAJOR_VERSION >= 7
+ const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}};
+#endif
ASSERT_OK(stream->updateSinkMetadata(metadata))
<< "source=" << toString(source) << ", volume=" << volume;
}
@@ -213,13 +268,22 @@
TEST_P(OutputStreamTest, updateSourceMetadata) {
doc::test("The HAL should not crash on metadata change");
+#if MAJOR_VERSION <= 6
hidl_enum_range<AudioUsage> usageRange;
hidl_enum_range<AudioContentType> contentRange;
+#elif MAJOR_VERSION >= 7
+ xsdc_enum_range<audio::policy::configuration::V7_0::AudioUsage> usageRange;
+ xsdc_enum_range<audio::policy::configuration::V7_0::AudioContentType> contentRange;
+#endif
// Test all possible track configuration
for (auto usage : usageRange) {
for (auto content : contentRange) {
for (float volume : {0.0, 0.5, 1.0}) {
+#if MAJOR_VERSION <= 6
const SourceMetadata metadata = {{{usage, content, volume}}};
+#elif MAJOR_VERSION >= 7
+ const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}};
+#endif
ASSERT_OK(stream->updateSourceMetadata(metadata))
<< "usage=" << toString(usage) << ", content=" << toString(content)
<< ", volume=" << volume;
@@ -227,12 +291,26 @@
}
}
+ // clang-format off
// Set many track of different configuration
ASSERT_OK(stream->updateSourceMetadata(
+#if MAJOR_VERSION <= 6
{{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1},
{AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0},
{AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0},
- {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}));
+ {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
+#elif MAJOR_VERSION >= 7
+ {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1},
+ {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0},
+ {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0},
+ {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}}
+#endif
+ ));
+ // clang-format on
// Set no metadata as if all stream track had stopped
ASSERT_OK(stream->updateSourceMetadata({}));
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
index 7a52d0e..81a1f7b 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
@@ -56,6 +56,7 @@
}
};
+#if MAJOR_VERSION <= 6
struct GetSupported {
static auto getFormat(IStream* stream) {
auto ret = stream->getFormat();
@@ -80,7 +81,7 @@
EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities)));
return Result::OK;
}
-#elif MAJOR_VERSION >= 6
+#else // MAJOR_VERSION == 6
static Result formats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
Result res;
EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities)));
@@ -88,6 +89,7 @@
}
#endif
};
+#endif // MAJOR_VERSION <= 6
template <class T>
auto dump(T t, hidl_handle handle) {
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index e09eeab..bd8de2d 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -17,6 +17,7 @@
// pull in all the <= 5.0 tests
#include "5.0/AudioPrimaryHidlHalTest.cpp"
+#if MAJOR_VERSION <= 6
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
@@ -28,8 +29,8 @@
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
- vector<audio_channel_mask_t>(channels.begin(), channels.end()),
- vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
+ std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
+ std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
profile->getFormat());
auto flags = ioProfile->getFlags();
for (auto& config : configs) {
@@ -46,8 +47,8 @@
config.offloadInfo.bufferSize = 256; // arbitrary value
config.offloadInfo.usage = AudioUsage::MEDIA;
result.emplace_back(device, config,
- AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
- AUDIO_OUTPUT_FLAG_DIRECT));
+ AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD |
+ AudioOutputFlag::DIRECT));
} else {
if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag
flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
@@ -74,8 +75,8 @@
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
- vector<audio_channel_mask_t>(channels.begin(), channels.end()),
- vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
+ std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
+ std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
profile->getFormat());
for (const auto& config : configs) {
result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags()));
@@ -87,13 +88,22 @@
}();
return parameters;
}
+#endif // MAJOR_VERSION <= 6
TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
doc::test("Verify that a device can't be closed if there are streams opened");
+#if MAJOR_VERSION <= 6
DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
- AudioConfig config{};
- auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
+ auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
+#elif MAJOR_VERSION >= 7
+ DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
+ SourceMetadata initMetadata = {
+ {{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}};
+ hidl_vec<AudioInOutFlag> flags;
+#endif
+ AudioConfig config{};
sp<IStreamOut> stream;
StreamHelper<IStreamOut> helper(stream);
AudioConfig suggestedConfig{};
@@ -111,14 +121,20 @@
TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
doc::test("Verify that a device can't be closed if there are streams opened");
- auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
- if (module->getInputProfiles().empty()) {
+ if (!getCachedPolicyConfig().haveInputProfilesInModule(getDeviceName())) {
GTEST_SKIP() << "Device doesn't have input profiles";
}
+#if MAJOR_VERSION <= 6
DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
- AudioConfig config{};
- auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+ auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
+#elif MAJOR_VERSION >= 7
+ DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
+ SinkMetadata initMetadata = {
+ {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+ hidl_vec<AudioInOutFlag> flags;
+#endif
+ AudioConfig config{};
sp<IStreamIn> stream;
StreamHelper<IStreamIn> helper(stream);
AudioConfig suggestedConfig{};
@@ -137,9 +153,8 @@
TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
AudioPatchHandle ignored;
- ASSERT_OK(getDevice()->updateAudioPatch(
- static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
- hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
+ ASSERT_OK(getDevice()->updateAudioPatch(AudioPatchHandle{}, hidl_vec<AudioPortConfig>(),
+ hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
}
@@ -152,6 +167,7 @@
&IStreamOut::setDualMonoMode, &IStreamOut::getDualMonoMode);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DualMonoModeAccessorHidlTest);
INSTANTIATE_TEST_CASE_P(DualMonoModeHidl, DualMonoModeAccessorHidlTest,
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
@@ -166,6 +182,7 @@
{48.5f, 1000.0f, std::numeric_limits<float>::infinity()});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioDescriptionMixLevelHidlTest);
INSTANTIATE_TEST_CASE_P(AudioDescriptionMixLevelHidl, AudioDescriptionMixLevelHidlTest,
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
@@ -200,6 +217,7 @@
TimestretchFallbackMode::FAIL}});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PlaybackRateParametersHidlTest);
INSTANTIATE_TEST_CASE_P(PlaybackRateParametersHidl, PlaybackRateParametersHidlTest,
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..63eaea8
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// pull in all the <= 6.0 tests
+#include "6.0/AudioPrimaryHidlHalTest.cpp"
+
+static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,
+ std::vector<int64_t> sampleRates,
+ const std::string& format) {
+ std::vector<AudioConfig> configs;
+ configs.reserve(channelMasks.size() * sampleRates.size());
+ for (auto channelMask : channelMasks) {
+ for (auto sampleRate : sampleRates) {
+ AudioConfig config{};
+ // leave offloadInfo to 0
+ config.base.channelMask.resize(1);
+ config.base.channelMask[0] = toString(channelMask);
+ config.base.sampleRateHz = sampleRate;
+ config.base.format = format;
+ configs.push_back(config);
+ }
+ }
+ return configs;
+}
+
+const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
+ static std::vector<DeviceConfigParameter> parameters = [] {
+ std::vector<DeviceConfigParameter> result;
+ const std::vector<AudioInOutFlag> offloadFlags = {
+ toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+ toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
+ for (const auto& device : getDeviceParameters()) {
+ auto module =
+ getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+ if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
+ auto xsdFlags = mixPort.getFlags();
+ const bool isOffload =
+ std::find(xsdFlags.begin(), xsdFlags.end(),
+ xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
+ xsdFlags.end();
+ std::vector<AudioInOutFlag> flags;
+ if (!isOffload) {
+ for (auto flag : xsdFlags) {
+ if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
+ flags.push_back(toString(flag));
+ }
+ }
+ } else {
+ flags = offloadFlags;
+ }
+ for (const auto& profile : mixPort.getProfile()) {
+ auto configs =
+ combineAudioConfig(profile.getChannelMasks(),
+ profile.getSamplingRates(), profile.getFormat());
+ for (auto& config : configs) {
+ // Some combinations of flags declared in the config file require special
+ // treatment.
+ if (isOffload) {
+ config.offloadInfo.base = config.base;
+ config.offloadInfo.streamType =
+ toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
+ config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
+ config.offloadInfo.bitRatePerSecond = 320;
+ config.offloadInfo.durationMicroseconds = -1;
+ config.offloadInfo.bitWidth = 16;
+ config.offloadInfo.bufferSize = 256; // arbitrary value
+ }
+ result.emplace_back(device, config, flags);
+ }
+ }
+ }
+ }
+ return result;
+ }();
+ return parameters;
+}
+
+const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
+ static std::vector<DeviceConfigParameter> parameters = [] {
+ std::vector<DeviceConfigParameter> result;
+ for (const auto& device : getDeviceParameters()) {
+ auto module =
+ getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+ if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
+ std::vector<AudioInOutFlag> flags;
+ std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(),
+ [](auto flag) { return toString(flag); });
+ for (const auto& profile : mixPort.getProfile()) {
+ auto configs =
+ combineAudioConfig(profile.getChannelMasks(),
+ profile.getSamplingRates(), profile.getFormat());
+ for (const auto& config : configs) {
+ result.emplace_back(device, config, flags);
+ }
+ }
+ }
+ }
+ return result;
+ }();
+ return parameters;
+}
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
new file mode 100644
index 0000000..d790b34
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
+
+namespace xsd {
+using Module = Modules::Module;
+}
+
+class PolicyConfig {
+ public:
+ explicit PolicyConfig(const std::string& configFileName)
+ : mConfigFileName{configFileName},
+ mFilePath{findExistingConfigurationFile(mConfigFileName)},
+ mConfig{xsd::read(mFilePath.c_str())} {
+ if (mConfig) {
+ mStatus = OK;
+ mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+ for (const auto& module : mConfig->getFirstModules()->get_module()) {
+ auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+ if (!attachedDevices.empty()) {
+ mModulesWithDevicesNames.insert(module.getName());
+ }
+ }
+ }
+ }
+ status_t getStatus() const { return mStatus; }
+ std::string getError() const {
+ if (mFilePath.empty()) {
+ return std::string{"Could not find "} + mConfigFileName +
+ " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+ } else {
+ return "Invalid config file: " + mFilePath;
+ }
+ }
+ const std::string& getFilePath() const { return mFilePath; }
+ const xsd::Module* getModuleFromName(const std::string& name) const {
+ if (mConfig) {
+ for (const auto& module : mConfig->getFirstModules()->get_module()) {
+ if (module.getName() == name) return &module;
+ }
+ }
+ return nullptr;
+ }
+ const xsd::Module* getPrimaryModule() const { return mPrimaryModule; }
+ const std::set<std::string>& getModulesWithDevicesNames() const {
+ return mModulesWithDevicesNames;
+ }
+ bool haveInputProfilesInModule(const std::string& name) const {
+ auto module = getModuleFromName(name);
+ for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+ if (mixPort.getRole() == xsd::Role::sink) return true;
+ }
+ return false;
+ }
+
+ private:
+ static std::string findExistingConfigurationFile(const std::string& fileName) {
+ for (const auto& location : android::audio_get_configuration_paths()) {
+ std::string path = location + '/' + fileName;
+ if (access(path.c_str(), F_OK) == 0) {
+ return path;
+ }
+ }
+ return std::string{};
+ }
+
+ const std::string mConfigFileName;
+ const std::string mFilePath;
+ std::optional<xsd::AudioPolicyConfiguration> mConfig;
+ status_t mStatus = NO_INIT;
+ const xsd::Module* mPrimaryModule;
+ std::set<std::string> mModulesWithDevicesNames;
+};
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 729ee7a..c7bfe08 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -19,9 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
static_libs: [
"android.hardware.audio.common.test.utility",
- "libaudiofoundation",
- "libaudiopolicycomponents",
- "libmedia_helper",
"libxml2",
],
shared_libs: [
@@ -44,6 +41,9 @@
"2.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
+ "libaudiofoundation",
+ "libaudiopolicycomponents",
+ "libmedia_helper",
"android.hardware.audio@2.0",
"android.hardware.audio.common@2.0",
],
@@ -55,7 +55,7 @@
data: [
":audio_policy_configuration_V2_0",
],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioV2_0TargetTest.xml",
}
@@ -67,6 +67,9 @@
"4.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
+ "libaudiofoundation",
+ "libaudiopolicycomponents",
+ "libmedia_helper",
"android.hardware.audio@4.0",
"android.hardware.audio.common@4.0",
],
@@ -78,7 +81,7 @@
data: [
":audio_policy_configuration_V4_0",
],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioV4_0TargetTest.xml",
}
@@ -90,6 +93,9 @@
"5.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
+ "libaudiofoundation",
+ "libaudiopolicycomponents",
+ "libmedia_helper",
"android.hardware.audio@5.0",
"android.hardware.audio.common@5.0",
],
@@ -101,7 +107,7 @@
data: [
":audio_policy_configuration_V5_0",
],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioV5_0TargetTest.xml",
}
@@ -113,6 +119,9 @@
"6.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
+ "libaudiofoundation",
+ "libaudiopolicycomponents",
+ "libmedia_helper",
"android.hardware.audio@6.0",
"android.hardware.audio.common@6.0",
],
@@ -124,7 +133,31 @@
data: [
":audio_policy_configuration_V6_0",
],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioV6_0TargetTest.xml",
}
+
+cc_test {
+ name: "VtsHalAudioV7_0TargetTest",
+ defaults: ["VtsHalAudioTargetTest_defaults"],
+ srcs: [
+ "7.0/AudioPrimaryHidlHalTest.cpp",
+ ],
+ static_libs: [
+ "android.hardware.audio@7.0",
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+ data: [
+ ":audio_policy_configuration_V7_0",
+ ],
+ // Use test_config for vts suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV7_0TargetTest.xml",
+}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index d5af335..5e4b414 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -42,8 +42,11 @@
#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
#include PATH(android/hardware/audio/FILE_VERSION/types.h)
#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0-enums.h>
+#include <audio_policy_configuration_V7_0.h>
+#endif
-#include <Serializer.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
#include <hidl/GtestPrinter.h>
@@ -63,14 +66,6 @@
#include "4.0/AudioPrimaryHidlHalUtils.h"
#endif
-using std::initializer_list;
-using std::list;
-using std::string;
-using std::to_string;
-using std::vector;
-
-using ::android::AudioPolicyConfig;
-using ::android::HwModule;
using ::android::NO_INIT;
using ::android::OK;
using ::android::sp;
@@ -93,6 +88,12 @@
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
+#if MAJOR_VERSION >= 7
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::CPP_VERSION;
+}
+#endif
// Typical accepted results from interface methods
static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
@@ -103,8 +104,12 @@
static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
-#define AUDIO_PRIMARY_HIDL_HAL_TEST
#include "DeviceManager.h"
+#if MAJOR_VERSION <= 6
+#include "PolicyConfig.h"
+#elif MAJOR_VERSION >= 7
+#include "7.0/PolicyConfig.h"
+#endif
class HidlTest : public ::testing::Test {
public:
@@ -136,83 +141,16 @@
////////////////////////// Audio policy configuration ////////////////////////
//////////////////////////////////////////////////////////////////////////////
-static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
-
// Stringify the argument.
#define QUOTE(x) #x
#define STRINGIFY(x) QUOTE(x)
-struct PolicyConfigData {
- android::HwModuleCollection hwModules;
- android::DeviceVector availableOutputDevices;
- android::DeviceVector availableInputDevices;
- sp<android::DeviceDescriptor> defaultOutputDevice;
-};
-
-class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
- public:
- PolicyConfig()
- : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
- defaultOutputDevice) {
- for (const auto& location : android::audio_get_configuration_paths()) {
- std::string path = location + '/' + kConfigFileName;
- if (access(path.c_str(), F_OK) == 0) {
- mFilePath = path;
- break;
- }
- }
- mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
- if (mStatus == OK) {
- mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice);
- // Available devices are not 'attached' to modules at this moment.
- // Need to go over available devices and find their module.
- for (const auto& device : availableOutputDevices) {
- for (const auto& module : hwModules) {
- if (module->getDeclaredDevices().indexOf(device) >= 0) {
- mModulesWithDevicesNames.insert(module->getName());
- break;
- }
- }
- }
- for (const auto& device : availableInputDevices) {
- for (const auto& module : hwModules) {
- if (module->getDeclaredDevices().indexOf(device) >= 0) {
- mModulesWithDevicesNames.insert(module->getName());
- break;
- }
- }
- }
- }
- }
- status_t getStatus() const { return mStatus; }
- std::string getError() const {
- if (mFilePath.empty()) {
- return std::string{"Could not find "} + kConfigFileName +
- " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
- } else {
- return "Invalid config file: " + mFilePath;
- }
- }
- const std::string& getFilePath() const { return mFilePath; }
- sp<const HwModule> getModuleFromName(const std::string& name) const {
- return getHwModules().getModuleFromName(name.c_str());
- }
- sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
- const std::set<std::string>& getModulesWithDevicesNames() const {
- return mModulesWithDevicesNames;
- }
-
- private:
- status_t mStatus = NO_INIT;
- std::string mFilePath;
- sp<HwModule> mPrimaryModule = nullptr;
- std::set<std::string> mModulesWithDevicesNames;
-};
+static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
// Cached policy config after parsing for faster test startup
const PolicyConfig& getCachedPolicyConfig() {
static std::unique_ptr<PolicyConfig> policyConfig = [] {
- auto config = std::make_unique<PolicyConfig>();
+ auto config = std::make_unique<PolicyConfig>(kConfigFileName);
return config;
}();
return *policyConfig;
@@ -331,6 +269,9 @@
INSTANTIATE_TEST_CASE_P(AudioHidl, AudioPolicyConfigTest,
::testing::ValuesIn(getDeviceParametersForFactoryTests()),
&DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPolicyConfigTest);
//////////////////////////////////////////////////////////////////////////////
////////////////////// getService audio_devices_factory //////////////////////
@@ -366,6 +307,9 @@
INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest,
::testing::ValuesIn(getDeviceParametersForFactoryTests()),
&DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlTest);
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// openDevice ///////////////////////////////////
@@ -391,6 +335,9 @@
INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest,
::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlDeviceTest);
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// openDevice primary ///////////////////////////
@@ -418,6 +365,9 @@
INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest,
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
&DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPrimaryHidlTest);
//////////////////////////////////////////////////////////////////////////////
///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
@@ -437,9 +387,10 @@
* The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
*/
template <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
- void testAccessors(IUTGetter iutGetter, const string& propertyName,
- const Initial expectedInitial, list<Property> valuesToTest, Setter setter,
- Getter getter, const vector<Property>& invalidValues = {}) {
+ void testAccessors(IUTGetter iutGetter, const std::string& propertyName,
+ const Initial expectedInitial, std::list<Property> valuesToTest,
+ Setter setter, Getter getter,
+ const std::vector<Property>& invalidValues = {}) {
const auto expectedResults = {Result::OK,
optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
@@ -483,9 +434,9 @@
EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue));
}
template <Optionality optionality = REQUIRED, class Getter, class Setter>
- void testAccessors(const string& propertyName, const Initial expectedInitial,
- list<Property> valuesToTest, Setter setter, Getter getter,
- const vector<Property>& invalidValues = {}) {
+ void testAccessors(const std::string& propertyName, const Initial expectedInitial,
+ std::list<Property> valuesToTest, Setter setter, Getter getter,
+ const std::vector<Property>& invalidValues = {}) {
testAccessors<optionality>(&BaseTestClass::getDevice, propertyName, expectedInitial,
valuesToTest, setter, getter, invalidValues);
}
@@ -513,6 +464,10 @@
INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
&DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorPrimaryHidlTest);
using FloatAccessorHidlTest = AccessorHidlTest<float>;
TEST_P(FloatAccessorHidlTest, MasterVolumeTest) {
@@ -525,6 +480,9 @@
INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest,
::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FloatAccessorHidlTest);
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// AudioPatches ////////////////////////////////
@@ -547,13 +505,20 @@
INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPatchHidlTest);
// Nesting a tuple in another tuple allows to use GTest Combine function to generate
// all combinations of devices and configs.
enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
+#if MAJOR_VERSION <= 6
enum { INDEX_INPUT, INDEX_OUTPUT };
using DeviceConfigParameter =
std::tuple<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
+#elif MAJOR_VERSION >= 7
+using DeviceConfigParameter = std::tuple<DeviceParameter, AudioConfig, std::vector<AudioInOutFlag>>;
+#endif
#if MAJOR_VERSION >= 6
const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
@@ -561,8 +526,8 @@
#endif
#if MAJOR_VERSION >= 4
-static string SanitizeStringForGTestName(const string& s) {
- string result = s;
+static std::string SanitizeStringForGTestName(const std::string& s) {
+ std::string result = s;
for (size_t i = 0; i < result.size(); i++) {
// gtest test names must only contain alphanumeric characters
if (!std::isalnum(result[i])) result[i] = '_';
@@ -576,43 +541,57 @@
* As the only parameter changing are channel mask and sample rate,
* only print those ones in the test name.
*/
-static string DeviceConfigParameterToString(
+static std::string DeviceConfigParameterToString(
const testing::TestParamInfo<DeviceConfigParameter>& info) {
const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
std::get<PARAM_DEVICE>(info.param), info.index});
- return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" +
- to_string(config.sampleRateHz) + "_" +
- // "MONO" is more clear than "FRONT_LEFT"
- ((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
- config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO))
- ? "MONO"
+ const auto devicePart =
+ (deviceName.empty() ? "" : deviceName + "_") + std::to_string(info.index);
+ // The types had changed a lot between versions 2, 4..6 and 7. Use separate
+ // code sections for easier understanding.
#if MAJOR_VERSION == 2
- : ::testing::PrintToString(config.channelMask)
-#elif MAJOR_VERSION >= 4
- // In V4 and above the channel mask is a bitfield.
- // Printing its value using HIDL's toString for a bitfield emits a lot of extra
- // text due to overlapping constant values. Instead, we print the bitfield value
- // as if it was a single value + its hex representation
- : SanitizeStringForGTestName(
- ::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" +
- toHexString(config.channelMask))
+ const auto configPart =
+ std::to_string(config.sampleRateHz) + "_" +
+ // "MONO" is more clear than "FRONT_LEFT"
+ (config.channelMask == AudioChannelMask::OUT_MONO ||
+ config.channelMask == AudioChannelMask::IN_MONO
+ ? "MONO"
+ : ::testing::PrintToString(config.channelMask)) +
+ "_" +
+ std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
+ std::get<PARAM_FLAGS>(info.param));
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
+ const auto configPart =
+ std::to_string(config.sampleRateHz) + "_" +
+ // "MONO" is more clear than "FRONT_LEFT"
+ (config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
+ config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)
+ ? "MONO"
+ // In V4 and above the channel mask is a bitfield.
+ // Printing its value using HIDL's toString for a bitfield emits a lot of extra
+ // text due to overlapping constant values. Instead, we print the bitfield
+ // value as if it was a single value + its hex representation
+ : SanitizeStringForGTestName(
+ ::testing::PrintToString(AudioChannelMask(config.channelMask)) +
+ "_" + toHexString(config.channelMask))) +
+ "_" +
+ SanitizeStringForGTestName(std::visit(
+ [](auto&& arg) -> std::string {
+ using T = std::decay_t<decltype(arg)>;
+ // Need to use FQN of toString to avoid confusing the compiler
+ return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
+ hidl_bitfield<T>(arg));
+ },
+ std::get<PARAM_FLAGS>(info.param)));
+#elif MAJOR_VERSION >= 7
+ const auto configPart =
+ std::to_string(config.base.sampleRateHz) + "_" +
+ // The channel masks and flags are vectors of strings, just need to sanitize them.
+ SanitizeStringForGTestName(::testing::PrintToString(config.base.channelMask)) + "_" +
+ SanitizeStringForGTestName(::testing::PrintToString(std::get<PARAM_FLAGS>(info.param)));
#endif
- ) +
- "_" +
-#if MAJOR_VERSION == 2
- std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
- std::get<PARAM_FLAGS>(info.param));
-#elif MAJOR_VERSION >= 4
- SanitizeStringForGTestName(std::visit(
- [](auto&& arg) -> std::string {
- using T = std::decay_t<decltype(arg)>;
- // Need to use FQN of toString to avoid confusing the compiler
- return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
- hidl_bitfield<T>(arg));
- },
- std::get<PARAM_FLAGS>(info.param)));
-#endif
+ return devicePart + "__" + configPart;
}
class AudioHidlTestWithDeviceConfigParameter
@@ -638,7 +617,7 @@
AudioOutputFlag getOutputFlags() const {
return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
}
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
hidl_bitfield<AudioInputFlag> getInputFlags() const {
return hidl_bitfield<AudioInputFlag>(
std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
@@ -647,10 +626,17 @@
return hidl_bitfield<AudioOutputFlag>(
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
}
+#elif MAJOR_VERSION >= 7
+ hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
+ hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
#endif
};
+#if MAJOR_VERSION <= 6
+#define AUDIO_PRIMARY_HIDL_HAL_TEST
#include "ConfigHelper.h"
+#undef AUDIO_PRIMARY_HIDL_HAL_TEST
+#endif
//////////////////////////////////////////////////////////////////////////////
///////////////////////////// getInputBufferSize /////////////////////////////
@@ -722,6 +708,10 @@
::testing::ValuesIn(getInputDeviceConfigParameters()),
&DeviceConfigParameterToString);
#endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OptionalInputBufferSizeTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RequiredInputBufferSizeTest);
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// setScreenState ///////////////////////////////
@@ -813,7 +803,7 @@
AudioConfig* suggestedConfigPtr) {
// FIXME: Open a stream without an IOHandle
// This is not required to be accepted by hal implementations
- AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
+ AudioIoHandle ioHandle{};
AudioConfig suggestedConfig{};
bool retryWithSuggestedConfig = true;
if (suggestedConfigPtr == nullptr) {
@@ -906,7 +896,11 @@
class OutputStreamTest : public OpenStreamTest<IStreamOut> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
+#if MAJOR_VERSION <= 6
address.device = AudioDevice::OUT_DEFAULT;
+#elif MAJOR_VERSION >= 7
+ address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT);
+#endif
const AudioConfig& config = getConfig();
auto flags = getOutputFlags();
testOpen(
@@ -920,13 +914,19 @@
},
config);
}
-#if MAJOR_VERSION >= 4
+#if MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
- protected:
+ protected:
const SourceMetadata initMetadata = {
{ { AudioUsage::MEDIA,
AudioContentType::MUSIC,
1 /* gain */ } }};
+#elif MAJOR_VERSION >= 7
+ protected:
+ const SourceMetadata initMetadata = {
+ { { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+ toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
+ 1 /* gain */ } }};
#endif
};
TEST_P(OutputStreamTest, OpenOutputStreamTest) {
@@ -960,13 +960,20 @@
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
#endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest);
////////////////////////////// openInputStream //////////////////////////////
class InputStreamTest : public OpenStreamTest<IStreamIn> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
+#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
+#elif MAJOR_VERSION <= 7
+ address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
+#endif
const AudioConfig& config = getConfig();
auto flags = getInputFlags();
testOpen(
@@ -980,8 +987,11 @@
protected:
#if MAJOR_VERSION == 2
const AudioSource initMetadata = AudioSource::DEFAULT;
-#elif MAJOR_VERSION >= 4
- const SinkMetadata initMetadata = {{{.source = AudioSource::DEFAULT, .gain = 1}}};
+#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
+ const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
+#elif MAJOR_VERSION >= 7
+ const SinkMetadata initMetadata = {
+ {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}};
#endif
};
@@ -1015,6 +1025,9 @@
::testing::ValuesIn(getInputDeviceConfigParameters()),
&DeviceConfigParameterToString);
#endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamTest);
//////////////////////////////////////////////////////////////////////////////
////////////////////////////// IStream getters ///////////////////////////////
@@ -1035,6 +1048,7 @@
TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
ASSERT_TRUE(stream->getFrameCount().isOk()))
+#if MAJOR_VERSION <= 6
TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
@@ -1043,6 +1057,7 @@
TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
+#endif
// TODO: for now only check that the framesize is not incoherent
TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
@@ -1052,7 +1067,7 @@
ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
template <class Property, class CapabilityGetter>
-static void testCapabilityGetter(const string& name, IStream* stream,
+static void testCapabilityGetter(const std::string& name, IStream* stream,
CapabilityGetter capabilityGetter,
Return<Property> (IStream::*getter)(),
Return<Result> (IStream::*setter)(Property),
@@ -1088,6 +1103,7 @@
}
}
+#if MAJOR_VERSION <= 6
TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
testCapabilityGetter("getSupportedSampleRate", stream.get(),
&GetSupported::sampleRates, &IStream::getSampleRate,
@@ -1105,19 +1121,71 @@
TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats,
&IStream::getFormat, &IStream::setFormat))
+#else
+static void testGetSupportedProfiles(IStream* stream) {
+ Result res;
+ hidl_vec<AudioProfile> profiles;
+ auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
+ EXPECT_TRUE(ret.isOk());
+ if (res == Result::OK) {
+ EXPECT_GT(profiles.size(), 0);
+ } else {
+ EXPECT_EQ(Result::NOT_SUPPORTED, res);
+ }
+}
+
+TEST_IO_STREAM(GetSupportedProfiles, "Try to call optional method GetSupportedProfiles",
+ testGetSupportedProfiles(stream.get()))
+
+static void testSetAudioProperties(IStream* stream) {
+ Result res;
+ hidl_vec<AudioProfile> profiles;
+ auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
+ EXPECT_TRUE(ret.isOk());
+ if (res == Result::NOT_SUPPORTED) {
+ GTEST_SKIP() << "Retrieving supported profiles is not implemented";
+ }
+ for (const auto& profile : profiles) {
+ for (const auto& sampleRate : profile.sampleRates) {
+ for (const auto& channelMask : profile.channelMasks) {
+ AudioConfigBase config{.format = profile.format,
+ .sampleRateHz = sampleRate,
+ .channelMask = channelMask};
+ auto ret = stream->setAudioProperties(config);
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(Result::OK, ret) << config.format << "; " << config.sampleRateHz << "; "
+ << toString(config.channelMask);
+ }
+ }
+ }
+}
+
+TEST_IO_STREAM(SetAudioProperties, "Call setAudioProperties for all supported profiles",
+ testSetAudioProperties(stream.get()))
+#endif
static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
+#if MAJOR_VERSION <= 6
uint32_t sampleRateHz;
auto mask = mkEnumBitfield<AudioChannelMask>({});
AudioFormat format;
- stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
+ auto ret = stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
+ EXPECT_TRUE(ret.isOk());
// FIXME: the qcom hal it does not currently negotiate the sampleRate &
// channel mask
EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
EXPECT_EQ(expectedConfig.channelMask, mask);
EXPECT_EQ(expectedConfig.format, format);
+#elif MAJOR_VERSION >= 7
+ AudioConfigBase actualConfig{};
+ auto ret = stream->getAudioProperties(returnIn(actualConfig));
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(expectedConfig.base.sampleRateHz, actualConfig.sampleRateHz);
+ EXPECT_EQ(expectedConfig.base.channelMask, actualConfig.channelMask);
+ EXPECT_EQ(expectedConfig.base.format, actualConfig.format);
+#endif
}
TEST_IO_STREAM(GetAudioProperties,
@@ -1128,7 +1196,7 @@
ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666)))
static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
- initializer_list<Result> expectedResults) {
+ std::initializer_list<Result> expectedResults) {
hidl_vec<ParameterValue> parameters;
Result res;
ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters)));
@@ -1239,7 +1307,11 @@
return;
}
ASSERT_OK(res);
+#if MAJOR_VERSION <= 6
ASSERT_EQ(AudioSource::DEFAULT, source);
+#elif MAJOR_VERSION >= 7
+ ASSERT_EQ(xsd::AudioSource::AUDIO_SOURCE_DEFAULT, xsd::stringToAudioSource(source));
+#endif
}
static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
@@ -1254,7 +1326,7 @@
}
static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
- string debugName) {
+ std::string debugName) {
auto result = setGain(1);
ASSERT_IS_OK(result);
if (result == Result::NOT_SUPPORTED) {
@@ -1274,7 +1346,7 @@
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
- [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+ [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
}
@@ -1339,7 +1411,7 @@
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
- [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
+ [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
}
@@ -1553,6 +1625,9 @@
INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest,
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
&DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TtyModeAccessorPrimaryHidlTest);
TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) {
doc::test("Query and set the HAC state");
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index 8ef2b43..1a1dbea 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#pragma once
+
// Code in this file uses 'getCachedPolicyConfig'
#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
#error Must be included from AudioPrimaryHidlTest.h
@@ -46,32 +48,32 @@
}
// Cache result ?
- static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
+ static const std::vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
{8000, 11025, 16000, 22050, 32000, 44100},
{AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
+ static const std::vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
{24000, 48000}, {AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
+ static const std::vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
{AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
+ static const std::vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
{AudioFormat::PCM_16_BIT});
}
- static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
- vector<uint32_t> sampleRates,
- audio_format_t format) {
- vector<AudioConfig> configs;
+ static std::vector<AudioConfig> combineAudioConfig(
+ std::vector<audio_channel_mask_t> channelMasks, std::vector<uint32_t> sampleRates,
+ audio_format_t format) {
+ std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {
@@ -86,10 +88,10 @@
return configs;
}
- static vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
- vector<uint32_t> sampleRates,
- vector<AudioFormat> formats) {
- vector<AudioConfig> configs;
+ static std::vector<AudioConfig> combineAudioConfig(std::vector<AudioChannelMask> channelMasks,
+ std::vector<uint32_t> sampleRates,
+ std::vector<AudioFormat> formats) {
+ std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size() * formats.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index 0c0727f..6efed79 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-// Code in this file uses 'environment'
-#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
-#error Must be included from AudioPrimaryHidlTest.h
-#endif
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
template <class Derived, class Key, class Interface>
class InterfaceManager {
diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h
new file mode 100644
index 0000000..c9e0c0d
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/PolicyConfig.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h
+// and thus it doesn't have all '#include' and 'using' directives required
+// for a standalone compilation.
+
+#include <Serializer.h>
+
+struct PolicyConfigData {
+ android::HwModuleCollection hwModules;
+ android::DeviceVector availableOutputDevices;
+ android::DeviceVector availableInputDevices;
+ sp<android::DeviceDescriptor> defaultOutputDevice;
+};
+
+class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig {
+ public:
+ explicit PolicyConfig(const std::string& configFileName)
+ : android::AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
+ defaultOutputDevice),
+ mConfigFileName{configFileName} {
+ for (const auto& location : android::audio_get_configuration_paths()) {
+ std::string path = location + '/' + mConfigFileName;
+ if (access(path.c_str(), F_OK) == 0) {
+ mFilePath = path;
+ break;
+ }
+ }
+ mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
+ if (mStatus == OK) {
+ mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
+ // Available devices are not 'attached' to modules at this moment.
+ // Need to go over available devices and find their module.
+ for (const auto& device : availableOutputDevices) {
+ for (const auto& module : hwModules) {
+ if (module->getDeclaredDevices().indexOf(device) >= 0) {
+ mModulesWithDevicesNames.insert(module->getName());
+ break;
+ }
+ }
+ }
+ for (const auto& device : availableInputDevices) {
+ for (const auto& module : hwModules) {
+ if (module->getDeclaredDevices().indexOf(device) >= 0) {
+ mModulesWithDevicesNames.insert(module->getName());
+ break;
+ }
+ }
+ }
+ }
+ }
+ status_t getStatus() const { return mStatus; }
+ std::string getError() const {
+ if (mFilePath.empty()) {
+ return std::string{"Could not find "} + mConfigFileName +
+ " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
+ } else {
+ return "Invalid config file: " + mFilePath;
+ }
+ }
+ const std::string& getFilePath() const { return mFilePath; }
+ sp<const android::HwModule> getModuleFromName(const std::string& name) const {
+ return getHwModules().getModuleFromName(name.c_str());
+ }
+ sp<const android::HwModule> getPrimaryModule() const { return mPrimaryModule; }
+ const std::set<std::string>& getModulesWithDevicesNames() const {
+ return mModulesWithDevicesNames;
+ }
+ bool haveInputProfilesInModule(const std::string& name) const {
+ auto module = getModuleFromName(name);
+ return module && !module->getInputProfiles().empty();
+ }
+
+ private:
+ const std::string mConfigFileName;
+ status_t mStatus = NO_INIT;
+ std::string mFilePath;
+ sp<const android::HwModule> mPrimaryModule = nullptr;
+ std::set<std::string> mModulesWithDevicesNames;
+};
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
new file mode 100644
index 0000000..6635f31
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalAudioV7_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalAudioV7_0TargetTest->/data/local/tmp/VtsHalAudioV7_0TargetTest" />
+ <option name="push" value="audio_policy_configuration_V7_0.xsd->/data/local/tmp/audio_policy_configuration_V7_0.xsd" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalAudioV7_0TargetTest" />
+ </test>
+</configuration>
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index 7b37260..a5a8b34 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -5,9 +5,6 @@
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
index 2242d6d..31f94ae 100644
--- a/audio/effect/4.0/Android.bp
+++ b/audio/effect/4.0/Android.bp
@@ -5,9 +5,6 @@
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/5.0/Android.bp b/audio/effect/5.0/Android.bp
index b7dad8d..a3081c6 100644
--- a/audio/effect/5.0/Android.bp
+++ b/audio/effect/5.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio.effect@5.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/6.0/Android.bp b/audio/effect/6.0/Android.bp
index b6184f3..de4bde7 100644
--- a/audio/effect/6.0/Android.bp
+++ b/audio/effect/6.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.audio.effect@6.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/7.0/Android.bp b/audio/effect/7.0/Android.bp
new file mode 100644
index 0000000..c113782
--- /dev/null
+++ b/audio/effect/7.0/Android.bp
@@ -0,0 +1,30 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.audio.effect@7.0",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IAcousticEchoCancelerEffect.hal",
+ "IAutomaticGainControlEffect.hal",
+ "IBassBoostEffect.hal",
+ "IDownmixEffect.hal",
+ "IEffect.hal",
+ "IEffectBufferProviderCallback.hal",
+ "IEffectsFactory.hal",
+ "IEnvironmentalReverbEffect.hal",
+ "IEqualizerEffect.hal",
+ "ILoudnessEnhancerEffect.hal",
+ "INoiseSuppressionEffect.hal",
+ "IPresetReverbEffect.hal",
+ "IVirtualizerEffect.hal",
+ "IVisualizerEffect.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@7.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
diff --git a/audio/effect/7.0/IAcousticEchoCancelerEffect.hal b/audio/effect/7.0/IAcousticEchoCancelerEffect.hal
new file mode 100644
index 0000000..2bc2a7f
--- /dev/null
+++ b/audio/effect/7.0/IAcousticEchoCancelerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IAcousticEchoCancelerEffect extends IEffect {
+ /**
+ * Sets echo delay value in milliseconds.
+ */
+ setEchoDelay(uint32_t echoDelayMs) generates (Result retval);
+
+ /**
+ * Gets echo delay value in milliseconds.
+ */
+ getEchoDelay() generates (Result retval, uint32_t echoDelayMs);
+};
diff --git a/audio/effect/7.0/IAutomaticGainControlEffect.hal b/audio/effect/7.0/IAutomaticGainControlEffect.hal
new file mode 100644
index 0000000..8ffa659
--- /dev/null
+++ b/audio/effect/7.0/IAutomaticGainControlEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IAutomaticGainControlEffect extends IEffect {
+ /**
+ * Sets target level in millibels.
+ */
+ setTargetLevel(int16_t targetLevelMb) generates (Result retval);
+
+ /**
+ * Gets target level.
+ */
+ getTargetLevel() generates (Result retval, int16_t targetLevelMb);
+
+ /**
+ * Sets gain in the compression range in millibels.
+ */
+ setCompGain(int16_t compGainMb) generates (Result retval);
+
+ /**
+ * Gets gain in the compression range.
+ */
+ getCompGain() generates (Result retval, int16_t compGainMb);
+
+ /**
+ * Enables or disables limiter.
+ */
+ setLimiterEnabled(bool enabled) generates (Result retval);
+
+ /**
+ * Returns whether limiter is enabled.
+ */
+ isLimiterEnabled() generates (Result retval, bool enabled);
+
+ struct AllProperties {
+ int16_t targetLevelMb;
+ int16_t compGainMb;
+ bool limiterEnabled;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/7.0/IBassBoostEffect.hal b/audio/effect/7.0/IBassBoostEffect.hal
new file mode 100644
index 0000000..d8d049e
--- /dev/null
+++ b/audio/effect/7.0/IBassBoostEffect.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IBassBoostEffect extends IEffect {
+ /**
+ * Returns whether setting bass boost strength is supported.
+ */
+ isStrengthSupported() generates (Result retval, bool strengthSupported);
+
+ enum StrengthRange : uint16_t {
+ MIN = 0,
+ MAX = 1000
+ };
+
+ /**
+ * Sets bass boost strength.
+ *
+ * @param strength strength of the effect. The valid range for strength
+ * strength is [0, 1000], where 0 per mille designates the
+ * mildest effect and 1000 per mille designates the
+ * strongest.
+ * @return retval operation completion status.
+ */
+ setStrength(uint16_t strength) generates (Result retval);
+
+ /**
+ * Gets virtualization strength.
+ */
+ getStrength() generates (Result retval, uint16_t strength);
+};
diff --git a/audio/effect/7.0/IDownmixEffect.hal b/audio/effect/7.0/IDownmixEffect.hal
new file mode 100644
index 0000000..2035430
--- /dev/null
+++ b/audio/effect/7.0/IDownmixEffect.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IDownmixEffect extends IEffect {
+ enum Type : int32_t {
+ STRIP, // throw away the extra channels
+ FOLD // mix the extra channels with FL/FR
+ };
+
+ /**
+ * Sets the current downmix preset.
+ */
+ setType(Type preset) generates (Result retval);
+
+ /**
+ * Gets the current downmix preset.
+ */
+ getType() generates (Result retval, Type preset);
+};
diff --git a/audio/effect/7.0/IEffect.hal b/audio/effect/7.0/IEffect.hal
new file mode 100644
index 0000000..aa94f6d
--- /dev/null
+++ b/audio/effect/7.0/IEffect.hal
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffectBufferProviderCallback;
+
+interface IEffect {
+ /**
+ * Initialize effect engine--all configurations return to default.
+ *
+ * @return retval operation completion status.
+ */
+ @entry
+ init() generates (Result retval);
+
+ /**
+ * Apply new audio parameters configurations for input and output buffers.
+ * The provider callbacks may be empty, but in this case the buffer
+ * must be provided in the EffectConfig structure.
+ *
+ * @param config configuration descriptor.
+ * @param inputBufferProvider optional buffer provider reference.
+ * @param outputBufferProvider optional buffer provider reference.
+ * @return retval operation completion status.
+ */
+ setConfig(EffectConfig config,
+ IEffectBufferProviderCallback inputBufferProvider,
+ IEffectBufferProviderCallback outputBufferProvider)
+ generates (Result retval);
+
+ /**
+ * Reset the effect engine. Keep configuration but resets state and buffer
+ * content.
+ *
+ * @return retval operation completion status.
+ */
+ reset() generates (Result retval);
+
+ /**
+ * Enable processing.
+ *
+ * @return retval operation completion status.
+ */
+ enable() generates (Result retval);
+
+ /**
+ * Disable processing.
+ *
+ * @return retval operation completion status.
+ */
+ disable() generates (Result retval);
+
+ /**
+ * Set the rendering device the audio output path is connected to. The
+ * effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its
+ * descriptor to receive this command when the device changes.
+ *
+ * Note: this method is only supported for effects inserted into
+ * the output chain.
+ *
+ * @param device output device specification.
+ * @return retval operation completion status.
+ */
+ setDevice(DeviceAddress device) generates (Result retval);
+
+ /**
+ * Set and get volume. Used by audio framework to delegate volume control to
+ * effect engine. The effect implementation must set EFFECT_FLAG_VOLUME_CTRL
+ * flag in its descriptor to receive this command. The effect engine must
+ * return the volume that should be applied before the effect is
+ * processed. The overall volume (the volume actually applied by the effect
+ * engine multiplied by the returned value) should match the value indicated
+ * in the command.
+ *
+ * @param volumes vector containing volume for each channel defined in
+ * EffectConfig for output buffer expressed in 8.24 fixed
+ * point format.
+ * @return result updated volume values.
+ * @return retval operation completion status.
+ */
+ setAndGetVolume(vec<uint32_t> volumes)
+ generates (Result retval, vec<uint32_t> result);
+
+ /**
+ * Notify the effect of the volume change. The effect implementation must
+ * set EFFECT_FLAG_VOLUME_IND flag in its descriptor to receive this
+ * command.
+ *
+ * @param volumes vector containing volume for each channel defined in
+ * EffectConfig for output buffer expressed in 8.24 fixed
+ * point format.
+ * @return retval operation completion status.
+ */
+ volumeChangeNotification(vec<uint32_t> volumes)
+ generates (Result retval);
+
+ /**
+ * Set the audio mode. The effect implementation must set
+ * EFFECT_FLAG_AUDIO_MODE_IND flag in its descriptor to receive this command
+ * when the audio mode changes.
+ *
+ * @param mode desired audio mode.
+ * @return retval operation completion status.
+ */
+ setAudioMode(AudioMode mode) generates (Result retval);
+
+ /**
+ * Apply new audio parameters configurations for input and output buffers of
+ * reverse stream. An example of reverse stream is the echo reference
+ * supplied to an Acoustic Echo Canceler.
+ *
+ * @param config configuration descriptor.
+ * @param inputBufferProvider optional buffer provider reference.
+ * @param outputBufferProvider optional buffer provider reference.
+ * @return retval operation completion status.
+ */
+ setConfigReverse(EffectConfig config,
+ IEffectBufferProviderCallback inputBufferProvider,
+ IEffectBufferProviderCallback outputBufferProvider)
+ generates (Result retval);
+
+ /**
+ * Set the capture device the audio input path is connected to. The effect
+ * implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to
+ * receive this command when the device changes.
+ *
+ * Note: this method is only supported for effects inserted into
+ * the input chain.
+ *
+ * @param device input device specification.
+ * @return retval operation completion status.
+ */
+ setInputDevice(DeviceAddress device) generates (Result retval);
+
+ /**
+ * Read audio parameters configurations for input and output buffers.
+ *
+ * @return retval operation completion status.
+ * @return config configuration descriptor.
+ */
+ getConfig() generates (Result retval, EffectConfig config);
+
+ /**
+ * Read audio parameters configurations for input and output buffers of
+ * reverse stream.
+ *
+ * @return retval operation completion status.
+ * @return config configuration descriptor.
+ */
+ getConfigReverse() generates (Result retval, EffectConfig config);
+
+ /**
+ * Queries for supported combinations of main and auxiliary channels
+ * (e.g. for a multi-microphone noise suppressor).
+ *
+ * @param maxConfigs maximum number of the combinations to return.
+ * @return retval absence of the feature support is indicated using
+ * NOT_SUPPORTED code. RESULT_TOO_BIG is returned if
+ * the number of supported combinations exceeds 'maxConfigs'.
+ * @return result list of configuration descriptors.
+ */
+ getSupportedAuxChannelsConfigs(uint32_t maxConfigs)
+ generates (Result retval, vec<EffectAuxChannelsConfig> result);
+
+ /**
+ * Retrieves the current configuration of main and auxiliary channels.
+ *
+ * @return retval absence of the feature support is indicated using
+ * NOT_SUPPORTED code.
+ * @return result configuration descriptor.
+ */
+ getAuxChannelsConfig()
+ generates (Result retval, EffectAuxChannelsConfig result);
+
+ /**
+ * Sets the current configuration of main and auxiliary channels.
+ *
+ * @return retval operation completion status; absence of the feature
+ * support is indicated using NOT_SUPPORTED code.
+ */
+ setAuxChannelsConfig(EffectAuxChannelsConfig config)
+ generates (Result retval);
+
+ /**
+ * Set the audio source the capture path is configured for (Camcorder, voice
+ * recognition...).
+ *
+ * Note: this method is only supported for effects inserted into
+ * the input chain.
+ *
+ * @param source source descriptor.
+ * @return retval operation completion status.
+ */
+ setAudioSource(AudioSource source) generates (Result retval);
+
+ /**
+ * This command indicates if the playback thread the effect is attached to
+ * is offloaded or not, and updates the I/O handle of the playback thread
+ * the effect is attached to.
+ *
+ * @param param effect offload descriptor.
+ * @return retval operation completion status.
+ */
+ offload(EffectOffloadParameter param) generates (Result retval);
+
+ /**
+ * Returns the effect descriptor.
+ *
+ * @return retval operation completion status.
+ * @return descriptor effect descriptor.
+ */
+ getDescriptor() generates (Result retval, EffectDescriptor descriptor);
+
+ /**
+ * Set up required transports for passing audio buffers to the effect.
+ *
+ * The transport consists of shared memory and a message queue for reporting
+ * effect processing operation status. The shared memory is set up
+ * separately using 'setProcessBuffers' method.
+ *
+ * Processing is requested by setting 'REQUEST_PROCESS' or
+ * 'REQUEST_PROCESS_REVERSE' EventFlags associated with the status message
+ * queue. The result of processing may be one of the following:
+ * OK if there were no errors during processing;
+ * INVALID_ARGUMENTS if audio buffers are invalid;
+ * INVALID_STATE if the engine has finished the disable phase;
+ * NOT_INITIALIZED if the audio buffers were not set;
+ * NOT_SUPPORTED if the requested processing type is not supported by
+ * the effect.
+ *
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queue.
+ * @return statusMQ a message queue used for passing status from the effect.
+ */
+ prepareForProcessing() generates (Result retval, fmq_sync<Result> statusMQ);
+
+ /**
+ * Set up input and output buffers for processing audio data. The effect
+ * may modify both the input and the output buffer during the operation.
+ * Buffers may be set multiple times during effect lifetime.
+ *
+ * The input and the output buffer may be reused between different effects,
+ * and the input buffer may be used as an output buffer. Buffers are
+ * distinguished using 'AudioBuffer.id' field.
+ *
+ * @param inBuffer input audio buffer.
+ * @param outBuffer output audio buffer.
+ * @return retval OK if both buffers were mapped successfully.
+ * INVALID_ARGUMENTS if there was a problem with mapping
+ * any of the buffers.
+ */
+ setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer)
+ generates (Result retval);
+
+ /**
+ * Execute a vendor specific command on the effect. The command code
+ * and data, as well as result data are not interpreted by Android
+ * Framework and are passed as-is between the application and the effect.
+ *
+ * The effect must use standard POSIX.1-2001 error codes for the operation
+ * completion status.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param commandId the ID of the command.
+ * @param data command data.
+ * @param resultMaxSize maximum size in bytes of the result; can be 0.
+ * @return status command completion status.
+ * @return result result data.
+ */
+ command(uint32_t commandId, vec<uint8_t> data, uint32_t resultMaxSize)
+ generates (int32_t status, vec<uint8_t> result);
+
+ /**
+ * Set a vendor-specific parameter and apply it immediately. The parameter
+ * code and data are not interpreted by Android Framework and are passed
+ * as-is between the application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+ * unknown or if provided parameter data is invalid. If the effect does not
+ * support setting vendor-specific parameters, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param parameter identifying data of the parameter.
+ * @param value the value of the parameter.
+ * @return retval operation completion status.
+ */
+ setParameter(vec<uint8_t> parameter, vec<uint8_t> value)
+ generates (Result retval);
+
+ /**
+ * Get a vendor-specific parameter value. The parameter code and returned
+ * data are not interpreted by Android Framework and are passed as-is
+ * between the application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+ * unknown. If the effect does not support setting vendor-specific
+ * parameters, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param parameter identifying data of the parameter.
+ * @param valueMaxSize maximum size in bytes of the value.
+ * @return retval operation completion status.
+ * @return result the value of the parameter.
+ */
+ getParameter(vec<uint8_t> parameter, uint32_t valueMaxSize)
+ generates (Result retval, vec<uint8_t> value);
+
+ /**
+ * Get supported configs for a vendor-specific feature. The configs returned
+ * are not interpreted by Android Framework and are passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific feature
+ * configs, it must return NOT_SUPPORTED. If the feature is supported but
+ * the total number of supported configurations exceeds the maximum number
+ * indicated by the caller, the method must return RESULT_TOO_BIG.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param maxConfigs maximum number of configs to return.
+ * @param configSize size of each config in bytes.
+ * @return retval operation completion status.
+ * @return configsCount number of configs returned.
+ * @return configsData data for all the configs returned.
+ */
+ getSupportedConfigsForFeature(
+ uint32_t featureId,
+ uint32_t maxConfigs,
+ uint32_t configSize) generates (
+ Result retval,
+ uint32_t configsCount,
+ vec<uint8_t> configsData);
+
+ /**
+ * Get the current config for a vendor-specific feature. The config returned
+ * is not interpreted by Android Framework and is passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific
+ * feature configs, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param configSize size of the config in bytes.
+ * @return retval operation completion status.
+ * @return configData config data.
+ */
+ getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize)
+ generates (Result retval, vec<uint8_t> configData);
+
+ /**
+ * Set the current config for a vendor-specific feature. The config data
+ * is not interpreted by Android Framework and is passed as-is between the
+ * application and the effect.
+ *
+ * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+ * unknown. If the effect does not support getting vendor-specific
+ * feature configs, it must return NOT_SUPPORTED.
+ *
+ * Use this method only if the effect is provided by a third party, and
+ * there is no interface defined for it. This method only works for effects
+ * implemented in software.
+ *
+ * @param featureId feature identifier.
+ * @param configData config data.
+ * @return retval operation completion status.
+ */
+ setCurrentConfigForFeature(uint32_t featureId, vec<uint8_t> configData)
+ generates (Result retval);
+
+ /**
+ * Called by the framework to deinitialize the effect and free up
+ * all currently allocated resources. It is recommended to close
+ * the effect on the client side as soon as it is becomes unused.
+ *
+ * The client must ensure that this function is not called while
+ * audio data is being transferred through the effect's message queues.
+ *
+ * @return retval OK in case the success.
+ * INVALID_STATE if the effect was already closed.
+ */
+ close() generates (Result retval);
+};
diff --git a/audio/effect/7.0/IEffectBufferProviderCallback.hal b/audio/effect/7.0/IEffectBufferProviderCallback.hal
new file mode 100644
index 0000000..d18f7df
--- /dev/null
+++ b/audio/effect/7.0/IEffectBufferProviderCallback.hal
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+/**
+ * This callback interface contains functions that can be used by the effect
+ * engine 'process' function to exchange input and output audio buffers.
+ */
+interface IEffectBufferProviderCallback {
+ /**
+ * Called to retrieve a buffer where data should read from by 'process'
+ * function.
+ *
+ * @return buffer audio buffer for processing
+ */
+ getBuffer() generates (AudioBuffer buffer);
+
+ /**
+ * Called to provide a buffer with the data written by 'process' function.
+ *
+ * @param buffer audio buffer for processing
+ */
+ putBuffer(AudioBuffer buffer);
+};
diff --git a/audio/effect/7.0/IEffectsFactory.hal b/audio/effect/7.0/IEffectsFactory.hal
new file mode 100644
index 0000000..337251c
--- /dev/null
+++ b/audio/effect/7.0/IEffectsFactory.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IEffectsFactory {
+ /**
+ * Returns descriptors of different effects in all loaded libraries.
+ *
+ * @return retval operation completion status.
+ * @return result list of effect descriptors.
+ */
+ getAllDescriptors() generates(Result retval, vec<EffectDescriptor> result);
+
+ /**
+ * Returns a descriptor of a particular effect.
+ *
+ * @return retval operation completion status.
+ * @return result effect descriptor.
+ */
+ getDescriptor(Uuid uid) generates(Result retval, EffectDescriptor result);
+
+ /**
+ * Creates an effect engine of the specified type. To release the effect
+ * engine, it is necessary to release references to the returned effect
+ * object.
+ *
+ * @param uid effect uuid.
+ * @param session audio session to which this effect instance will be
+ * attached. All effects created with the same session ID
+ * are connected in series and process the same signal
+ * stream.
+ * @param ioHandle identifies the output or input stream this effect is
+ * directed to in audio HAL.
+ * @param device identifies the sink or source device this effect is directed to in the
+ * audio HAL. Must be specified if session is AudioSessionConsts.DEVICE.
+ * "device" is the AudioPortHandle used for the device when the audio
+ * patch is created at the audio HAL.
+ * @return retval operation completion status.
+ * @return result the interface for the created effect.
+ * @return effectId the unique ID of the effect to be used with
+ * IStream::addEffect and IStream::removeEffect methods.
+ */
+ createEffect(Uuid uid, AudioSession session, AudioIoHandle ioHandle, AudioPortHandle device)
+ generates (Result retval, IEffect result, uint64_t effectId);
+};
diff --git a/audio/effect/7.0/IEnvironmentalReverbEffect.hal b/audio/effect/7.0/IEnvironmentalReverbEffect.hal
new file mode 100644
index 0000000..e02cfbc
--- /dev/null
+++ b/audio/effect/7.0/IEnvironmentalReverbEffect.hal
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IEnvironmentalReverbEffect extends IEffect {
+ /**
+ * Sets whether the effect should be bypassed.
+ */
+ setBypass(bool bypass) generates (Result retval);
+
+ /**
+ * Gets whether the effect should be bypassed.
+ */
+ getBypass() generates (Result retval, bool bypass);
+
+ enum ParamRange : int16_t {
+ ROOM_LEVEL_MIN = -6000,
+ ROOM_LEVEL_MAX = 0,
+ ROOM_HF_LEVEL_MIN = -4000,
+ ROOM_HF_LEVEL_MAX = 0,
+ DECAY_TIME_MIN = 100,
+ DECAY_TIME_MAX = 20000,
+ DECAY_HF_RATIO_MIN = 100,
+ DECAY_HF_RATIO_MAX = 1000,
+ REFLECTIONS_LEVEL_MIN = -6000,
+ REFLECTIONS_LEVEL_MAX = 0,
+ REFLECTIONS_DELAY_MIN = 0,
+ REFLECTIONS_DELAY_MAX = 65,
+ REVERB_LEVEL_MIN = -6000,
+ REVERB_LEVEL_MAX = 0,
+ REVERB_DELAY_MIN = 0,
+ REVERB_DELAY_MAX = 65,
+ DIFFUSION_MIN = 0,
+ DIFFUSION_MAX = 1000,
+ DENSITY_MIN = 0,
+ DENSITY_MAX = 1000
+ };
+
+ /**
+ * Sets the room level.
+ */
+ setRoomLevel(int16_t roomLevel) generates (Result retval);
+
+ /**
+ * Gets the room level.
+ */
+ getRoomLevel() generates (Result retval, int16_t roomLevel);
+
+ /**
+ * Sets the room high frequencies level.
+ */
+ setRoomHfLevel(int16_t roomHfLevel) generates (Result retval);
+
+ /**
+ * Gets the room high frequencies level.
+ */
+ getRoomHfLevel() generates (Result retval, int16_t roomHfLevel);
+
+ /**
+ * Sets the room decay time.
+ */
+ setDecayTime(uint32_t decayTime) generates (Result retval);
+
+ /**
+ * Gets the room decay time.
+ */
+ getDecayTime() generates (Result retval, uint32_t decayTime);
+
+ /**
+ * Sets the ratio of high frequencies decay.
+ */
+ setDecayHfRatio(int16_t decayHfRatio) generates (Result retval);
+
+ /**
+ * Gets the ratio of high frequencies decay.
+ */
+ getDecayHfRatio() generates (Result retval, int16_t decayHfRatio);
+
+ /**
+ * Sets the level of reflections in the room.
+ */
+ setReflectionsLevel(int16_t reflectionsLevel) generates (Result retval);
+
+ /**
+ * Gets the level of reflections in the room.
+ */
+ getReflectionsLevel() generates (Result retval, int16_t reflectionsLevel);
+
+ /**
+ * Sets the reflections delay in the room.
+ */
+ setReflectionsDelay(uint32_t reflectionsDelay) generates (Result retval);
+
+ /**
+ * Gets the reflections delay in the room.
+ */
+ getReflectionsDelay() generates (Result retval, uint32_t reflectionsDelay);
+
+ /**
+ * Sets the reverb level of the room.
+ */
+ setReverbLevel(int16_t reverbLevel) generates (Result retval);
+
+ /**
+ * Gets the reverb level of the room.
+ */
+ getReverbLevel() generates (Result retval, int16_t reverbLevel);
+
+ /**
+ * Sets the reverb delay of the room.
+ */
+ setReverbDelay(uint32_t reverDelay) generates (Result retval);
+
+ /**
+ * Gets the reverb delay of the room.
+ */
+ getReverbDelay() generates (Result retval, uint32_t reverbDelay);
+
+ /**
+ * Sets room diffusion.
+ */
+ setDiffusion(int16_t diffusion) generates (Result retval);
+
+ /**
+ * Gets room diffusion.
+ */
+ getDiffusion() generates (Result retval, int16_t diffusion);
+
+ /**
+ * Sets room wall density.
+ */
+ setDensity(int16_t density) generates (Result retval);
+
+ /**
+ * Gets room wall density.
+ */
+ getDensity() generates (Result retval, int16_t density);
+
+ struct AllProperties {
+ int16_t roomLevel; // in millibels, range -6000 to 0
+ int16_t roomHfLevel; // in millibels, range -4000 to 0
+ uint32_t decayTime; // in milliseconds, range 100 to 20000
+ int16_t decayHfRatio; // in permilles, range 100 to 1000
+ int16_t reflectionsLevel; // in millibels, range -6000 to 0
+ uint32_t reflectionsDelay; // in milliseconds, range 0 to 65
+ int16_t reverbLevel; // in millibels, range -6000 to 0
+ uint32_t reverbDelay; // in milliseconds, range 0 to 65
+ int16_t diffusion; // in permilles, range 0 to 1000
+ int16_t density; // in permilles, range 0 to 1000
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/7.0/IEqualizerEffect.hal b/audio/effect/7.0/IEqualizerEffect.hal
new file mode 100644
index 0000000..e7d7ae1
--- /dev/null
+++ b/audio/effect/7.0/IEqualizerEffect.hal
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IEqualizerEffect extends IEffect {
+ /**
+ * Gets the number of frequency bands that the equalizer supports.
+ */
+ getNumBands() generates (Result retval, uint16_t numBands);
+
+ /**
+ * Returns the minimum and maximum band levels supported.
+ */
+ getLevelRange()
+ generates (Result retval, int16_t minLevel, int16_t maxLevel);
+
+ /**
+ * Sets the gain for the given equalizer band.
+ */
+ setBandLevel(uint16_t band, int16_t level) generates (Result retval);
+
+ /**
+ * Gets the gain for the given equalizer band.
+ */
+ getBandLevel(uint16_t band) generates (Result retval, int16_t level);
+
+ /**
+ * Gets the center frequency of the given band, in milliHertz.
+ */
+ getBandCenterFrequency(uint16_t band)
+ generates (Result retval, uint32_t centerFreqmHz);
+
+ /**
+ * Gets the frequency range of the given frequency band, in milliHertz.
+ */
+ getBandFrequencyRange(uint16_t band)
+ generates (Result retval, uint32_t minFreqmHz, uint32_t maxFreqmHz);
+
+ /**
+ * Gets the band that has the most effect on the given frequency
+ * in milliHertz.
+ */
+ getBandForFrequency(uint32_t freqmHz)
+ generates (Result retval, uint16_t band);
+
+ /**
+ * Gets the names of all presets the equalizer supports.
+ */
+ getPresetNames() generates (Result retval, vec<string> names);
+
+ /**
+ * Sets the current preset using the index of the preset in the names
+ * vector returned via 'getPresetNames'.
+ */
+ setCurrentPreset(uint16_t preset) generates (Result retval);
+
+ /**
+ * Gets the current preset.
+ */
+ getCurrentPreset() generates (Result retval, uint16_t preset);
+
+ struct AllProperties {
+ uint16_t curPreset;
+ vec<int16_t> bandLevels;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/7.0/ILoudnessEnhancerEffect.hal b/audio/effect/7.0/ILoudnessEnhancerEffect.hal
new file mode 100644
index 0000000..0304f20
--- /dev/null
+++ b/audio/effect/7.0/ILoudnessEnhancerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface ILoudnessEnhancerEffect extends IEffect {
+ /**
+ * Sets target gain expressed in millibels.
+ */
+ setTargetGain(int32_t targetGainMb) generates (Result retval);
+
+ /**
+ * Gets target gain expressed in millibels.
+ */
+ getTargetGain() generates (Result retval, int32_t targetGainMb);
+};
diff --git a/audio/effect/7.0/INoiseSuppressionEffect.hal b/audio/effect/7.0/INoiseSuppressionEffect.hal
new file mode 100644
index 0000000..2c6210c
--- /dev/null
+++ b/audio/effect/7.0/INoiseSuppressionEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface INoiseSuppressionEffect extends IEffect {
+ enum Level : int32_t {
+ LOW,
+ MEDIUM,
+ HIGH
+ };
+
+ /**
+ * Sets suppression level.
+ */
+ setSuppressionLevel(Level level) generates (Result retval);
+
+ /**
+ * Gets suppression level.
+ */
+ getSuppressionLevel() generates (Result retval, Level level);
+
+ enum Type : int32_t {
+ SINGLE_CHANNEL,
+ MULTI_CHANNEL
+ };
+
+ /**
+ * Set suppression type.
+ */
+ setSuppressionType(Type type) generates (Result retval);
+
+ /**
+ * Get suppression type.
+ */
+ getSuppressionType() generates (Result retval, Type type);
+
+ struct AllProperties {
+ Level level;
+ Type type;
+ };
+
+ /**
+ * Sets all properties at once.
+ */
+ setAllProperties(AllProperties properties) generates (Result retval);
+
+ /**
+ * Gets all properties at once.
+ */
+ getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/7.0/IPresetReverbEffect.hal b/audio/effect/7.0/IPresetReverbEffect.hal
new file mode 100644
index 0000000..da61d24
--- /dev/null
+++ b/audio/effect/7.0/IPresetReverbEffect.hal
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IPresetReverbEffect extends IEffect {
+ enum Preset : int32_t {
+ NONE, // no reverb or reflections
+ SMALLROOM, // a small room less than five meters in length
+ MEDIUMROOM, // a medium room with a length of ten meters or less
+ LARGEROOM, // a large-sized room suitable for live performances
+ MEDIUMHALL, // a medium-sized hall
+ LARGEHALL, // a large-sized hall suitable for a full orchestra
+ PLATE, // synthesis of the traditional plate reverb
+ LAST = PLATE
+ };
+
+ /**
+ * Sets the current preset.
+ */
+ setPreset(Preset preset) generates (Result retval);
+
+ /**
+ * Gets the current preset.
+ */
+ getPreset() generates (Result retval, Preset preset);
+};
diff --git a/audio/effect/7.0/IVirtualizerEffect.hal b/audio/effect/7.0/IVirtualizerEffect.hal
new file mode 100644
index 0000000..141b4e6
--- /dev/null
+++ b/audio/effect/7.0/IVirtualizerEffect.hal
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IVirtualizerEffect extends IEffect {
+ /**
+ * Returns whether setting virtualization strength is supported.
+ */
+ isStrengthSupported() generates (bool strengthSupported);
+
+ enum StrengthRange : uint16_t {
+ MIN = 0,
+ MAX = 1000
+ };
+
+ /**
+ * Sets virtualization strength.
+ *
+ * @param strength strength of the effect. The valid range for strength
+ * strength is [0, 1000], where 0 per mille designates the
+ * mildest effect and 1000 per mille designates the
+ * strongest.
+ * @return retval operation completion status.
+ */
+ setStrength(uint16_t strength) generates (Result retval);
+
+ /**
+ * Gets virtualization strength.
+ */
+ getStrength() generates (Result retval, uint16_t strength);
+
+ struct SpeakerAngle {
+ /** Speaker channel mask */
+ vec<AudioChannelMask> mask;
+ // all angles are expressed in degrees and
+ // are relative to the listener.
+ int16_t azimuth; // 0 is the direction the listener faces
+ // 180 is behind the listener
+ // -90 is to their left
+ int16_t elevation; // 0 is the horizontal plane
+ // +90 is above the listener, -90 is below
+ };
+ /**
+ * Retrieves virtual speaker angles for the given channel mask on the
+ * specified device.
+ */
+ getVirtualSpeakerAngles(vec<AudioChannelMask> mask, DeviceAddress device)
+ generates (Result retval, vec<SpeakerAngle> speakerAngles);
+
+ /**
+ * Forces the virtualizer effect for the given output device.
+ */
+ forceVirtualizationMode(DeviceAddress device) generates (Result retval);
+
+ /**
+ * Returns audio device reflecting the current virtualization mode,
+ * Device type can be empty when not virtualizing.
+ */
+ getVirtualizationMode() generates (Result retval, DeviceAddress device);
+};
diff --git a/audio/effect/7.0/IVisualizerEffect.hal b/audio/effect/7.0/IVisualizerEffect.hal
new file mode 100644
index 0000000..b4e8659
--- /dev/null
+++ b/audio/effect/7.0/IVisualizerEffect.hal
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+import IEffect;
+
+interface IVisualizerEffect extends IEffect {
+ enum CaptureSizeRange : int32_t {
+ MAX = 1024, // maximum capture size in samples
+ MIN = 128 // minimum capture size in samples
+ };
+
+ /**
+ * Sets the number PCM samples in the capture.
+ */
+ setCaptureSize(uint16_t captureSize) generates (Result retval);
+
+ /**
+ * Gets the number PCM samples in the capture.
+ */
+ getCaptureSize() generates (Result retval, uint16_t captureSize);
+
+ enum ScalingMode : int32_t {
+ // Keep in sync with SCALING_MODE_... in
+ // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+ NORMALIZED = 0,
+ AS_PLAYED = 1
+ };
+
+ /**
+ * Specifies the way the captured data is scaled.
+ */
+ setScalingMode(ScalingMode scalingMode) generates (Result retval);
+
+ /**
+ * Retrieves the way the captured data is scaled.
+ */
+ getScalingMode() generates (Result retval, ScalingMode scalingMode);
+
+ /**
+ * Informs the visualizer about the downstream latency.
+ */
+ setLatency(uint32_t latencyMs) generates (Result retval);
+
+ /**
+ * Gets the downstream latency.
+ */
+ getLatency() generates (Result retval, uint32_t latencyMs);
+
+ enum MeasurementMode : int32_t {
+ // Keep in sync with MEASUREMENT_MODE_... in
+ // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+ NONE = 0x0,
+ PEAK_RMS = 0x1
+ };
+
+ /**
+ * Specifies which measurements are to be made.
+ */
+ setMeasurementMode(MeasurementMode measurementMode)
+ generates (Result retval);
+
+ /**
+ * Retrieves which measurements are to be made.
+ */
+ getMeasurementMode() generates (
+ Result retval, MeasurementMode measurementMode);
+
+ /**
+ * Retrieves the latest PCM snapshot captured by the visualizer engine. The
+ * number of samples to capture is specified by 'setCaptureSize' parameter.
+ *
+ * @return retval operation completion status.
+ * @return samples samples in 8 bit unsigned format (0 = 0x80)
+ */
+ capture() generates (Result retval, vec<uint8_t> samples);
+
+ struct Measurement {
+ MeasurementMode mode; // discriminator
+ union Values {
+ struct PeakAndRms {
+ int32_t peakMb; // millibels
+ int32_t rmsMb; // millibels
+ } peakAndRms;
+ } value;
+ };
+ /**
+ * Retrieves the latest measurements. The measurements to be made
+ * are specified by 'setMeasurementMode' parameter.
+ *
+ * @return retval operation completion status.
+ * @return result measurement.
+ */
+ measure() generates (Result retval, Measurement result);
+};
diff --git a/audio/effect/7.0/types.hal b/audio/effect/7.0/types.hal
new file mode 100644
index 0000000..fe4ee51
--- /dev/null
+++ b/audio/effect/7.0/types.hal
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect@7.0;
+
+import android.hardware.audio.common@7.0;
+
+enum Result : int32_t {
+ OK,
+ NOT_INITIALIZED,
+ INVALID_ARGUMENTS,
+ INVALID_STATE,
+ NOT_SUPPORTED,
+ RESULT_TOO_BIG
+};
+
+/**
+ * Effect engine capabilities/requirements flags.
+ *
+ * Definitions for flags field of effect descriptor.
+ *
+ * +----------------+--------+--------------------------------------------------
+ * | description | bits | values
+ * +----------------+--------+--------------------------------------------------
+ * | connection | 0..2 | 0 insert: after track process
+ * | mode | | 1 auxiliary: connect to track auxiliary
+ * | | | output and use send level
+ * | | | 2 replace: replaces track process function;
+ * | | | must implement SRC, volume and mono to stereo.
+ * | | | 3 pre processing: applied below audio HAL on in
+ * | | | 4 post processing: applied below audio HAL on out
+ * | | | 5 - 7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | insertion | 3..5 | 0 none
+ * | preference | | 1 first of the chain
+ * | | | 2 last of the chain
+ * | | | 3 exclusive (only effect in the insert chain)
+ * | | | 4..7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Volume | 6..8 | 0 none
+ * | management | | 1 implements volume control
+ * | | | 2 requires volume indication
+ * | | | 3 monitors requested volume
+ * | | | 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Device | 9..11 | 0 none
+ * | indication | | 1 requires device updates
+ * | | | 2, 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Sample input | 12..13 | 1 direct: process() function or
+ * | mode | | EFFECT_CMD_SET_CONFIG command must specify
+ * | | | a buffer descriptor
+ * | | | 2 provider: process() function uses the
+ * | | | bufferProvider indicated by the
+ * | | | EFFECT_CMD_SET_CONFIG command to request input.
+ * | | | buffers.
+ * | | | 3 both: both input modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Sample output | 14..15 | 1 direct: process() function or
+ * | mode | | EFFECT_CMD_SET_CONFIG command must specify
+ * | | | a buffer descriptor
+ * | | | 2 provider: process() function uses the
+ * | | | bufferProvider indicated by the
+ * | | | EFFECT_CMD_SET_CONFIG command to request output
+ * | | | buffers.
+ * | | | 3 both: both output modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Hardware | 16..17 | 0 No hardware acceleration
+ * | acceleration | | 1 non tunneled hw acceleration: the process()
+ * | | | function reads the samples, send them to HW
+ * | | | accelerated effect processor, reads back
+ * | | | the processed samples and returns them
+ * | | | to the output buffer.
+ * | | | 2 tunneled hw acceleration: the process()
+ * | | | function is transparent. The effect interface
+ * | | | is only used to control the effect engine.
+ * | | | This mode is relevant for global effects
+ * | | | actually applied by the audio hardware on
+ * | | | the output stream.
+ * +----------------+--------+--------------------------------------------------
+ * | Audio Mode | 18..19 | 0 none
+ * | indication | | 1 requires audio mode updates
+ * | | | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Audio source | 20..21 | 0 none
+ * | indication | | 1 requires audio source updates
+ * | | | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Effect offload | 22 | 0 The effect cannot be offloaded to an audio DSP
+ * | supported | | 1 The effect can be offloaded to an audio DSP
+ * +----------------+--------+--------------------------------------------------
+ * | Process | 23 | 0 The effect implements a process function.
+ * | function | | 1 The effect does not implement a process
+ * | not | | function: enabling the effect has no impact
+ * | implemented | | on latency or CPU load.
+ * | | | Effect implementations setting this flag do not
+ * | | | have to implement a process function.
+ * +----------------+--------+--------------------------------------------------
+ */
+@export(name="", value_prefix="EFFECT_FLAG_")
+enum EffectFlags : int32_t {
+ // Insert mode
+ TYPE_SHIFT = 0,
+ TYPE_SIZE = 3,
+ TYPE_MASK = ((1 << TYPE_SIZE) -1) << TYPE_SHIFT,
+ TYPE_INSERT = 0 << TYPE_SHIFT,
+ TYPE_AUXILIARY = 1 << TYPE_SHIFT,
+ TYPE_REPLACE = 2 << TYPE_SHIFT,
+ TYPE_PRE_PROC = 3 << TYPE_SHIFT,
+ TYPE_POST_PROC = 4 << TYPE_SHIFT,
+
+ // Insert preference
+ INSERT_SHIFT = TYPE_SHIFT + TYPE_SIZE,
+ INSERT_SIZE = 3,
+ INSERT_MASK = ((1 << INSERT_SIZE) -1) << INSERT_SHIFT,
+ INSERT_ANY = 0 << INSERT_SHIFT,
+ INSERT_FIRST = 1 << INSERT_SHIFT,
+ INSERT_LAST = 2 << INSERT_SHIFT,
+ INSERT_EXCLUSIVE = 3 << INSERT_SHIFT,
+
+ // Volume control
+ VOLUME_SHIFT = INSERT_SHIFT + INSERT_SIZE,
+ VOLUME_SIZE = 3,
+ VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT,
+ VOLUME_CTRL = 1 << VOLUME_SHIFT,
+ VOLUME_IND = 2 << VOLUME_SHIFT,
+ VOLUME_MONITOR = 3 << VOLUME_SHIFT,
+ VOLUME_NONE = 0 << VOLUME_SHIFT,
+
+ // Device indication
+ DEVICE_SHIFT = VOLUME_SHIFT + VOLUME_SIZE,
+ DEVICE_SIZE = 3,
+ DEVICE_MASK = ((1 << DEVICE_SIZE) -1) << DEVICE_SHIFT,
+ DEVICE_IND = 1 << DEVICE_SHIFT,
+ DEVICE_NONE = 0 << DEVICE_SHIFT,
+
+ // Sample input modes
+ INPUT_SHIFT = DEVICE_SHIFT + DEVICE_SIZE,
+ INPUT_SIZE = 2,
+ INPUT_MASK = ((1 << INPUT_SIZE) -1) << INPUT_SHIFT,
+ INPUT_DIRECT = 1 << INPUT_SHIFT,
+ INPUT_PROVIDER = 2 << INPUT_SHIFT,
+ INPUT_BOTH = 3 << INPUT_SHIFT,
+
+ // Sample output modes
+ OUTPUT_SHIFT = INPUT_SHIFT + INPUT_SIZE,
+ OUTPUT_SIZE = 2,
+ OUTPUT_MASK = ((1 << OUTPUT_SIZE) -1) << OUTPUT_SHIFT,
+ OUTPUT_DIRECT = 1 << OUTPUT_SHIFT,
+ OUTPUT_PROVIDER = 2 << OUTPUT_SHIFT,
+ OUTPUT_BOTH = 3 << OUTPUT_SHIFT,
+
+ // Hardware acceleration mode
+ HW_ACC_SHIFT = OUTPUT_SHIFT + OUTPUT_SIZE,
+ HW_ACC_SIZE = 2,
+ HW_ACC_MASK = ((1 << HW_ACC_SIZE) -1) << HW_ACC_SHIFT,
+ HW_ACC_SIMPLE = 1 << HW_ACC_SHIFT,
+ HW_ACC_TUNNEL = 2 << HW_ACC_SHIFT,
+
+ // Audio mode indication
+ AUDIO_MODE_SHIFT = HW_ACC_SHIFT + HW_ACC_SIZE,
+ AUDIO_MODE_SIZE = 2,
+ AUDIO_MODE_MASK = ((1 << AUDIO_MODE_SIZE) -1) << AUDIO_MODE_SHIFT,
+ AUDIO_MODE_IND = 1 << AUDIO_MODE_SHIFT,
+ AUDIO_MODE_NONE = 0 << AUDIO_MODE_SHIFT,
+
+ // Audio source indication
+ AUDIO_SOURCE_SHIFT = AUDIO_MODE_SHIFT + AUDIO_MODE_SIZE,
+ AUDIO_SOURCE_SIZE = 2,
+ AUDIO_SOURCE_MASK = ((1 << AUDIO_SOURCE_SIZE) -1) << AUDIO_SOURCE_SHIFT,
+ AUDIO_SOURCE_IND = 1 << AUDIO_SOURCE_SHIFT,
+ AUDIO_SOURCE_NONE = 0 << AUDIO_SOURCE_SHIFT,
+
+ // Effect offload indication
+ OFFLOAD_SHIFT = AUDIO_SOURCE_SHIFT + AUDIO_SOURCE_SIZE,
+ OFFLOAD_SIZE = 1,
+ OFFLOAD_MASK = ((1 << OFFLOAD_SIZE) -1) << OFFLOAD_SHIFT,
+ OFFLOAD_SUPPORTED = 1 << OFFLOAD_SHIFT,
+
+ // Effect has no process indication
+ NO_PROCESS_SHIFT = OFFLOAD_SHIFT + OFFLOAD_SIZE,
+ NO_PROCESS_SIZE = 1,
+ NO_PROCESS_MASK = ((1 << NO_PROCESS_SIZE) -1) << NO_PROCESS_SHIFT,
+ NO_PROCESS = 1 << NO_PROCESS_SHIFT
+};
+
+/**
+ * The effect descriptor contains necessary information to facilitate the
+ * enumeration of the effect engines present in a library.
+ */
+struct EffectDescriptor {
+ Uuid type; // UUID of to the OpenSL ES interface implemented
+ // by this effect
+ Uuid uuid; // UUID for this particular implementation
+ bitfield<EffectFlags> flags; // effect engine capabilities/requirements flags
+ uint16_t cpuLoad; // CPU load indication expressed in 0.1 MIPS units
+ // as estimated on an ARM9E core (ARMv5TE) with 0 WS
+ uint16_t memoryUsage; // data memory usage expressed in KB and includes
+ // only dynamically allocated memory
+ uint8_t[64] name; // human readable effect name
+ uint8_t[64] implementor; // human readable effect implementor name
+};
+
+/**
+ * A buffer is a chunk of audio data for processing. Multi-channel audio is
+ * always interleaved. The channel order is from LSB to MSB with regard to the
+ * channel mask definition in audio.h, audio_channel_mask_t, e.g.:
+ * Stereo: L, R; 5.1: FL, FR, FC, LFE, BL, BR.
+ *
+ * The buffer size is expressed in frame count, a frame being composed of
+ * samples for all channels at a given time. Frame size for unspecified format
+ * (AUDIO_FORMAT_OTHER) is 8 bit by definition.
+ */
+struct AudioBuffer {
+ uint64_t id;
+ uint32_t frameCount;
+ memory data;
+};
+
+@export(name="effect_buffer_access_e", value_prefix="EFFECT_BUFFER_")
+enum EffectBufferAccess : int32_t {
+ ACCESS_WRITE,
+ ACCESS_READ,
+ ACCESS_ACCUMULATE
+};
+
+/**
+ * Determines what fields of EffectBufferConfig need to be considered.
+ */
+@export(name="", value_prefix="EFFECT_CONFIG_")
+enum EffectConfigParameters : int32_t {
+ BUFFER = 0x0001, // buffer field
+ SMP_RATE = 0x0002, // samplingRate
+ CHANNELS = 0x0004, // channels
+ FORMAT = 0x0008, // format
+ ACC_MODE = 0x0010, // accessMode
+ // Note that the 2.0 ALL have been moved to an helper function
+};
+
+/**
+ * The buffer config structure specifies the input or output audio format
+ * to be used by the effect engine.
+ */
+struct EffectBufferConfig {
+ AudioBuffer buffer;
+ uint32_t samplingRateHz;
+ AudioChannelMask channels;
+ AudioFormat format;
+ EffectBufferAccess accessMode;
+ bitfield<EffectConfigParameters> mask;
+};
+
+struct EffectConfig {
+ EffectBufferConfig inputCfg;
+ EffectBufferConfig outputCfg;
+};
+
+@export(name="effect_feature_e", value_prefix="EFFECT_FEATURE_")
+enum EffectFeature : int32_t {
+ AUX_CHANNELS, // supports auxiliary channels
+ // (e.g. dual mic noise suppressor)
+ CNT
+};
+
+struct EffectAuxChannelsConfig {
+ vec<AudioChannelMask> mainChannels; // channel mask for main channels
+ vec<AudioChannelMask> auxChannels; // channel mask for auxiliary channels
+};
+
+struct EffectOffloadParameter {
+ bool isOffload; // true if the playback thread the effect
+ // is attached to is offloaded
+ AudioIoHandle ioHandle; // io handle of the playback thread
+ // the effect is attached to
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * the status message queue used by effects.
+ */
+enum MessageQueueFlagBits : uint32_t {
+ DONE_PROCESSING = 1 << 0,
+ REQUEST_PROCESS = 1 << 1,
+ REQUEST_PROCESS_REVERSE = 1 << 2,
+ REQUEST_QUIT = 1 << 3,
+ REQUEST_PROCESS_ALL =
+ REQUEST_PROCESS | REQUEST_PROCESS_REVERSE | REQUEST_QUIT
+};
diff --git a/audio/effect/7.0/xml/Android.bp b/audio/effect/7.0/xml/Android.bp
new file mode 100644
index 0000000..dc12e63
--- /dev/null
+++ b/audio/effect/7.0/xml/Android.bp
@@ -0,0 +1,5 @@
+xsd_config {
+ name: "audio_effects_conf_V7_0",
+ srcs: ["audio_effects_conf.xsd"],
+ package_name: "audio.effects.V7_0",
+}
diff --git a/audio/effect/7.0/xml/api/current.txt b/audio/effect/7.0/xml/api/current.txt
new file mode 100644
index 0000000..34cb541
--- /dev/null
+++ b/audio/effect/7.0/xml/api/current.txt
@@ -0,0 +1,208 @@
+// Signature format: 2.0
+package audio.effects.V7_0 {
+
+ public class AudioEffectsConf {
+ ctor public AudioEffectsConf();
+ method public audio.effects.V7_0.AudioEffectsConf.DeviceEffects getDeviceEffects();
+ method public audio.effects.V7_0.EffectsType getEffects();
+ method public audio.effects.V7_0.LibrariesType getLibraries();
+ method public audio.effects.V7_0.AudioEffectsConf.Postprocess getPostprocess();
+ method public audio.effects.V7_0.AudioEffectsConf.Preprocess getPreprocess();
+ method public audio.effects.V7_0.VersionType getVersion();
+ method public void setDeviceEffects(audio.effects.V7_0.AudioEffectsConf.DeviceEffects);
+ method public void setEffects(audio.effects.V7_0.EffectsType);
+ method public void setLibraries(audio.effects.V7_0.LibrariesType);
+ method public void setPostprocess(audio.effects.V7_0.AudioEffectsConf.Postprocess);
+ method public void setPreprocess(audio.effects.V7_0.AudioEffectsConf.Preprocess);
+ method public void setVersion(audio.effects.V7_0.VersionType);
+ }
+
+ public static class AudioEffectsConf.DeviceEffects {
+ ctor public AudioEffectsConf.DeviceEffects();
+ method public java.util.List<audio.effects.V7_0.DeviceProcessType> getDevicePort();
+ }
+
+ public static class AudioEffectsConf.Postprocess {
+ ctor public AudioEffectsConf.Postprocess();
+ method public java.util.List<audio.effects.V7_0.StreamPostprocessType> getStream();
+ }
+
+ public static class AudioEffectsConf.Preprocess {
+ ctor public AudioEffectsConf.Preprocess();
+ method public java.util.List<audio.effects.V7_0.StreamPreprocessType> getStream();
+ }
+
+ public class DeviceProcessType extends audio.effects.V7_0.StreamProcessingType {
+ ctor public DeviceProcessType();
+ method public String getAddress();
+ method public audio.effects.V7_0.DeviceType getType();
+ method public void setAddress(String);
+ method public void setType(audio.effects.V7_0.DeviceType);
+ }
+
+ public enum DeviceType {
+ method public String getRawName();
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_AUX_DIGITAL;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BACK_MIC;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BUILTIN_MIC;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_BUS;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_COMMUNICATION;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_ECHO_REFERENCE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_FM_TUNER;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_HDMI;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_HDMI_ARC;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_IP;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_LINE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_LOOPBACK;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_PROXY;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_SPDIF;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_TELEPHONY_RX;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_TV_TUNER;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_USB_ACCESSORY;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_USB_DEVICE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_USB_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_VOICE_CALL;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_IN_WIRED_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_AUX_LINE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_BUS;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_EARPIECE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_FM;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_HDMI;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_HDMI_ARC;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_HEARING_AID;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_IP;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_LINE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_PROXY;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_SPDIF;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_SPEAKER;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_TELEPHONY_TX;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_USB_DEVICE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_USB_HEADSET;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ enum_constant public static final audio.effects.V7_0.DeviceType AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ }
+
+ public class EffectImplType {
+ ctor public EffectImplType();
+ method public String getLibrary();
+ method public String getUuid();
+ method public void setLibrary(String);
+ method public void setUuid(String);
+ }
+
+ public class EffectProxyType extends audio.effects.V7_0.EffectType {
+ ctor public EffectProxyType();
+ method public audio.effects.V7_0.EffectImplType getLibhw();
+ method public audio.effects.V7_0.EffectImplType getLibsw();
+ method public void setLibhw(audio.effects.V7_0.EffectImplType);
+ method public void setLibsw(audio.effects.V7_0.EffectImplType);
+ }
+
+ public class EffectType extends audio.effects.V7_0.EffectImplType {
+ ctor public EffectType();
+ method public String getName();
+ method public void setName(String);
+ }
+
+ public class EffectsType {
+ ctor public EffectsType();
+ method public java.util.List<audio.effects.V7_0.EffectProxyType> getEffectProxy_optional();
+ method public java.util.List<audio.effects.V7_0.EffectType> getEffect_optional();
+ }
+
+ public class LibrariesType {
+ ctor public LibrariesType();
+ method public java.util.List<audio.effects.V7_0.LibrariesType.Library> getLibrary();
+ }
+
+ public static class LibrariesType.Library {
+ ctor public LibrariesType.Library();
+ method public String getName();
+ method public String getPath();
+ method public void setName(String);
+ method public void setPath(String);
+ }
+
+ public enum StreamInputType {
+ method public String getRawName();
+ enum_constant public static final audio.effects.V7_0.StreamInputType camcorder;
+ enum_constant public static final audio.effects.V7_0.StreamInputType echo_reference;
+ enum_constant public static final audio.effects.V7_0.StreamInputType fm_tuner;
+ enum_constant public static final audio.effects.V7_0.StreamInputType mic;
+ enum_constant public static final audio.effects.V7_0.StreamInputType unprocessed;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_call;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_communication;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_downlink;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_performance;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_recognition;
+ enum_constant public static final audio.effects.V7_0.StreamInputType voice_uplink;
+ }
+
+ public enum StreamOutputType {
+ method public String getRawName();
+ enum_constant public static final audio.effects.V7_0.StreamOutputType alarm;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType assistant;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType bluetooth_sco;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType dtmf;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType enforced_audible;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType music;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType notification;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType ring;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType system;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType tts;
+ enum_constant public static final audio.effects.V7_0.StreamOutputType voice_call;
+ }
+
+ public class StreamPostprocessType extends audio.effects.V7_0.StreamProcessingType {
+ ctor public StreamPostprocessType();
+ method public audio.effects.V7_0.StreamOutputType getType();
+ method public void setType(audio.effects.V7_0.StreamOutputType);
+ }
+
+ public class StreamPreprocessType extends audio.effects.V7_0.StreamProcessingType {
+ ctor public StreamPreprocessType();
+ method public audio.effects.V7_0.StreamInputType getType();
+ method public void setType(audio.effects.V7_0.StreamInputType);
+ }
+
+ public class StreamProcessingType {
+ ctor public StreamProcessingType();
+ method public java.util.List<audio.effects.V7_0.StreamProcessingType.Apply> getApply();
+ }
+
+ public static class StreamProcessingType.Apply {
+ ctor public StreamProcessingType.Apply();
+ method public String getEffect();
+ method public void setEffect(String);
+ }
+
+ public enum VersionType {
+ method public String getRawName();
+ enum_constant public static final audio.effects.V7_0.VersionType _2_0;
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static audio.effects.V7_0.AudioEffectsConf read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/tests/bar/1.0/.hidl_for_test b/audio/effect/7.0/xml/api/last_current.txt
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to audio/effect/7.0/xml/api/last_current.txt
diff --git a/tests/bar/1.0/.hidl_for_test b/audio/effect/7.0/xml/api/last_removed.txt
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to audio/effect/7.0/xml/api/last_removed.txt
diff --git a/audio/effect/7.0/xml/api/removed.txt b/audio/effect/7.0/xml/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/effect/7.0/xml/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/effect/7.0/xml/audio_effects_conf.xsd b/audio/effect/7.0/xml/audio_effects_conf.xsd
new file mode 100644
index 0000000..94f9f76
--- /dev/null
+++ b/audio/effect/7.0/xml/audio_effects_conf.xsd
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+ xmlns:aec="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+ elementFormDefault="qualified">
+ <!-- Simple types -->
+ <xs:simpleType name="versionType">
+ <xs:restriction base="xs:decimal">
+ <xs:enumeration value="2.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="uuidType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="streamInputType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mic"/>
+ <xs:enumeration value="voice_uplink"/>
+ <xs:enumeration value="voice_downlink"/>
+ <xs:enumeration value="voice_call"/>
+ <xs:enumeration value="camcorder"/>
+ <xs:enumeration value="voice_recognition"/>
+ <xs:enumeration value="voice_communication"/>
+ <xs:enumeration value="unprocessed"/>
+ <xs:enumeration value="voice_performance"/>
+ <xs:enumeration value="echo_reference"/>
+ <xs:enumeration value="fm_tuner"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="streamOutputType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="voice_call"/>
+ <xs:enumeration value="system"/>
+ <xs:enumeration value="ring"/>
+ <xs:enumeration value="music"/>
+ <xs:enumeration value="alarm"/>
+ <xs:enumeration value="notification"/>
+ <xs:enumeration value="bluetooth_sco"/>
+ <xs:enumeration value="enforced_audible"/>
+ <xs:enumeration value="dtmf"/>
+ <xs:enumeration value="tts"/>
+ <xs:enumeration value="assistant"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="relativePathType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[^/].*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="deviceType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+ <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+ <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Complex types -->
+ <xs:complexType name="librariesType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ List of effect libraries to load. Each library element must have "name" and
+ "path" attributes. The latter is giving the path of the library .so file
+ relative to the standard effect folders: /(vendor|odm|system)/lib(64)?/soundfx/
+ Example for a library in "/vendor/lib/soundfx/lib.so":
+ <library name="name" path="lib.so"/>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="library" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="path" type="aec:relativePathType" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="effectImplType">
+ <xs:attribute name="library" type="xs:string" use="required"/>
+ <xs:attribute name="uuid" type="aec:uuidType" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="effectType">
+ <xs:complexContent>
+ <xs:extension base="aec:effectImplType">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="effectProxyType">
+ <xs:complexContent>
+ <xs:extension base="aec:effectType">
+ <xs:sequence>
+ <xs:element name="libsw" type="aec:effectImplType"/>
+ <xs:element name="libhw" type="aec:effectImplType"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="effectsType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ List of effects to load. Each effect element must contain "name",
+ "library", and "uuid" attrs. The value of the "library" attr must
+ correspond to the name of a "library" element. The name of the effect
+ element is indicative, only the value of the "uuid" element designates
+ the effect for the audio framework. The uuid is the implementation
+ specific UUID as specified by the effect vendor. This is not the generic
+ effect type UUID.
+ For effect proxy implementations, SW and HW implementations of the effect
+ can be specified.
+ Example:
+ <effect name="name" library="lib" uuid="uuuu"/>
+ <effectProxy name="proxied" library="proxy" uuid="xxxx">
+ <libsw library="sw_bundle" uuid="yyyy"/>
+ <libhw library="offload_bundle" uuid="zzzz"/>
+ </effectProxy>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="effect" type="aec:effectType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="effectProxy" type="aec:effectProxyType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="streamProcessingType">
+ <xs:sequence>
+ <xs:element name="apply" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="effect" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="streamPreprocessType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio preprocessing configuration. The processing configuration consists
+ of a list of elements each describing processing settings for a given
+ input stream. Valid input stream types are listed in "streamInputType".
+ Each stream element contains a list of "apply" elements. The value of the
+ "effect" attr must correspond to the name of an "effect" element.
+ Example:
+ <stream type="voice_communication">
+ <apply effect="effect1"/>
+ <apply effect="effect2"/>
+ </stream>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="aec:streamProcessingType">
+ <xs:attribute name="type" type="aec:streamInputType" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="streamPostprocessType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio postprocessing configuration. The processing configuration consists
+ of a list of elements each describing processing settings for a given
+ output stream. Valid output stream types are listed in "streamOutputType".
+ Each stream element contains a list of "apply" elements. The value of the
+ "effect" attr must correspond to the name of an "effect" element.
+ Example:
+ <stream type="music">
+ <apply effect="effect1"/>
+ </stream>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="aec:streamProcessingType">
+ <xs:attribute name="type" type="aec:streamOutputType" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="deviceProcessType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio Device Effects configuration. The processing configuration consists
+ of a list of effects to be automatically added on a device Port when involved in an audio
+ patch.
+ Valid device type are listed in "deviceType" and shall be aligned.
+ Each stream element contains a list of "apply" elements. The value of the
+ "effect" attr must correspond to the name of an "effect" element.
+ Note that if the device is involved in a hardware patch, the effect must be hardware
+ accelerated.
+ Example:
+ <devicePort address="BUS00_USAGE_MAIN" type="AUDIO_DEVICE_OUT_BUS">
+ <apply effect="equalizer"/>
+ <apply effect="effect2"/>
+ </devicePort>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="aec:streamProcessingType">
+ <xs:attribute name="address" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="aec:deviceType" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <!-- Root element -->
+ <xs:element name="audio_effects_conf">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="libraries" type="aec:librariesType"/>
+ <xs:element name="effects" type="aec:effectsType"/>
+ <xs:element name="postprocess" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="stream" type="aec:streamPostprocessType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="preprocess" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="stream" type="aec:streamPreprocessType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="deviceEffects" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="devicePort" type="aec:deviceProcessType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="version" type="aec:versionType" use="required"/>
+ </xs:complexType>
+ <!-- Keys and references -->
+ <xs:key name="libraryName">
+ <xs:selector xpath="aec:libraries/aec:library"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:keyref name="libraryNameRef1" refer="aec:libraryName">
+ <xs:selector xpath="aec:effects/aec:effect"/>
+ <xs:field xpath="@library"/>
+ </xs:keyref>
+ <xs:keyref name="libraryNameRef2" refer="aec:libraryName">
+ <xs:selector xpath="aec:effects/aec:effect/aec:libsw"/>
+ <xs:field xpath="@library"/>
+ </xs:keyref>
+ <xs:keyref name="libraryNameRef3" refer="aec:libraryName">
+ <xs:selector xpath="aec:effects/aec:effect/aec:libhw"/>
+ <xs:field xpath="@library"/>
+ </xs:keyref>
+ <xs:key name="effectName">
+ <xs:selector xpath="aec:effects/aec:effect|aec:effects/aec:effectProxy"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:keyref name="effectNamePreRef" refer="aec:effectName">
+ <xs:selector xpath="aec:preprocess/aec:stream/aec:apply"/>
+ <xs:field xpath="@effect"/>
+ </xs:keyref>
+ <xs:keyref name="effectNamePostRef" refer="aec:effectName">
+ <xs:selector xpath="aec:postprocess/aec:stream/aec:apply"/>
+ <xs:field xpath="@effect"/>
+ </xs:keyref>
+ </xs:element>
+</xs:schema>
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index d9bb78b..1c3dc74 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -56,7 +56,7 @@
"-DMAJOR_VERSION=2",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -71,7 +71,7 @@
"-DMAJOR_VERSION=4",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -86,7 +86,7 @@
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -101,5 +101,21 @@
"-DMAJOR_VERSION=6",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
+}
+
+cc_library_shared {
+ enabled: false,
+ name: "android.hardware.audio.effect@7.0-impl",
+ defaults: ["android.hardware.audio.effect-impl_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.effect@7.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
}
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 309aa9d..f4a7283 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -19,7 +19,7 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"VtsHalAudioEffectTargetTest.cpp",
- "ValidateAudioEffectsConfiguration.cpp"
+ "ValidateAudioEffectsConfiguration.cpp",
],
static_libs: [
"android.hardware.audio.common.test.utility",
@@ -31,7 +31,10 @@
header_libs: [
"android.hardware.audio.common.util@all-versions",
],
- test_suites: ["general-tests", "vts"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
cc_test {
@@ -51,7 +54,7 @@
"-DMAJOR_VERSION=2",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_test {
@@ -71,7 +74,7 @@
"-DMAJOR_VERSION=4",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_test {
@@ -91,7 +94,7 @@
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_test {
@@ -111,5 +114,26 @@
"-DMAJOR_VERSION=6",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
+}
+
+cc_test {
+ name: "VtsHalAudioEffectV7_0TargetTest",
+ defaults: ["VtsHalAudioEffectTargetTest_default"],
+ // Use test_config for vts suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioEffectV7_0TargetTest.xml",
+ static_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.effect@7.0",
+ ],
+ data: [
+ ":audio_effects_conf_V7_0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
}
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 070242f..b64f105 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -16,7 +16,9 @@
#define LOG_TAG "AudioEffectHidlHalTest"
#include <android-base/logging.h>
+#if MAJOR_VERSION <= 6
#include <system/audio.h>
+#endif
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffect.h)
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
@@ -25,6 +27,10 @@
#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#if MAJOR_VERSION >= 7
+#include <audio_policy_configuration_V7_0-enums.h>
+#include <audio_policy_configuration_V7_0.h>
+#endif
#include <common/all-versions/VersionUtils.h>
@@ -45,6 +51,12 @@
using ::android::hidl::memory::V1_0::IMemory;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
+#if MAJOR_VERSION >= 7
+// Make an alias for enumerations generated from the APM config XSD.
+namespace xsd {
+using namespace ::audio::policy::configuration::CPP_VERSION;
+}
+#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@ -171,7 +183,7 @@
effectsFactory = IEffectsFactory::getService(std::get<PARAM_FACTORY_NAME>(GetParam()));
ASSERT_NE(nullptr, effectsFactory.get());
- findAndCreateEffect(getEffectType());
+ ASSERT_NO_FATAL_FAILURE(findAndCreateEffect(getEffectType()));
ASSERT_NE(nullptr, effect.get());
Return<Result> ret = effect->init();
@@ -201,7 +213,7 @@
void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
Uuid effectUuid;
- findEffectInstance(type, &effectUuid);
+ ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
Return<void> ret = effectsFactory->createEffect(
effectUuid, 1 /*session*/, 1 /*ioHandle*/,
#if MAJOR_VERSION >= 6
@@ -244,10 +256,16 @@
});
ASSERT_TRUE(ret.isOk());
ASSERT_EQ(Result::OK, retval);
+#if MAJOR_VERSION <= 6
ASSERT_TRUE(audio_channel_mask_is_valid(
static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
*channelCount = audio_channel_count_from_out_mask(
static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels));
+#else
+ *channelCount =
+ audio::policy::configuration::V7_0::getChannelCount(currentConfig.outputCfg.channels);
+ ASSERT_NE(*channelCount, 0);
+#endif
}
TEST_P(AudioEffectHidlTest, Close) {
@@ -391,7 +409,12 @@
TEST_P(AudioEffectHidlTest, SetDevice) {
description("Verify that SetDevice works for an output chain effect");
+#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER));
+#else
+ DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)};
+ Return<Result> ret = effect->setDevice(device);
+#endif
EXPECT_TRUE(ret.isOk());
EXPECT_EQ(Result::OK, ret);
}
@@ -441,22 +464,28 @@
TEST_P(AudioEffectHidlTest, SetInputDevice) {
description("Verify that SetInputDevice does not crash");
+#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC));
+#else
+ DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC)};
+ Return<Result> ret = effect->setInputDevice(device);
+#endif
EXPECT_TRUE(ret.isOk());
}
TEST_P(AudioEffectHidlTest, SetAudioSource) {
description("Verify that SetAudioSource does not crash");
+#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setAudioSource(AudioSource::MIC);
+#else
+ Return<Result> ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+#endif
EXPECT_TRUE(ret.isOk());
}
TEST_P(AudioEffectHidlTest, Offload) {
description("Verify that calling Offload method does not crash");
- EffectOffloadParameter offloadParam;
- offloadParam.isOffload = false;
- offloadParam.ioHandle = static_cast<int>(AudioHandleConsts::AUDIO_IO_HANDLE_NONE);
- Return<Result> ret = effect->offload(offloadParam);
+ Return<Result> ret = effect->offload(EffectOffloadParameter{});
EXPECT_TRUE(ret.isOk());
}
@@ -845,3 +874,9 @@
IEffectsFactory::descriptor)),
::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
EffectParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectsFactoryHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerAudioEffectHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerAudioEffectHidlTest);
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV7_0TargetTest.xml b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV7_0TargetTest.xml
new file mode 100644
index 0000000..e609756
--- /dev/null
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV7_0TargetTest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalAudioEffectV7_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalAudioEffectV7_0TargetTest->/data/local/tmp/VtsHalAudioEffectV7_0TargetTest" />
+ <option name="push" value="audio_effects_conf_V7_0.xsd->/data/local/tmp/audio_effects_conf_V7_0.xsd" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalAudioEffectV7_0TargetTest" />
+ </test>
+</configuration>
diff --git a/audio/policy/1.0/vts/functional/Android.bp b/audio/policy/1.0/vts/functional/Android.bp
index a5ddee5..7b7cf0d 100644
--- a/audio/policy/1.0/vts/functional/Android.bp
+++ b/audio/policy/1.0/vts/functional/Android.bp
@@ -1,6 +1,5 @@
cc_test {
name: "VtsHalAudioPolicyV1_0TargetTest",
- defaults: ["vts_target_tests_defaults"],
srcs: [
"ValidateEngineConfiguration.cpp",
],
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
index 3b84c3b..5c556d2 100644
--- a/authsecret/1.0/Android.bp
+++ b/authsecret/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.authsecret@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IAuthSecret.hal",
],
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
index f27f266..c09b265 100644
--- a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -81,6 +81,7 @@
authsecret->primaryUserCredential(WRONG_SECRET);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AuthSecretHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, AuthSecretHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAuthSecret::descriptor)),
diff --git a/automotive/OWNERS b/automotive/OWNERS
index 83ee63c..fb3e3d6 100644
--- a/automotive/OWNERS
+++ b/automotive/OWNERS
@@ -3,3 +3,4 @@
pfg@google.com
gurunagarajan@google.com
keunyoung@google.com
+felipeal@google.com
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index 7ef7909..8835f51 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.audiocontrol@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAudioControl.hal",
diff --git a/automotive/audiocontrol/2.0/Android.bp b/automotive/audiocontrol/2.0/Android.bp
index 2a9f849..e9ce638 100644
--- a/automotive/audiocontrol/2.0/Android.bp
+++ b/automotive/audiocontrol/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.audiocontrol@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAudioControl.hal",
@@ -13,8 +10,9 @@
"IFocusListener.hal",
],
interfaces: [
- "android.hidl.base@1.0",
"android.hardware.audio.common@6.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
],
gen_java: true,
}
diff --git a/automotive/can/1.0/Android.bp b/automotive/can/1.0/Android.bp
index 2221e66..2ddfaf9 100644
--- a/automotive/can/1.0/Android.bp
+++ b/automotive/can/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.can@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICanBus.hal",
diff --git a/automotive/evs/1.0/Android.bp b/automotive/evs/1.0/Android.bp
index 51f8e20..279c09a 100644
--- a/automotive/evs/1.0/Android.bp
+++ b/automotive/evs/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.evs@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IEvsCamera.hal",
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 54862a2..7fe7a33 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -579,7 +579,7 @@
}
}
-
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EvsHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance,
EvsHidlTest,
diff --git a/automotive/evs/1.1/Android.bp b/automotive/evs/1.1/Android.bp
index f9bccef..443422e 100644
--- a/automotive/evs/1.1/Android.bp
+++ b/automotive/evs/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.evs@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IEvsCamera.hal",
diff --git a/automotive/sv/1.0/Android.bp b/automotive/sv/1.0/Android.bp
index 769bdc6..3a39148 100644
--- a/automotive/sv/1.0/Android.bp
+++ b/automotive/sv/1.0/Android.bp
@@ -3,22 +3,19 @@
hidl_interface {
name: "android.hardware.automotive.sv@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
- "ISurroundViewStream.hal",
- "ISurroundViewSession.hal",
"ISurroundView2dSession.hal",
"ISurroundView3dSession.hal",
"ISurroundViewService.hal",
+ "ISurroundViewSession.hal",
+ "ISurroundViewStream.hal",
],
interfaces: [
- "android.hidl.base@1.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
+ "android.hidl.base@1.0",
],
gen_java: true,
}
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 0e73d85..4fa8773 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.automotive.vehicle@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IVehicle.hal",
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index cf1e4ba..ef29560 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -22,6 +22,7 @@
#include <android/binder_process.h>
#include <utils/Looper.h>
+#include <vhal_v2_0/EmulatedUserHal.h>
#include <vhal_v2_0/EmulatedVehicleConnector.h>
#include <vhal_v2_0/EmulatedVehicleHal.h>
#include <vhal_v2_0/VehicleHalManager.h>
@@ -34,7 +35,8 @@
int main(int /* argc */, char* /* argv */ []) {
auto store = std::make_unique<VehiclePropertyStore>();
auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
- auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
+ auto userHal = connector->getEmulatedUserHal();
+ auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
auto service = std::make_unique<VehicleHalManager>(hal.get());
connector->setValuePool(hal->getValuePool());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 1d51600..a0b566d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -15,8 +15,13 @@
*/
#define LOG_TAG "DefaultVehicleHal_v2_0"
-#include <android/log.h>
#include <android-base/macros.h>
+#include <android-base/properties.h>
+#include <android/log.h>
+#include <dirent.h>
+#include <sys/system_properties.h>
+#include <fstream>
+#include <regex>
#include "EmulatedVehicleHal.h"
#include "JsonFakeValueGenerator.h"
@@ -102,6 +107,30 @@
mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
this, std::placeholders::_1,
std::placeholders::_2));
+
+ mInitVhalValueOverride =
+ android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
+ if (mInitVhalValueOverride) {
+ getAllPropertiesOverride();
+ }
+}
+
+void EmulatedVehicleHal::getAllPropertiesOverride() {
+ if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
+ std::regex reg_json(".*[.]json", std::regex::icase);
+ while (auto f = readdir(dir)) {
+ if (!regex_match(f->d_name, reg_json)) {
+ continue;
+ }
+ std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
+ JsonFakeValueGenerator tmpGenerator(file);
+
+ std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
+ mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
+ std::begin(propvalues), std::end(propvalues));
+ }
+ closedir(dir);
+ }
}
VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
@@ -210,6 +239,14 @@
return StatusCode::NOT_AVAILABLE;
}
+ if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
+ // Emulator does not support remote brightness control, b/139959479
+ // do not send it down so that it does not bring unnecessary property change event
+ // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
+ // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
+ return StatusCode::OK;
+ }
+
/**
* After checking all conditions, such as the property is available, a real vhal will
* sent the events to Car ECU to take actions.
@@ -235,6 +272,17 @@
return false;
}
+// determine if it's running inside Android Emulator
+static bool isInEmulator() {
+ char propValue[PROP_VALUE_MAX];
+ bool isEmulator = (__system_property_get("ro.kernel.qemu", propValue) != 0);
+ if (!isEmulator) {
+ isEmulator = (__system_property_get("ro.hardware", propValue) != 0) &&
+ (!strcmp(propValue, "ranchu") || !strcmp(propValue, "goldfish"));
+ }
+ return isEmulator;
+}
+
// Parse supported properties list and generate vector of property values to hold current values.
void EmulatedVehicleHal::onCreate() {
static constexpr bool shouldUpdateStatus = true;
@@ -279,12 +327,21 @@
}
} else {
prop.value = it.initialValue;
+ if (mInitVhalValueOverride) {
+ for (auto& itOverride : mVehiclePropertiesOverride) {
+ if (itOverride.prop == cfg.prop) {
+ prop.value = itOverride.value;
+ }
+ }
+ }
}
mPropStore->writeValue(prop, shouldUpdateStatus);
}
}
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+ mInEmulator = isInEmulator();
+ ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
}
std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 30f6bfa..eb38d7d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -63,6 +63,7 @@
// Methods from EmulatedVehicleHalIface
bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
std::vector<VehiclePropValue> getAllProperties() const override;
+ void getAllPropertiesOverride();
private:
constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
@@ -87,6 +88,9 @@
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
VehicleHalClient* mVehicleClient;
+ bool mInEmulator;
+ bool mInitVhalValueOverride;
+ std::vector<VehiclePropValue> mVehiclePropertiesOverride;
EmulatedUserHal* mEmulatedUserHal;
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 8677f83..890eb33 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -48,6 +48,22 @@
mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
+JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
+ std::ifstream ifs(path);
+ if (!ifs) {
+ ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+ }
+ mGenCfg = {
+ .index = 0,
+ .events = parseFakeValueJson(ifs),
+ };
+ mNumOfIterations = mGenCfg.events.size();
+}
+
+std::vector<VehiclePropValue> JsonFakeValueGenerator::getAllEvents() {
+ return mGenCfg.events;
+}
+
VehiclePropValue JsonFakeValueGenerator::nextEvent() {
VehiclePropValue generatedValue;
if (!hasNext()) {
@@ -109,6 +125,7 @@
Json::Value rawEventValue = rawEvent["value"];
auto& value = event.value;
+ int32_t count;
switch (getPropType(event.prop)) {
case VehiclePropertyType::BOOLEAN:
case VehiclePropertyType::INT32:
@@ -126,6 +143,13 @@
case VehiclePropertyType::STRING:
value.stringValue = rawEventValue.asString();
break;
+ case VehiclePropertyType::INT32_VEC:
+ value.int32Values.resize(rawEventValue.size());
+ count = 0;
+ for (auto& it : rawEventValue) {
+ value.int32Values[count++] = it.asInt();
+ }
+ break;
case VehiclePropertyType::MIXED:
copyMixedValueJson(value, rawEventValue);
if (isDiagnosticProperty(event.prop)) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index 70575f7..dc8ff66 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,9 +41,12 @@
public:
JsonFakeValueGenerator(const VehiclePropValue& request);
+ JsonFakeValueGenerator(std::string path);
+
~JsonFakeValueGenerator() = default;
VehiclePropValue nextEvent();
+ std::vector<VehiclePropValue> getAllEvents();
bool hasNext();
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
index ebb8668..dd406f9 100644
--- a/biometrics/face/1.0/Android.bp
+++ b/biometrics/face/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.biometrics.face@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBiometricsFace.hal",
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 78f93af..379f37f 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -348,6 +348,7 @@
} // anonymous namespace
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FaceHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, FaceHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
index c8cc0f1..25bd48d 100644
--- a/biometrics/fingerprint/2.1/Android.bp
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.biometrics.fingerprint@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBiometricsFingerprint.hal",
diff --git a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
index 6093caa..b928314 100644
--- a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
+++ b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
@@ -472,6 +472,7 @@
}
} // anonymous namespace
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FingerprintHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
IBiometricsFingerprint::descriptor)),
diff --git a/biometrics/fingerprint/2.2/Android.bp b/biometrics/fingerprint/2.2/Android.bp
index 6c769ac..a8f202c 100644
--- a/biometrics/fingerprint/2.2/Android.bp
+++ b/biometrics/fingerprint/2.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.biometrics.fingerprint@2.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBiometricsFingerprint.hal",
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index 7036d6e..1cac820 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.bluetooth@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBluetoothHci.hal",
diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp
index f66c25e..6e39d54 100644
--- a/bluetooth/1.0/default/Android.bp
+++ b/bluetooth/1.0/default/Android.bp
@@ -102,13 +102,13 @@
srcs: [
"bluetooth_address.cc",
"test/bluetooth_address_test.cc",
- "test/properties.cc",
],
local_include_dirs: [
"test",
],
shared_libs: [
"libbase",
+ "libcutils",
"liblog",
],
}
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 8c24f76..43abbe4 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -90,6 +90,7 @@
hci_packet_type_ = static_cast<HciPacketType>(buffer[0]);
if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA &&
hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA &&
+ hci_packet_type_ != HCI_PACKET_TYPE_ISO_DATA &&
hci_packet_type_ != HCI_PACKET_TYPE_EVENT) {
LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
static_cast<int>(hci_packet_type_));
diff --git a/bluetooth/1.0/default/hci_internals.h b/bluetooth/1.0/default/hci_internals.h
index 24e944f..6f7ff90 100644
--- a/bluetooth/1.0/default/hci_internals.h
+++ b/bluetooth/1.0/default/hci_internals.h
@@ -44,6 +44,10 @@
const size_t HCI_EVENT_PREAMBLE_SIZE = 2;
const size_t HCI_LENGTH_OFFSET_EVT = 1;
+// 2 bytes for handle and flags, 2 byte for data length (Volume 4, Part E, 5.4.5)
+const size_t HCI_ISO_PREAMBLE_SIZE = 4;
+const size_t HCI_LENGTH_OFFSET_ISO = 2;
+
const size_t HCI_PREAMBLE_SIZE_MAX = HCI_ACL_PREAMBLE_SIZE;
// Event codes (Volume 2, Part E, 7.7.14)
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 7cb3a11..78ce61d 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -26,17 +26,27 @@
namespace {
-const size_t preamble_size_for_type[] = {
- 0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE,
- HCI_EVENT_PREAMBLE_SIZE};
-const size_t packet_length_offset_for_type[] = {
- 0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO,
- HCI_LENGTH_OFFSET_EVT};
+const size_t preamble_size_for_type[] = {0,
+ HCI_COMMAND_PREAMBLE_SIZE,
+ HCI_ACL_PREAMBLE_SIZE,
+ HCI_SCO_PREAMBLE_SIZE,
+ HCI_EVENT_PREAMBLE_SIZE,
+ HCI_ISO_PREAMBLE_SIZE};
+const size_t packet_length_offset_for_type[] = {0,
+ HCI_LENGTH_OFFSET_CMD,
+ HCI_LENGTH_OFFSET_ACL,
+ HCI_LENGTH_OFFSET_SCO,
+ HCI_LENGTH_OFFSET_EVT,
+ HCI_LENGTH_OFFSET_ISO};
size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) {
size_t offset = packet_length_offset_for_type[type];
- if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset];
- return (((preamble[offset + 1]) << 8) | preamble[offset]);
+ if (type == HCI_PACKET_TYPE_ACL_DATA) {
+ return (((preamble[offset + 1]) << 8) | preamble[offset]);
+ } else if (type == HCI_PACKET_TYPE_ISO_DATA) {
+ return ((((preamble[offset + 1]) & 0x3f) << 8) | preamble[offset]);
+ }
+ return preamble[offset];
}
} // namespace
diff --git a/bluetooth/1.0/default/test/bluetooth_address_test.cc b/bluetooth/1.0/default/test/bluetooth_address_test.cc
index 2c8dbe5..ee52d33 100644
--- a/bluetooth/1.0/default/test/bluetooth_address_test.cc
+++ b/bluetooth/1.0/default/test/bluetooth_address_test.cc
@@ -120,95 +120,6 @@
EXPECT_FALSE(memcmp(addrA, addrB, BluetoothAddress::kStringLength) == 0);
}
-TEST_F(BluetoothAddressTest, property_set) {
- // Set the properties to empty strings.
- property_set(PERSIST_BDADDR_PROPERTY, "");
- property_set(PROPERTY_BT_BDADDR_PATH, "");
- property_set(FACTORY_BDADDR_PROPERTY, "");
-
- // Get returns 0.
- char prop[PROP_VALUE_MAX] = "";
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 0);
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 0);
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 0);
-
- // Set the properties to known strings.
- property_set(PERSIST_BDADDR_PROPERTY, "1");
- property_set(PROPERTY_BT_BDADDR_PATH, "22");
- property_set(FACTORY_BDADDR_PROPERTY, "333");
-
- // Get returns the correct length.
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 1);
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 2);
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 3);
-
- // Set the properties to empty strings again.
- property_set(PERSIST_BDADDR_PROPERTY, "");
- property_set(PROPERTY_BT_BDADDR_PATH, "");
- property_set(FACTORY_BDADDR_PROPERTY, "");
-
- // Get returns 0.
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 0);
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 0);
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 0);
-}
-
-TEST_F(BluetoothAddressTest, property_get) {
- // Set the properties to known strings.
- property_set(PERSIST_BDADDR_PROPERTY, PERSIST_BDADDR_PROPERTY);
- property_set(PROPERTY_BT_BDADDR_PATH, PROPERTY_BT_BDADDR_PATH);
- property_set(FACTORY_BDADDR_PROPERTY, FACTORY_BDADDR_PROPERTY);
-
- // Get returns the same strings.
- char prop[PROP_VALUE_MAX] = "";
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(PERSIST_BDADDR_PROPERTY, prop) == 0);
-
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(PROPERTY_BT_BDADDR_PATH, prop) == 0);
-
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
- // Set a property to a different known string.
- char prop2[PROP_VALUE_MAX] = "Erased";
- property_set(PERSIST_BDADDR_PROPERTY, prop2);
-
- // Get returns the correct strings.
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(PROPERTY_BT_BDADDR_PATH, prop) == 0);
-
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
- // Set another property to prop2.
- property_set(PROPERTY_BT_BDADDR_PATH, prop2);
-
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
- // Set the third property to prop2.
- property_set(FACTORY_BDADDR_PROPERTY, prop2);
-
- EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
- EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
- EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
- EXPECT_TRUE(strcmp(prop2, prop) == 0);
-}
-
TEST_F(BluetoothAddressTest, get_local_address) {
EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, "") == 0);
EXPECT_TRUE(property_set(FACTORY_BDADDR_PROPERTY, "") == 0);
diff --git a/bluetooth/1.0/default/test/h4_protocol_unittest.cc b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
index 283243d..174861c 100644
--- a/bluetooth/1.0/default/test/h4_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
@@ -190,8 +190,10 @@
void WriteAndExpectInboundIsoData(char* payload) {
// h4 type[1] + handle[2] + size[1]
- char preamble[4] = {HCI_PACKET_TYPE_ISO_DATA, 20, 17, 0};
- preamble[3] = strlen(payload) & 0xFF;
+ char preamble[5] = {HCI_PACKET_TYPE_ISO_DATA, 19, 92, 0, 0};
+ int length = strlen(payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = (length >> 8) & 0x3F;
ALOGD("%s writing", __func__);
TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
diff --git a/bluetooth/1.0/default/test/properties.cc b/bluetooth/1.0/default/test/properties.cc
deleted file mode 100644
index 70de01e..0000000
--- a/bluetooth/1.0/default/test/properties.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright 2016 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 "properties"
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-static const int MAX_PROPERTIES = 5;
-
-struct property {
- char key[PROP_KEY_MAX + 2];
- char value[PROP_VALUE_MAX + 2];
-};
-
-int num_properties = 0;
-struct property properties[MAX_PROPERTIES];
-
-// Find the correct entry.
-static int property_find(const char* key) {
- for (int i = 0; i < num_properties; i++) {
- if (strncmp(properties[i].key, key, PROP_KEY_MAX) == 0) {
- return i;
- }
- }
- return MAX_PROPERTIES;
-}
-
-int property_set(const char* key, const char* value) {
- if (strnlen(value, PROP_VALUE_MAX) > PROP_VALUE_MAX) return -1;
-
- // Check to see if the property exists.
- int prop_index = property_find(key);
-
- if (prop_index == MAX_PROPERTIES) {
- if (num_properties >= MAX_PROPERTIES) return -1;
- prop_index = num_properties;
- num_properties += 1;
- }
-
- // This is test code. Be nice and don't push the boundary cases!
- strncpy(properties[prop_index].key, key, PROP_KEY_MAX + 1);
- strncpy(properties[prop_index].value, value, PROP_VALUE_MAX + 1);
- return 0;
-}
-
-int property_get(const char* key, char* value, const char* default_value) {
- // This doesn't mock the behavior of default value
- if (default_value != NULL) ALOGE("%s: default_value is ignored!", __func__);
-
- // Check to see if the property exists.
- int prop_index = property_find(key);
-
- if (prop_index == MAX_PROPERTIES) return 0;
-
- int len = strlen(properties[prop_index].value);
- memcpy(value, properties[prop_index].value, len);
- value[len] = '\0';
- return len;
-}
diff --git a/bluetooth/1.0/default/test/sys/system_properties.h b/bluetooth/1.0/default/test/sys/system_properties.h
deleted file mode 100644
index b477a6b..0000000
--- a/bluetooth/1.0/default/test/sys/system_properties.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright 2016 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.
-//
-
-// Mock sys/system_properties.h for testing
-
-#define PROP_VALUE_MAX 50
-#define PROP_KEY_MAX 50
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index ef02eff..0328af1 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -741,6 +741,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BluetoothHidlTest,
testing::ValuesIn(
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
index 4204aed..c3967f0 100644
--- a/bluetooth/1.1/Android.bp
+++ b/bluetooth/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.bluetooth@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IBluetoothHci.hal",
"IBluetoothHciCallbacks.hal",
diff --git a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
index 659b2c8..9ae3837 100644
--- a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
+++ b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
@@ -753,6 +753,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BluetoothHidlTest,
testing::ValuesIn(
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
index 02f224a..d9ec982 100644
--- a/bluetooth/a2dp/1.0/Android.bp
+++ b/bluetooth/a2dp/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.bluetooth.a2dp@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBluetoothAudioHost.hal",
diff --git a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
index 44b138a..f7fdf31 100644
--- a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
+++ b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
@@ -107,4 +107,6 @@
PerInstance, BluetoothA2dpHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
IBluetoothAudioOffload::descriptor)),
- android::hardware::PrintInstanceNameToString);
\ No newline at end of file
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothA2dpHidlTest);
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index 6bf0070..3fbd51f 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.bluetooth.audio@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBluetoothAudioPort.hal",
diff --git a/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp b/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
index d60e732..50119bf 100644
--- a/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
@@ -90,14 +90,16 @@
// bluetooth_audio outputs
void BluetoothAudioSession::OnSessionEnded() {
std::lock_guard<std::recursive_mutex> guard(mutex_);
- if (IsSessionReady()) {
- ReportSessionStatus();
- }
+ bool toggled = IsSessionReady();
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
? kInvalidOffloadAudioConfiguration
: kInvalidSoftwareAudioConfiguration);
stack_iface_ = nullptr;
UpdateDataPath(nullptr);
+ if (toggled) {
+ ReportSessionStatus();
+ }
}
// invoking the registered session_changed_cb_
diff --git a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
index b3cb6f7..ac97b52 100644
--- a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
+++ b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
@@ -888,20 +888,28 @@
android::hardware::getAllHalInstanceNames(
IBluetoothAudioProvidersFactory::descriptor);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProvidersFactoryHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest,
testing::ValuesIn(kAudioInstances),
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpSoftwareHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance,
BluetoothAudioProviderA2dpSoftwareHidlTest,
testing::ValuesIn(kAudioInstances),
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpHardwareHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance,
BluetoothAudioProviderA2dpHardwareHidlTest,
testing::ValuesIn(kAudioInstances),
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderHearingAidSoftwareHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance,
BluetoothAudioProviderHearingAidSoftwareHidlTest,
testing::ValuesIn(kAudioInstances),
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
new file mode 100644
index 0000000..9af8add
--- /dev/null
+++ b/bluetooth/audio/2.1/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.bluetooth.audio@2.1",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IBluetoothAudioProvider.hal",
+ "IBluetoothAudioProvidersFactory.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@5.0",
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth.updatable",
+ ],
+ gen_java: false,
+}
diff --git a/bluetooth/audio/2.1/IBluetoothAudioProvider.hal b/bluetooth/audio/2.1/IBluetoothAudioProvider.hal
new file mode 100644
index 0000000..c462b9e
--- /dev/null
+++ b/bluetooth/audio/2.1/IBluetoothAudioProvider.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import @2.0::IBluetoothAudioProvider;
+import @2.0::IBluetoothAudioPort;
+import @2.0::Status;
+
+/**
+ * HAL interface from the Bluetooth stack to the Audio HAL
+ *
+ * The Bluetooth stack calls methods in this interface to start and end audio
+ * sessions and sends callback events to the Audio HAL.
+ *
+ * Note: For HIDL APIs with a "generates" statement, the callback parameter used
+ * for return value must be invoked synchronously before the API call returns.
+ */
+interface IBluetoothAudioProvider extends @2.0::IBluetoothAudioProvider {
+
+ /**
+ * This method indicates that the Bluetooth stack is ready to stream audio.
+ * It registers an instance of IBluetoothAudioPort with and provides the
+ * current negotiated codec to the Audio HAL. After this method is called,
+ * the Audio HAL can invoke IBluetoothAudioPort.startStream().
+ *
+ * Note: endSession() must be called to unregister this IBluetoothAudioPort
+ *
+ * @param hostIf An instance of IBluetoothAudioPort for stream control
+ * @param audioConfig The audio configuration negotiated with the remote
+ * device. The PCM parameters are set if software based encoding,
+ * otherwise the correct codec configuration is used for hardware
+ * encoding.
+ *
+ * @return status One of the following
+ * SUCCESS if this IBluetoothAudioPort was successfully registered with
+ * the Audio HAL
+ * UNSUPPORTED_CODEC_CONFIGURATION if the Audio HAL cannot register this
+ * IBluetoothAudioPort with the given codec configuration
+ * FAILURE if the Audio HAL cannot register this IBluetoothAudioPort for
+ * any other reason
+ * @return dataMQ The fast message queue for audio data from/to this
+ * provider. Audio data will be in PCM format as specified by the
+ * audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
+ * from/to hardware or on failure.
+ */
+ startSession_2_1(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
+ generates (Status status, fmq_sync<uint8_t> dataMQ);
+};
diff --git a/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal
new file mode 100644
index 0000000..5593c7c
--- /dev/null
+++ b/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.hal
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import IBluetoothAudioProvider;
+import @2.0::IBluetoothAudioProvidersFactory;
+import @2.0::Status;
+
+/**
+ * This factory allows a HAL implementation to be split into multiple
+ * independent providers.
+ *
+ * When the Bluetooth stack is ready to create an audio session, it must first
+ * obtain the IBluetoothAudioProvider for that session type by calling
+ * openProvider().
+ *
+ * Note: For HIDL APIs with a "generates" statement, the callback parameter used
+ * for return value must be invoked synchronously before the API call returns.
+ */
+interface IBluetoothAudioProvidersFactory extends @2.0::IBluetoothAudioProvidersFactory {
+
+ /**
+ * Opens an audio provider for a session type. To close the provider, it is
+ * necessary to release references to the returned provider object.
+ *
+ * @param sessionType The session type (e.g.
+ * LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
+ *
+ * @return status One of the following
+ * SUCCESS if the Audio HAL successfully opens the provider with the
+ * given session type
+ * FAILURE if the Audio HAL cannot open the provider
+ * @return provider The provider of the specified session type
+ */
+ openProvider_2_1(SessionType sessionType)
+ generates (Status status, IBluetoothAudioProvider provider);
+
+ /**
+ * Gets a list of audio capabilities for a session type.
+ *
+ * For software encoding, the PCM capabilities are returned.
+ * For hardware encoding, the supported codecs and their capabilities are
+ * returned.
+ *
+ * @param sessionType The session type (e.g.
+ * A2DP_SOFTWARE_ENCODING_DATAPATH).
+ * @return audioCapabilities A list containing all the capabilities
+ * supported by the sesson type. The capabilities is a list of
+ * available options when configuring the codec for the session.
+ * For software encoding it is the PCM data rate.
+ * For hardware encoding it is the list of supported codecs and their
+ * capabilities.
+ * If a provider isn't supported, an empty list should be returned.
+ * Note: Only one entry should exist per codec when using hardware
+ * encoding.
+ */
+ getProviderCapabilities_2_1(SessionType sessionType)
+ generates (vec<AudioCapabilities> audioCapabilities);
+};
diff --git a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..b4a61b6
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpOffload"
+
+#include "A2dpOffloadAudioProvider.h"
+
+#include <android-base/logging.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider()
+ : BluetoothAudioProvider() {
+ session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+}
+
+bool A2dpOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+ return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool A2dpOffloadAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_);
+}
+
+Return<void> A2dpOffloadAudioProvider::startSession(
+ const sp<IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ if (audioConfig.getDiscriminator() !=
+ AudioConfiguration::hidl_discriminator::codecConfig) {
+ LOG(WARNING) << __func__
+ << " - Invalid Audio Configuration=" << toString(audioConfig);
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ } else if (!android::bluetooth::audio::IsOffloadCodecConfigurationValid(
+ session_type_, audioConfig.codecConfig())) {
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> A2dpOffloadAudioProvider::onSessionReady(
+ startSession_cb _hidl_cb) {
+ BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+ nullptr, audio_config_);
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..13e0b9a
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+ A2dpOffloadAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+ bool isValid(const V2_0::SessionType& sessionType) override;
+
+ Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+
+ private:
+ Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..a67c341
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpSoftware"
+
+#include "A2dpSoftwareAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7; // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 2; // double buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
+ : BluetoothAudioProvider(), mDataMQ(nullptr) {
+ LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+ << " byte(s)";
+ std::unique_ptr<DataMQ> tempDataMQ(
+ new DataMQ(kDataMqSize, /* EventFlag */ true));
+ if (tempDataMQ && tempDataMQ->isValid()) {
+ mDataMQ = std::move(tempDataMQ);
+ session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+ } else {
+ ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+ ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+ }
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+ return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
+}
+
+Return<void> A2dpSoftwareAudioProvider::startSession(
+ const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ if (audioConfig.getDiscriminator() !=
+ AudioConfiguration::hidl_discriminator::pcmConfig) {
+ LOG(WARNING) << __func__
+ << " - Invalid Audio Configuration=" << toString(audioConfig);
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
+ audioConfig.pcmConfig())) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << toString(audioConfig.pcmConfig());
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> A2dpSoftwareAudioProvider::onSessionReady(
+ startSession_cb _hidl_cb) {
+ if (mDataMQ && mDataMQ->isValid()) {
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+ } else {
+ _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..20566d1
--- /dev/null
+++ b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+ A2dpSoftwareAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+ bool isValid(const V2_0::SessionType& sessionType) override;
+
+ Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+
+ private:
+ // audio data queue for software encoding
+ std::unique_ptr<DataMQ> mDataMQ;
+
+ Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/Android.bp b/bluetooth/audio/2.1/default/Android.bp
new file mode 100644
index 0000000..5381fec
--- /dev/null
+++ b/bluetooth/audio/2.1/default/Android.bp
@@ -0,0 +1,48 @@
+cc_library_shared {
+ name: "android.hardware.bluetooth.audio@2.1-impl",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "BluetoothAudioProvidersFactory.cpp",
+ "BluetoothAudioProvider.cpp",
+ "A2dpOffloadAudioProvider.cpp",
+ "A2dpSoftwareAudioProvider.cpp",
+ "HearingAidAudioProvider.cpp",
+ "LeAudioAudioProvider.cpp",
+ ],
+ header_libs: ["libhardware_headers"],
+ shared_libs: [
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "libbase",
+ "libbluetooth_audio_session_2_1",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_library_shared {
+ name: "libbluetooth_audio_session_2_1",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ srcs: [
+ "session/BluetoothAudioSession.cpp",
+ "session/BluetoothAudioSupportedCodecsDB.cpp",
+ ],
+ export_include_dirs: ["session/"],
+ header_libs: ["libhardware_headers"],
+ shared_libs: [
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
new file mode 100644
index 0000000..092038b
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderStub"
+
+#include "BluetoothAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Void;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+void BluetoothAudioDeathRecipient::serviceDied(
+ uint64_t cookie __unused,
+ const wp<::android::hidl::base::V1_0::IBase>& who __unused) {
+ LOG(ERROR) << "BluetoothAudioDeathRecipient::" << __func__
+ << " - BluetoothAudio Service died";
+ provider_->endSession();
+}
+
+BluetoothAudioProvider::BluetoothAudioProvider()
+ : death_recipient_(new BluetoothAudioDeathRecipient(this)),
+ session_type_(SessionType::UNKNOWN),
+ audio_config_({}) {}
+
+Return<void> BluetoothAudioProvider::startSession(
+ const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ AudioConfiguration audioConfig_2_1;
+
+ if (audioConfig.getDiscriminator() ==
+ V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
+ audioConfig_2_1.pcmConfig() = {
+ .sampleRate =
+ static_cast<SampleRate>(audioConfig.pcmConfig().sampleRate),
+ .channelMode = audioConfig.pcmConfig().channelMode,
+ .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
+ .dataIntervalUs = 0};
+ } else {
+ audioConfig_2_1.codecConfig() = audioConfig.codecConfig();
+ }
+
+ return startSession_2_1(hostIf, audioConfig_2_1, _hidl_cb);
+}
+
+Return<void> BluetoothAudioProvider::startSession_2_1(
+ const sp<IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ if (hostIf == nullptr) {
+ _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+ return Void();
+ }
+
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ audio_config_ = audioConfig;
+ stack_iface_ = hostIf;
+ stack_iface_->linkToDeath(death_recipient_, 0);
+
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", AudioConfiguration=[" << toString(audio_config_) << "]";
+
+ onSessionReady(_hidl_cb);
+ return Void();
+}
+
+Return<void> BluetoothAudioProvider::streamStarted(
+ BluetoothAudioStatus status) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status);
+
+ /**
+ * Streaming on control path has started,
+ * HAL server should start the streaming on data path.
+ */
+ if (stack_iface_) {
+ BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
+ status);
+ } else {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status) << " has NO session";
+ }
+
+ return Void();
+}
+
+Return<void> BluetoothAudioProvider::streamSuspended(
+ BluetoothAudioStatus status) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status);
+
+ /**
+ * Streaming on control path has suspend,
+ * HAL server should suspend the streaming on data path.
+ */
+ if (stack_iface_) {
+ BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
+ status);
+ } else {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status) << " has NO session";
+ }
+
+ return Void();
+}
+
+Return<void> BluetoothAudioProvider::endSession() {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+ if (stack_iface_) {
+ BluetoothAudioSessionReport::OnSessionEnded(session_type_);
+ stack_iface_->unlinkToDeath(death_recipient_);
+ } else {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ }
+
+ /**
+ * Clean up the audio platform as remote audio device is no
+ * longer active
+ */
+ stack_iface_ = nullptr;
+ audio_config_ = {};
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.h b/bluetooth/audio/2.1/default/BluetoothAudioProvider.h
new file mode 100644
index 0000000..a2e611f
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+
+using BluetoothAudioStatus =
+ ::android::hardware::bluetooth::audio::V2_0::Status;
+
+class BluetoothAudioDeathRecipient;
+
+class BluetoothAudioProvider : public IBluetoothAudioProvider {
+ public:
+ BluetoothAudioProvider();
+ ~BluetoothAudioProvider() = default;
+
+ virtual bool isValid(const SessionType& sessionType) = 0;
+ virtual bool isValid(const V2_0::SessionType& sessionType) = 0;
+
+ Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+ Return<void> startSession_2_1(const sp<IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+ Return<void> streamStarted(BluetoothAudioStatus status) override;
+ Return<void> streamSuspended(BluetoothAudioStatus status) override;
+ Return<void> endSession() override;
+
+ protected:
+ sp<BluetoothAudioDeathRecipient> death_recipient_;
+
+ SessionType session_type_;
+ AudioConfiguration audio_config_;
+ sp<V2_0::IBluetoothAudioPort> stack_iface_;
+
+ virtual Return<void> onSessionReady(startSession_cb _hidl_cb) = 0;
+};
+
+class BluetoothAudioDeathRecipient : public hidl_death_recipient {
+ public:
+ BluetoothAudioDeathRecipient(const sp<BluetoothAudioProvider> provider)
+ : provider_(provider) {}
+
+ virtual void serviceDied(
+ uint64_t cookie,
+ const wp<::android::hidl::base::V1_0::IBase>& who) override;
+
+ private:
+ sp<BluetoothAudioProvider> provider_;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
new file mode 100644
index 0000000..adf2717
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProvidersFactory"
+
+#include "BluetoothAudioProvidersFactory.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+
+A2dpSoftwareAudioProvider
+ BluetoothAudioProvidersFactory::a2dp_software_provider_instance_;
+A2dpOffloadAudioProvider
+ BluetoothAudioProvidersFactory::a2dp_offload_provider_instance_;
+HearingAidAudioProvider
+ BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
+LeAudioOutputAudioProvider
+ BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
+LeAudioInputAudioProvider
+ BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
+
+Return<void> BluetoothAudioProvidersFactory::openProvider(
+ const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
+ BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
+ BluetoothAudioProvider* provider = nullptr;
+ switch (sessionType) {
+ case V2_0::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+ provider = &a2dp_software_provider_instance_;
+ break;
+ case V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
+ provider = &a2dp_offload_provider_instance_;
+ break;
+ case V2_0::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+ provider = &hearing_aid_provider_instance_;
+ break;
+ default:
+ status = BluetoothAudioStatus::FAILURE;
+ }
+ if (provider == nullptr || !provider->isValid(sessionType)) {
+ provider = nullptr;
+ status = BluetoothAudioStatus::FAILURE;
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
+ << ", status=" << toString(status);
+ }
+ _hidl_cb(status, provider);
+ return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::openProvider_2_1(
+ const SessionType sessionType, openProvider_2_1_cb _hidl_cb) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
+ BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
+ BluetoothAudioProvider* provider = nullptr;
+ switch (sessionType) {
+ case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+ provider = &a2dp_software_provider_instance_;
+ break;
+ case SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
+ provider = &a2dp_offload_provider_instance_;
+ break;
+ case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+ provider = &hearing_aid_provider_instance_;
+ break;
+ case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+ provider = &leaudio_output_provider_instance_;
+ break;
+ case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
+ provider = &leaudio_input_provider_instance_;
+ break;
+ default:
+ status = BluetoothAudioStatus::FAILURE;
+ }
+ if (provider == nullptr || !provider->isValid(sessionType)) {
+ provider = nullptr;
+ status = BluetoothAudioStatus::FAILURE;
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
+ << ", status=" << toString(status);
+ }
+ _hidl_cb(status, provider);
+ return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities(
+ const V2_0::SessionType sessionType, getProviderCapabilities_cb _hidl_cb) {
+ hidl_vec<V2_0::AudioCapabilities> audio_capabilities =
+ hidl_vec<V2_0::AudioCapabilities>(0);
+ if (sessionType == V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ std::vector<CodecCapabilities> db_codec_capabilities =
+ android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType != V2_0::SessionType::UNKNOWN) {
+ std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+ db_pcm_capabilities =
+ android::bluetooth::audio::GetSoftwarePcmCapabilities();
+ if (db_pcm_capabilities.size() == 1) {
+ audio_capabilities.resize(1);
+ audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+ }
+ }
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+ << " supports " << audio_capabilities.size() << " codecs";
+ _hidl_cb(audio_capabilities);
+ return Void();
+}
+
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_1(
+ const SessionType sessionType, getProviderCapabilities_2_1_cb _hidl_cb) {
+ hidl_vec<AudioCapabilities> audio_capabilities =
+ hidl_vec<AudioCapabilities>(0);
+ if (sessionType == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ std::vector<CodecCapabilities> db_codec_capabilities =
+ android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType != SessionType::UNKNOWN) {
+ std::vector<PcmParameters> db_pcm_capabilities =
+ android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
+ if (db_pcm_capabilities.size() == 1) {
+ audio_capabilities.resize(1);
+ audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+ }
+ }
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+ << " supports " << audio_capabilities.size() << " codecs";
+ _hidl_cb(audio_capabilities);
+ return Void();
+}
+
+IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
+ const char* /* name */) {
+ return new BluetoothAudioProvidersFactory();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
new file mode 100644
index 0000000..fd83694
--- /dev/null
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory {
+ public:
+ BluetoothAudioProvidersFactory() {}
+
+ Return<void> openProvider(const V2_0::SessionType sessionType,
+ openProvider_cb _hidl_cb) override;
+
+ Return<void> getProviderCapabilities(
+ const V2_0::SessionType sessionType,
+ getProviderCapabilities_cb _hidl_cb) override;
+
+ Return<void> openProvider_2_1(const SessionType sessionType,
+ openProvider_2_1_cb _hidl_cb) override;
+
+ Return<void> getProviderCapabilities_2_1(
+ const SessionType sessionType,
+ getProviderCapabilities_2_1_cb _hidl_cb) override;
+
+ private:
+ static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
+ static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
+ static HearingAidAudioProvider hearing_aid_provider_instance_;
+ static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
+ static LeAudioInputAudioProvider leaudio_input_provider_instance_;
+};
+
+extern "C" IBluetoothAudioProvidersFactory*
+HIDL_FETCH_IBluetoothAudioProvidersFactory(const char* name);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp
new file mode 100644
index 0000000..aded7e1
--- /dev/null
+++ b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderHearingAid"
+
+#include "HearingAidAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7; // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 1; // single buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+HearingAidAudioProvider::HearingAidAudioProvider()
+ : BluetoothAudioProvider(), mDataMQ(nullptr) {
+ LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+ << " byte(s)";
+ std::unique_ptr<DataMQ> tempDataMQ(
+ new DataMQ(kDataMqSize, /* EventFlag */ true));
+ if (tempDataMQ && tempDataMQ->isValid()) {
+ mDataMQ = std::move(tempDataMQ);
+ session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+ } else {
+ ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+ ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+ }
+}
+
+bool HearingAidAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+ return isValid(static_cast<SessionType>(sessionType));
+}
+
+bool HearingAidAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
+}
+
+Return<void> HearingAidAudioProvider::startSession(
+ const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ if (audioConfig.getDiscriminator() !=
+ AudioConfiguration::hidl_discriminator::pcmConfig) {
+ LOG(WARNING) << __func__
+ << " - Invalid Audio Configuration=" << toString(audioConfig);
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
+ audioConfig.pcmConfig())) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << toString(audioConfig.pcmConfig());
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
+}
+
+Return<void> HearingAidAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+ if (mDataMQ && mDataMQ->isValid()) {
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+ } else {
+ _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/HearingAidAudioProvider.h b/bluetooth/audio/2.1/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..c949257
--- /dev/null
+++ b/bluetooth/audio/2.1/default/HearingAidAudioProvider.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class HearingAidAudioProvider : public BluetoothAudioProvider {
+ public:
+ HearingAidAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+ bool isValid(const V2_0::SessionType& sessionType) override;
+
+ Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+ const V2_0::AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+
+ private:
+ // audio data queue for software encoding
+ std::unique_ptr<DataMQ> mDataMQ;
+
+ Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
new file mode 100644
index 0000000..1fa2dce
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
+ * www.ehima.com
+ *
+ * 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 "BTAudioProviderLeAudio"
+
+#include "LeAudioAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport.h"
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+static constexpr uint32_t kBufferOutCount = 2; // two frame buffer
+static constexpr uint32_t kBufferInCount = 2; // two frame buffer
+
+LeAudioOutputAudioProvider::LeAudioOutputAudioProvider()
+ : LeAudioAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioInputAudioProvider::LeAudioInputAudioProvider()
+ : LeAudioAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
+}
+
+LeAudioAudioProvider::LeAudioAudioProvider()
+ : BluetoothAudioProvider(), mDataMQ(nullptr) {}
+
+bool LeAudioAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+ LOG(ERROR) << __func__ << ", invalid session type for Le Audio provider: "
+ << toString(sessionType);
+
+ return false;
+}
+
+bool LeAudioAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_);
+}
+
+Return<void> LeAudioAudioProvider::startSession_2_1(
+ const sp<V2_0::IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ if (audioConfig.getDiscriminator() !=
+ AudioConfiguration::hidl_discriminator::pcmConfig) {
+ LOG(WARNING) << __func__
+ << " - Invalid Audio Configuration=" << toString(audioConfig);
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid_2_1(
+ audioConfig.pcmConfig())) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << toString(audioConfig.pcmConfig());
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ uint32_t kDataMqSize = 0;
+ switch (audioConfig.pcmConfig().sampleRate) {
+ case SampleRate::RATE_16000:
+ kDataMqSize = 16000;
+ break;
+ case SampleRate::RATE_24000:
+ kDataMqSize = 24000;
+ break;
+ case SampleRate::RATE_44100:
+ kDataMqSize = 44100;
+ break;
+ case SampleRate::RATE_48000:
+ kDataMqSize = 48000;
+ break;
+ case SampleRate::RATE_88200:
+ kDataMqSize = 88200;
+ break;
+ case SampleRate::RATE_96000:
+ kDataMqSize = 96000;
+ break;
+ case SampleRate::RATE_176400:
+ kDataMqSize = 176400;
+ break;
+ case SampleRate::RATE_192000:
+ kDataMqSize = 192000;
+ break;
+ default:
+ /* This should never happen it would be caught while validating
+ * parameters.
+ */
+ break;
+ }
+
+ /* Number of samples per millisecond */
+ kDataMqSize = ceil(kDataMqSize / 1000);
+
+ switch (audioConfig.pcmConfig().channelMode) {
+ case ChannelMode::MONO:
+ break;
+ case ChannelMode::STEREO:
+ kDataMqSize *= 2;
+ break;
+ default:
+ /* This should never happen it would be caught while validating
+ * parameters.
+ */
+ break;
+ }
+
+ switch (audioConfig.pcmConfig().bitsPerSample) {
+ case BitsPerSample::BITS_16:
+ kDataMqSize *= 2;
+ break;
+ case BitsPerSample::BITS_24:
+ kDataMqSize *= 3;
+ break;
+ case BitsPerSample::BITS_32:
+ kDataMqSize *= 4;
+ break;
+ default:
+ /* This should never happen it would be caught while validating
+ * parameters.
+ */
+ break;
+ }
+
+ if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
+ kDataMqSize *= kBufferOutCount;
+ else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH)
+ kDataMqSize *= kBufferInCount;
+ else
+ LOG(WARNING) << __func__ << ", default single buffer used";
+
+ kDataMqSize *= audioConfig.pcmConfig().dataIntervalUs / 1000;
+
+ LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+ << " byte(s)";
+
+ std::unique_ptr<DataMQ> tempDataMQ(
+ new DataMQ(kDataMqSize, /* EventFlag */ true));
+ if (tempDataMQ && tempDataMQ->isValid()) {
+ mDataMQ = std::move(tempDataMQ);
+ } else {
+ ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
+ ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
+ _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+ return Void();
+ }
+
+ return BluetoothAudioProvider::startSession_2_1(hostIf, audioConfig,
+ _hidl_cb);
+}
+
+Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+ if (mDataMQ && mDataMQ->isValid()) {
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
+ } else {
+ _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.h b/bluetooth/audio/2.1/default/LeAudioAudioProvider.h
new file mode 100644
index 0000000..09b2b54
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
+ * www.ehima.com
+ *
+ * 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 <android/hardware/bluetooth/audio/2.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class LeAudioAudioProvider : public BluetoothAudioProvider {
+ public:
+ LeAudioAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+ bool isValid(const V2_0::SessionType& sessionType) override;
+
+ Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+
+ private:
+ /** queue for software encodec/decoded audio data */
+ std::unique_ptr<DataMQ> mDataMQ;
+
+ Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+class LeAudioOutputAudioProvider : public LeAudioAudioProvider {
+ public:
+ LeAudioOutputAudioProvider();
+};
+
+class LeAudioInputAudioProvider : public LeAudioAudioProvider {
+ public:
+ LeAudioInputAudioProvider();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp
new file mode 100644
index 0000000..ea2c54a
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderSession"
+
+#include "BluetoothAudioSession.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::audio::common::V5_0::AudioContentType;
+using ::android::hardware::audio::common::V5_0::AudioUsage;
+using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::TimeSpec;
+
+const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {
+ .codecType = CodecType::UNKNOWN,
+ .encodedAudioBitrate = 0x00000000,
+ .peerMtu = 0xffff,
+ .isScmstEnabled = false,
+ .config = {}};
+AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration =
+ {};
+AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {};
+
+static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
+static constexpr int kFmqReceiveTimeoutMs =
+ 1000; // 1000 ms timeout for receiving
+static constexpr int kWritePollMs = 1; // polled non-blocking interval
+static constexpr int kReadPollMs = 1; // polled non-blocking interval
+
+static inline timespec timespec_convert_from_hal(const TimeSpec& TS) {
+ return {.tv_sec = static_cast<long>(TS.tvSec),
+ .tv_nsec = static_cast<long>(TS.tvNSec)};
+}
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+ : session_type_(session_type), stack_iface_(nullptr), mDataMQ(nullptr) {
+ invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
+ invalidOffloadAudioConfiguration.codecConfig(kInvalidCodecConfiguration);
+}
+
+// The report function is used to report that the Bluetooth stack has started
+// this session without any failure, and will invoke session_changed_cb_ to
+// notify those registered bluetooth_audio outputs
+void BluetoothAudioSession::OnSessionStarted(
+ const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
+ const AudioConfiguration& audio_config) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (stack_iface == nullptr) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", IBluetoothAudioPort Invalid";
+ } else if (!UpdateAudioConfig(audio_config)) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", AudioConfiguration=" << toString(audio_config)
+ << " Invalid";
+ } else if (!UpdateDataPath(dataMQ)) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << " DataMQ Invalid";
+ audio_config_ =
+ (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
+ ? kInvalidOffloadAudioConfiguration
+ : kInvalidSoftwareAudioConfiguration);
+ } else {
+ stack_iface_ = stack_iface;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", AudioConfiguration=" << toString(audio_config);
+ ReportSessionStatus();
+ }
+}
+
+// The report function is used to report that the Bluetooth stack has ended the
+// session, and will invoke session_changed_cb_ to notify registered
+// bluetooth_audio outputs
+void BluetoothAudioSession::OnSessionEnded() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ bool toggled = IsSessionReady();
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+ audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
+ ? kInvalidOffloadAudioConfiguration
+ : kInvalidSoftwareAudioConfiguration);
+ stack_iface_ = nullptr;
+ UpdateDataPath(nullptr);
+ if (toggled) {
+ ReportSessionStatus();
+ }
+}
+
+// invoking the registered session_changed_cb_
+void BluetoothAudioSession::ReportSessionStatus() {
+ // This is locked already by OnSessionStarted / OnSessionEnded
+ if (observers_.empty()) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO port state observer";
+ return;
+ }
+ for (auto& observer : observers_) {
+ uint16_t cookie = observer.first;
+ std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " notify to bluetooth_audio=0x"
+ << android::base::StringPrintf("%04x", cookie);
+ cb->session_changed_cb_(cookie);
+ }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession::ReportControlStatus(
+ bool start_resp, const BluetoothAudioStatus& status) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (observers_.empty()) {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO port state observer";
+ return;
+ }
+ for (auto& observer : observers_) {
+ uint16_t cookie = observer.first;
+ std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+ LOG(INFO) << __func__ << " - status=" << toString(status)
+ << " for SessionType=" << toString(session_type_)
+ << ", bluetooth_audio=0x"
+ << android::base::StringPrintf("%04x", cookie)
+ << (start_resp ? " started" : " suspended");
+ cb->control_result_cb_(cookie, start_resp, status);
+ }
+}
+
+// The function helps to check if this session is ready or not
+// @return: true if the Bluetooth stack has started the specified session
+bool BluetoothAudioSession::IsSessionReady() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ bool dataMQ_valid =
+ (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
+ (mDataMQ != nullptr && mDataMQ->isValid()));
+ return stack_iface_ != nullptr && dataMQ_valid;
+}
+
+bool BluetoothAudioSession::UpdateDataPath(const DataMQ::Descriptor* dataMQ) {
+ if (dataMQ == nullptr) {
+ // usecase of reset by nullptr
+ mDataMQ = nullptr;
+ return true;
+ }
+ std::unique_ptr<DataMQ> tempDataMQ;
+ tempDataMQ.reset(new DataMQ(*dataMQ));
+ if (!tempDataMQ || !tempDataMQ->isValid()) {
+ mDataMQ = nullptr;
+ return false;
+ }
+ mDataMQ = std::move(tempDataMQ);
+ return true;
+}
+
+bool BluetoothAudioSession::UpdateAudioConfig(
+ const AudioConfiguration& audio_config) {
+ bool is_software_session =
+ (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+ bool is_offload_session =
+ (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+ auto audio_config_discriminator = audio_config.getDiscriminator();
+ bool is_software_audio_config =
+ (is_software_session &&
+ audio_config_discriminator ==
+ AudioConfiguration::hidl_discriminator::pcmConfig);
+ bool is_offload_audio_config =
+ (is_offload_session &&
+ audio_config_discriminator ==
+ AudioConfiguration::hidl_discriminator::codecConfig);
+ if (!is_software_audio_config && !is_offload_audio_config) {
+ return false;
+ }
+ audio_config_ = audio_config;
+ return true;
+}
+
+// The control function helps the bluetooth_audio module to register
+// PortStatusCallbacks
+// @return: cookie - the assigned number to this bluetooth_audio output
+uint16_t BluetoothAudioSession::RegisterStatusCback(
+ const PortStatusCallbacks& cbacks) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ uint16_t cookie = ObserversCookieGetInitValue(session_type_);
+ uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
+
+ while (cookie < cookie_upper_bound) {
+ if (observers_.find(cookie) == observers_.end()) {
+ break;
+ }
+ ++cookie;
+ }
+ if (cookie >= cookie_upper_bound) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has " << observers_.size()
+ << " observers already (No Resource)";
+ return kObserversCookieUndefined;
+ }
+ std::shared_ptr<struct PortStatusCallbacks> cb =
+ std::make_shared<struct PortStatusCallbacks>();
+ *cb = cbacks;
+ observers_[cookie] = cb;
+ return cookie;
+}
+
+// The control function helps the bluetooth_audio module to unregister
+// PortStatusCallbacks
+// @param: cookie - indicates which bluetooth_audio output is
+void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (observers_.erase(cookie) != 1) {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << " no such provider=0x"
+ << android::base::StringPrintf("%04x", cookie);
+ }
+}
+
+// The control function is for the bluetooth_audio module to get the current
+// AudioConfiguration
+const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (IsSessionReady()) {
+ return audio_config_;
+ } else if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ return kInvalidOffloadAudioConfiguration;
+ } else {
+ return kInvalidSoftwareAudioConfiguration;
+ }
+}
+
+// Those control functions are for the bluetooth_audio module to start, suspend,
+// stop stream, to check position, and to update metadata.
+bool BluetoothAudioSession::StartStream() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return false;
+ }
+ auto hal_retval = stack_iface_->startStream();
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ return false;
+ }
+ return true;
+}
+
+bool BluetoothAudioSession::SuspendStream() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return false;
+ }
+ auto hal_retval = stack_iface_->suspendStream();
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ return false;
+ }
+ return true;
+}
+
+void BluetoothAudioSession::StopStream() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ return;
+ }
+ auto hal_retval = stack_iface_->stopStream();
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ }
+}
+
+bool BluetoothAudioSession::GetPresentationPosition(
+ uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
+ timespec* data_position) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return false;
+ }
+ bool retval = false;
+ auto hal_retval = stack_iface_->getPresentationPosition(
+ [&retval, &remote_delay_report_ns, &total_bytes_readed, &data_position](
+ BluetoothAudioStatus status,
+ const uint64_t& remoteDeviceAudioDelayNanos,
+ uint64_t transmittedOctets,
+ const TimeSpec& transmittedOctetsTimeStamp) {
+ if (status == BluetoothAudioStatus::SUCCESS) {
+ if (remote_delay_report_ns)
+ *remote_delay_report_ns = remoteDeviceAudioDelayNanos;
+ if (total_bytes_readed) *total_bytes_readed = transmittedOctets;
+ if (data_position)
+ *data_position =
+ timespec_convert_from_hal(transmittedOctetsTimeStamp);
+ retval = true;
+ }
+ });
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ return false;
+ }
+ return retval;
+}
+
+void BluetoothAudioSession::UpdateTracksMetadata(
+ const struct source_metadata* source_metadata) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return;
+ }
+
+ ssize_t track_count = source_metadata->track_count;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", "
+ << track_count << " track(s)";
+ if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ return;
+ }
+
+ struct playback_track_metadata* track = source_metadata->tracks;
+ SourceMetadata sourceMetadata;
+ PlaybackTrackMetadata* halMetadata;
+
+ sourceMetadata.tracks.resize(track_count);
+ halMetadata = sourceMetadata.tracks.data();
+ while (track_count && track) {
+ halMetadata->usage = static_cast<AudioUsage>(track->usage);
+ halMetadata->contentType =
+ static_cast<AudioContentType>(track->content_type);
+ halMetadata->gain = track->gain;
+ LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", usage=" << toString(halMetadata->usage)
+ << ", content=" << toString(halMetadata->contentType)
+ << ", gain=" << halMetadata->gain;
+ --track_count;
+ ++track;
+ ++halMetadata;
+ }
+ auto hal_retval = stack_iface_->updateMetadata(sourceMetadata);
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ }
+}
+
+// The control function writes stream to FMQ
+size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
+ size_t bytes) {
+ if (buffer == nullptr || !bytes) return 0;
+ size_t totalWritten = 0;
+ int ms_timeout = kFmqSendTimeoutMs;
+ do {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ if (!IsSessionReady()) break;
+ size_t availableToWrite = mDataMQ->availableToWrite();
+ if (availableToWrite) {
+ if (availableToWrite > (bytes - totalWritten)) {
+ availableToWrite = bytes - totalWritten;
+ }
+
+ if (!mDataMQ->write(static_cast<const uint8_t*>(buffer) + totalWritten,
+ availableToWrite)) {
+ ALOGE("FMQ datapath writing %zu/%zu failed", totalWritten, bytes);
+ return totalWritten;
+ }
+ totalWritten += availableToWrite;
+ } else if (ms_timeout >= kWritePollMs) {
+ lock.unlock();
+ usleep(kWritePollMs * 1000);
+ ms_timeout -= kWritePollMs;
+ } else {
+ ALOGD("out data %zu/%zu overflow %d ms", totalWritten, bytes,
+ (kFmqSendTimeoutMs - ms_timeout));
+ return totalWritten;
+ }
+ } while (totalWritten < bytes);
+ return totalWritten;
+}
+
+// The control function reads stream from FMQ
+size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+ if (buffer == nullptr || !bytes) return 0;
+ size_t totalRead = 0;
+ int ms_timeout = kFmqReceiveTimeoutMs;
+ do {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ if (!IsSessionReady()) break;
+ size_t availableToRead = mDataMQ->availableToRead();
+ if (availableToRead) {
+ if (availableToRead > (bytes - totalRead)) {
+ availableToRead = bytes - totalRead;
+ }
+ if (!mDataMQ->read(static_cast<uint8_t*>(buffer) + totalRead,
+ availableToRead)) {
+ ALOGE("FMQ datapath reading %zu/%zu failed", totalRead, bytes);
+ return totalRead;
+ }
+ totalRead += availableToRead;
+ } else if (ms_timeout >= kReadPollMs) {
+ lock.unlock();
+ usleep(kReadPollMs * 1000);
+ ms_timeout -= kReadPollMs;
+ continue;
+ } else {
+ ALOGD("in data %zu/%zu overflow %d ms", totalRead, bytes,
+ (kFmqReceiveTimeoutMs - ms_timeout));
+ return totalRead;
+ }
+ } while (totalRead < bytes);
+ return totalRead;
+}
+
+std::unique_ptr<BluetoothAudioSessionInstance>
+ BluetoothAudioSessionInstance::instance_ptr =
+ std::unique_ptr<BluetoothAudioSessionInstance>(
+ new BluetoothAudioSessionInstance());
+
+// API to fetch the session
+std::shared_ptr<BluetoothAudioSession>
+BluetoothAudioSessionInstance::GetSessionInstance(
+ const SessionType& session_type) {
+ std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
+ if (!instance_ptr->sessions_map_.empty()) {
+ auto entry = instance_ptr->sessions_map_.find(session_type);
+ if (entry != instance_ptr->sessions_map_.end()) {
+ return entry->second;
+ }
+ }
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ std::make_shared<BluetoothAudioSession>(session_type);
+ instance_ptr->sessions_map_[session_type] = session_ptr;
+ return session_ptr;
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h
new file mode 100644
index 0000000..7bc12e6
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <unordered_map>
+
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <hardware/audio.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::sp;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_1::SessionType;
+
+using BluetoothAudioStatus =
+ ::android::hardware::bluetooth::audio::V2_0::Status;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+static constexpr uint16_t kObserversCookieSize = 0x0010; // 0x0000 ~ 0x000f
+constexpr uint16_t kObserversCookieUndefined =
+ (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
+inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
+ return static_cast<SessionType>(cookie >> 8 & 0x00ff);
+}
+inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
+ return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
+ return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+ kObserversCookieSize;
+}
+
+// This presents the callbacks of started / suspended and session changed,
+// and the bluetooth_audio module uses to receive the status notification
+struct PortStatusCallbacks {
+ // control_result_cb_ - when the Bluetooth stack reports results of
+ // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+ // this callback to report to the bluetooth_audio module.
+ // @param: cookie - indicates which bluetooth_audio output should handle
+ // @param: start_resp - this report is for startStream or not
+ // @param: status - the result of startStream
+ std::function<void(uint16_t cookie, bool start_resp,
+ const BluetoothAudioStatus& status)>
+ control_result_cb_;
+ // session_changed_cb_ - when the Bluetooth stack start / end session, the
+ // BluetoothAudioProvider will invoke this callback to notify to the
+ // bluetooth_audio module.
+ // @param: cookie - indicates which bluetooth_audio output should handle
+ std::function<void(uint16_t cookie)> session_changed_cb_;
+};
+
+class BluetoothAudioSession {
+ private:
+ // using recursive_mutex to allow hwbinder to re-enter again.
+ std::recursive_mutex mutex_;
+ SessionType session_type_;
+
+ // audio control path to use for both software and offloading
+ sp<IBluetoothAudioPort> stack_iface_;
+ // Audio path (FMQ) for software encoding/decoded data
+ std::unique_ptr<DataMQ> mDataMQ;
+ // audio data configuration for both software and offloading
+ AudioConfiguration audio_config_;
+
+ static AudioConfiguration invalidSoftwareAudioConfiguration;
+ static AudioConfiguration invalidOffloadAudioConfiguration;
+
+ // saving those registered bluetooth_audio's callbacks
+ std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
+ observers_;
+
+ bool UpdateDataPath(const DataMQ::Descriptor* dataMQ);
+ bool UpdateAudioConfig(const AudioConfiguration& audio_config);
+ // invoking the registered session_changed_cb_
+ void ReportSessionStatus();
+
+ public:
+ BluetoothAudioSession(const SessionType& session_type);
+
+ // The function helps to check if this session is ready or not
+ // @return: true if the Bluetooth stack has started the specified session
+ bool IsSessionReady();
+
+ // The report function is used to report that the Bluetooth stack has started
+ // this session without any failure, and will invoke session_changed_cb_ to
+ // notify those registered bluetooth_audio outputs
+ void OnSessionStarted(const sp<IBluetoothAudioPort> stack_iface,
+ const DataMQ::Descriptor* dataMQ,
+ const AudioConfiguration& audio_config);
+
+ // The report function is used to report that the Bluetooth stack has ended
+ // the session, and will invoke session_changed_cb_ to notify registered
+ // bluetooth_audio outputs
+ void OnSessionEnded();
+
+ // The report function is used to report that the Bluetooth stack has notified
+ // the result of startStream or suspendStream, and will invoke
+ // control_result_cb_ to notify registered bluetooth_audio outputs
+ void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
+
+ // The control function helps the bluetooth_audio module to register
+ // PortStatusCallbacks
+ // @return: cookie - the assigned number to this bluetooth_audio output
+ uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
+
+ // The control function helps the bluetooth_audio module to unregister
+ // PortStatusCallbacks
+ // @param: cookie - indicates which bluetooth_audio output is
+ void UnregisterStatusCback(uint16_t cookie);
+
+ // The control function is for the bluetooth_audio module to get the current
+ // AudioConfiguration
+ const AudioConfiguration& GetAudioConfig();
+
+ // Those control functions are for the bluetooth_audio module to start,
+ // suspend, stop stream, to check position, and to update metadata.
+ bool StartStream();
+ bool SuspendStream();
+ void StopStream();
+ bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+ uint64_t* total_bytes_readed,
+ timespec* data_position);
+ void UpdateTracksMetadata(const struct source_metadata* source_metadata);
+
+ // The control function writes stream to FMQ
+ size_t OutWritePcmData(const void* buffer, size_t bytes);
+ // The control function read stream from FMQ
+ size_t InReadPcmData(void* buffer, size_t bytes);
+
+ static constexpr PcmParameters kInvalidPcmParameters = {
+ .sampleRate = SampleRate::RATE_UNKNOWN,
+ .channelMode = ChannelMode::UNKNOWN,
+ .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
+ .dataIntervalUs = 0,
+ };
+ // can't be constexpr because of non-literal type
+ static const CodecConfiguration kInvalidCodecConfiguration;
+
+ static constexpr AudioConfiguration& kInvalidSoftwareAudioConfiguration =
+ invalidSoftwareAudioConfiguration;
+ static constexpr AudioConfiguration& kInvalidOffloadAudioConfiguration =
+ invalidOffloadAudioConfiguration;
+};
+
+class BluetoothAudioSessionInstance {
+ public:
+ // The API is to fetch the specified session
+ static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
+ const SessionType& session_type);
+
+ private:
+ static std::unique_ptr<BluetoothAudioSessionInstance> instance_ptr;
+ std::mutex mutex_;
+ std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+ sessions_map_;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..017a611
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionControl {
+ public:
+ // The control API helps to check if session is ready or not
+ // @return: true if the Bluetooth stack has started th specified session
+ static bool IsSessionReady(const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->IsSessionReady();
+ }
+ return false;
+ }
+
+ // The control API helps the bluetooth_audio module to register
+ // PortStatusCallbacks
+ // @return: cookie - the assigned number to this bluetooth_audio output
+ static uint16_t RegisterControlResultCback(
+ const SessionType& session_type, const PortStatusCallbacks& cbacks) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->RegisterStatusCback(cbacks);
+ }
+ return kObserversCookieUndefined;
+ }
+
+ // The control API helps the bluetooth_audio module to unregister
+ // PortStatusCallbacks
+ // @param: cookie - indicates which bluetooth_audio output is
+ static void UnregisterControlResultCback(const SessionType& session_type,
+ uint16_t cookie) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->UnregisterStatusCback(cookie);
+ }
+ }
+
+ // The control API for the bluetooth_audio module to get current
+ // AudioConfiguration
+ static const AudioConfiguration& GetAudioConfig(
+ const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->GetAudioConfig();
+ } else if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ return BluetoothAudioSession::kInvalidOffloadAudioConfiguration;
+ } else {
+ return BluetoothAudioSession::kInvalidSoftwareAudioConfiguration;
+ }
+ }
+
+ // Those control APIs for the bluetooth_audio module to start / suspend / stop
+ // stream, to check position, and to update metadata.
+ static bool StartStream(const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->StartStream();
+ }
+ return false;
+ }
+
+ static bool SuspendStream(const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->SuspendStream();
+ }
+ return false;
+ }
+
+ static void StopStream(const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->StopStream();
+ }
+ }
+
+ static bool GetPresentationPosition(const SessionType& session_type,
+ uint64_t* remote_delay_report_ns,
+ uint64_t* total_bytes_readed,
+ timespec* data_position) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->GetPresentationPosition(
+ remote_delay_report_ns, total_bytes_readed, data_position);
+ }
+ return false;
+ }
+
+ static void UpdateTracksMetadata(
+ const SessionType& session_type,
+ const struct source_metadata* source_metadata) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->UpdateTracksMetadata(source_metadata);
+ }
+ }
+
+ // The control API writes stream to FMQ
+ static size_t OutWritePcmData(const SessionType& session_type,
+ const void* buffer, size_t bytes) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->OutWritePcmData(buffer, bytes);
+ }
+ return 0;
+ }
+
+ // The control API reads stream from FMQ
+ static size_t InReadPcmData(const SessionType& session_type, void* buffer,
+ size_t bytes) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->InReadPcmData(buffer, bytes);
+ }
+ return 0;
+ }
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..267bf8f
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionReport {
+ public:
+ // The API reports the Bluetooth stack has started the session, and will
+ // inform registered bluetooth_audio session
+ static void OnSessionStarted(const SessionType& session_type,
+ const sp<IBluetoothAudioPort> host_iface,
+ const DataMQ::Descriptor* dataMQ,
+ const AudioConfiguration& audio_config) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config);
+ }
+ }
+ // The API reports the Bluetooth stack has ended the session, and will
+ // inform registered bluetooth_audio outputs
+ static void OnSessionEnded(const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->OnSessionEnded();
+ }
+ }
+ // The API reports the Bluetooth stack has replied the result of startStream
+ // or suspendStream, and will inform registered bluetooth_audio outputs
+ static void ReportControlStatus(const SessionType& session_type,
+ const bool& start_resp,
+ const BluetoothAudioStatus& status) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->ReportControlStatus(start_resp, status);
+ }
+ }
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
new file mode 100644
index 0000000..d15db49
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderSessionCodecsDB"
+
+#include "BluetoothAudioSupportedCodecsDB.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+// Default Supported PCM Parameters
+static const ::android::hardware::bluetooth::audio::V2_0::PcmParameters
+ kDefaultSoftwarePcmCapabilities = {
+ .sampleRate = static_cast<
+ android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000),
+ .channelMode =
+ static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
+ .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
+ BitsPerSample::BITS_24 |
+ BitsPerSample::BITS_32)};
+
+static const PcmParameters kDefaultSoftwarePcmCapabilities_2_1 = {
+ .sampleRate = static_cast<SampleRate>(
+ SampleRate::RATE_48000 | SampleRate::RATE_44100 |
+ SampleRate::RATE_32000 | SampleRate::RATE_24000 |
+ SampleRate::RATE_16000 | SampleRate::RATE_8000),
+ .channelMode =
+ static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
+ .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16)};
+
+// Default Supported Codecs
+// SBC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(MONO|STEREO)
+// all blocks | subbands 8 | Loudness
+static const SbcParameters kDefaultOffloadSbcCapability = {
+ .sampleRate =
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+ .channelMode = static_cast<SbcChannelMode>(SbcChannelMode::MONO |
+ SbcChannelMode::JOINT_STEREO),
+ .blockLength = static_cast<SbcBlockLength>(
+ SbcBlockLength::BLOCKS_4 | SbcBlockLength::BLOCKS_8 |
+ SbcBlockLength::BLOCKS_12 | SbcBlockLength::BLOCKS_16),
+ .numSubbands = SbcNumSubbands::SUBBAND_8,
+ .allocMethod = SbcAllocMethod::ALLOC_MD_L,
+ .bitsPerSample = BitsPerSample::BITS_16,
+ .minBitpool = 2,
+ .maxBitpool = 53};
+
+// AAC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(STEREO)
+static const AacParameters kDefaultOffloadAacCapability = {
+ .objectType = AacObjectType::MPEG2_LC,
+ .sampleRate =
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+ .channelMode = ChannelMode::STEREO,
+ .variableBitRateEnabled = AacVariableBitRate::ENABLED,
+ .bitsPerSample = BitsPerSample::BITS_16};
+
+// LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
+// mChannelMode:(DUAL|STEREO)
+static const LdacParameters kDefaultOffloadLdacCapability = {
+ .sampleRate =
+ static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000),
+ .channelMode = static_cast<LdacChannelMode>(LdacChannelMode::DUAL |
+ LdacChannelMode::STEREO),
+ .qualityIndex = LdacQualityIndex::QUALITY_HIGH,
+ .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
+ BitsPerSample::BITS_24 |
+ BitsPerSample::BITS_32)};
+
+// aptX: mSampleRate:(44100|48000), mBitsPerSample:(16), mChannelMode:(STEREO)
+static const AptxParameters kDefaultOffloadAptxCapability = {
+ .sampleRate =
+ static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
+ .channelMode = ChannelMode::STEREO,
+ .bitsPerSample = BitsPerSample::BITS_16,
+};
+
+// aptX HD: mSampleRate:(44100|48000), mBitsPerSample:(24),
+// mChannelMode:(STEREO)
+static const AptxParameters kDefaultOffloadAptxHdCapability = {
+ .sampleRate =
+ static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
+ .channelMode = ChannelMode::STEREO,
+ .bitsPerSample = BitsPerSample::BITS_24,
+};
+
+const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
+ {.codecType = CodecType::SBC, .capabilities = {}},
+ {.codecType = CodecType::AAC, .capabilities = {}},
+ {.codecType = CodecType::LDAC, .capabilities = {}},
+ {.codecType = CodecType::APTX, .capabilities = {}},
+ {.codecType = CodecType::APTX_HD, .capabilities = {}}};
+
+static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield) {
+ bool single = false;
+ uint32_t test_bit = 0x00000001;
+ while (test_bit <= bitmasks && test_bit <= bitfield) {
+ if (bitfield & test_bit && bitmasks & test_bit) {
+ if (single) return false;
+ single = true;
+ }
+ if (test_bit == 0x80000000) break;
+ test_bit <<= 1;
+ }
+ return single;
+}
+
+static bool IsOffloadSbcConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadLdacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAptxConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+static bool IsOffloadAptxHdConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+
+static bool IsOffloadSbcConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getDiscriminator() !=
+ CodecConfiguration::CodecSpecific::hidl_discriminator::sbcConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ }
+ const SbcParameters sbc_data = codec_specific.sbcConfig();
+ if (!IsSingleBit(static_cast<uint32_t>(sbc_data.sampleRate), 0xff) ||
+ !IsSingleBit(static_cast<uint32_t>(sbc_data.channelMode), 0x0f) ||
+ !IsSingleBit(static_cast<uint32_t>(sbc_data.blockLength), 0xf0) ||
+ !IsSingleBit(static_cast<uint32_t>(sbc_data.numSubbands), 0x0c) ||
+ !IsSingleBit(static_cast<uint32_t>(sbc_data.allocMethod), 0x03) ||
+ !IsSingleBit(static_cast<uint32_t>(sbc_data.bitsPerSample), 0x07) ||
+ sbc_data.minBitpool > sbc_data.maxBitpool) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ } else if ((sbc_data.sampleRate & kDefaultOffloadSbcCapability.sampleRate) &&
+ (sbc_data.channelMode &
+ kDefaultOffloadSbcCapability.channelMode) &&
+ (sbc_data.blockLength &
+ kDefaultOffloadSbcCapability.blockLength) &&
+ (sbc_data.numSubbands &
+ kDefaultOffloadSbcCapability.numSubbands) &&
+ (sbc_data.allocMethod &
+ kDefaultOffloadSbcCapability.allocMethod) &&
+ (sbc_data.bitsPerSample &
+ kDefaultOffloadSbcCapability.bitsPerSample) &&
+ (kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
+ sbc_data.maxBitpool <= kDefaultOffloadSbcCapability.maxBitpool)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << toString(codec_specific);
+ return false;
+}
+
+static bool IsOffloadAacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getDiscriminator() !=
+ CodecConfiguration::CodecSpecific::hidl_discriminator::aacConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ }
+ const AacParameters aac_data = codec_specific.aacConfig();
+ if (!IsSingleBit(static_cast<uint32_t>(aac_data.objectType), 0xf0) ||
+ !IsSingleBit(static_cast<uint32_t>(aac_data.sampleRate), 0xff) ||
+ !IsSingleBit(static_cast<uint32_t>(aac_data.channelMode), 0x03) ||
+ !IsSingleBit(static_cast<uint32_t>(aac_data.bitsPerSample), 0x07)) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ } else if ((aac_data.objectType & kDefaultOffloadAacCapability.objectType) &&
+ (aac_data.sampleRate & kDefaultOffloadAacCapability.sampleRate) &&
+ (aac_data.channelMode &
+ kDefaultOffloadAacCapability.channelMode) &&
+ (aac_data.variableBitRateEnabled == AacVariableBitRate::DISABLED ||
+ kDefaultOffloadAacCapability.variableBitRateEnabled ==
+ AacVariableBitRate::ENABLED) &&
+ (aac_data.bitsPerSample &
+ kDefaultOffloadAacCapability.bitsPerSample)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << toString(codec_specific);
+ return false;
+}
+
+static bool IsOffloadLdacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getDiscriminator() !=
+ CodecConfiguration::CodecSpecific::hidl_discriminator::ldacConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ }
+ const LdacParameters ldac_data = codec_specific.ldacConfig();
+ if (!IsSingleBit(static_cast<uint32_t>(ldac_data.sampleRate), 0xff) ||
+ !IsSingleBit(static_cast<uint32_t>(ldac_data.channelMode), 0x07) ||
+ (ldac_data.qualityIndex > LdacQualityIndex::QUALITY_LOW &&
+ ldac_data.qualityIndex != LdacQualityIndex::QUALITY_ABR) ||
+ !IsSingleBit(static_cast<uint32_t>(ldac_data.bitsPerSample), 0x07)) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ } else if ((ldac_data.sampleRate &
+ kDefaultOffloadLdacCapability.sampleRate) &&
+ (ldac_data.channelMode &
+ kDefaultOffloadLdacCapability.channelMode) &&
+ (ldac_data.bitsPerSample &
+ kDefaultOffloadLdacCapability.bitsPerSample)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << toString(codec_specific);
+ return false;
+}
+
+static bool IsOffloadAptxConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getDiscriminator() !=
+ CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ }
+ const AptxParameters aptx_data = codec_specific.aptxConfig();
+ if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
+ !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
+ !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ } else if ((aptx_data.sampleRate &
+ kDefaultOffloadAptxCapability.sampleRate) &&
+ (aptx_data.channelMode &
+ kDefaultOffloadAptxCapability.channelMode) &&
+ (aptx_data.bitsPerSample &
+ kDefaultOffloadAptxCapability.bitsPerSample)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << toString(codec_specific);
+ return false;
+}
+
+static bool IsOffloadAptxHdConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getDiscriminator() !=
+ CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ }
+ const AptxParameters aptx_data = codec_specific.aptxConfig();
+ if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
+ !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
+ !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << toString(codec_specific);
+ return false;
+ } else if ((aptx_data.sampleRate &
+ kDefaultOffloadAptxHdCapability.sampleRate) &&
+ (aptx_data.channelMode &
+ kDefaultOffloadAptxHdCapability.channelMode) &&
+ (aptx_data.bitsPerSample &
+ kDefaultOffloadAptxHdCapability.bitsPerSample)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << toString(codec_specific);
+ return false;
+}
+
+std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+GetSoftwarePcmCapabilities() {
+ return std::vector<
+ ::android::hardware::bluetooth::audio::V2_0::PcmParameters>(
+ 1, kDefaultSoftwarePcmCapabilities);
+}
+
+std::vector<PcmParameters> GetSoftwarePcmCapabilities_2_1() {
+ return std::vector<PcmParameters>(1, kDefaultSoftwarePcmCapabilities_2_1);
+}
+
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+ const ::android::hardware::bluetooth::audio::V2_0::SessionType&
+ session_type) {
+ return GetOffloadCodecCapabilities(static_cast<SessionType>(session_type));
+}
+
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+ const SessionType& session_type) {
+ if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ return std::vector<CodecCapabilities>(0);
+ }
+ std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
+ kDefaultOffloadA2dpCodecCapabilities;
+ for (auto& codec_capability : offload_a2dp_codec_capabilities) {
+ switch (codec_capability.codecType) {
+ case CodecType::SBC:
+ codec_capability.capabilities.sbcCapabilities(
+ kDefaultOffloadSbcCapability);
+ break;
+ case CodecType::AAC:
+ codec_capability.capabilities.aacCapabilities(
+ kDefaultOffloadAacCapability);
+ break;
+ case CodecType::LDAC:
+ codec_capability.capabilities.ldacCapabilities(
+ kDefaultOffloadLdacCapability);
+ break;
+ case CodecType::APTX:
+ codec_capability.capabilities.aptxCapabilities(
+ kDefaultOffloadAptxCapability);
+ break;
+ case CodecType::APTX_HD:
+ codec_capability.capabilities.aptxCapabilities(
+ kDefaultOffloadAptxHdCapability);
+ break;
+ case CodecType::UNKNOWN:
+ codec_capability = {};
+ break;
+ }
+ }
+ return offload_a2dp_codec_capabilities;
+}
+
+bool IsSoftwarePcmConfigurationValid(
+ const ::android::hardware::bluetooth::audio::V2_0::PcmParameters&
+ pcm_config) {
+ if ((pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 &&
+ pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 &&
+ pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 &&
+ pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 &&
+ pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000 &&
+ pcm_config.sampleRate !=
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000) ||
+ (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
+ pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
+ pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
+ (pcm_config.channelMode != ChannelMode::MONO &&
+ pcm_config.channelMode != ChannelMode::STEREO)) {
+ LOG(WARNING) << __func__
+ << ": Invalid PCM Configuration=" << toString(pcm_config);
+ return false;
+ } else if (pcm_config.sampleRate &
+ kDefaultSoftwarePcmCapabilities.sampleRate &&
+ pcm_config.bitsPerSample &
+ kDefaultSoftwarePcmCapabilities.bitsPerSample &&
+ pcm_config.channelMode &
+ kDefaultSoftwarePcmCapabilities.channelMode) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported PCM Configuration=" << toString(pcm_config);
+ return false;
+}
+
+bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config) {
+ if ((pcm_config.sampleRate != SampleRate::RATE_44100 &&
+ pcm_config.sampleRate != SampleRate::RATE_48000 &&
+ pcm_config.sampleRate != SampleRate::RATE_88200 &&
+ pcm_config.sampleRate != SampleRate::RATE_96000 &&
+ pcm_config.sampleRate != SampleRate::RATE_16000 &&
+ pcm_config.sampleRate != SampleRate::RATE_24000) ||
+ (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
+ pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
+ pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
+ (pcm_config.channelMode != ChannelMode::MONO &&
+ pcm_config.channelMode != ChannelMode::STEREO)) {
+ LOG(WARNING) << __func__
+ << ": Invalid PCM Configuration=" << toString(pcm_config);
+ return false;
+ } else if (pcm_config.sampleRate &
+ kDefaultSoftwarePcmCapabilities_2_1.sampleRate &&
+ pcm_config.bitsPerSample &
+ kDefaultSoftwarePcmCapabilities_2_1.bitsPerSample &&
+ pcm_config.channelMode &
+ kDefaultSoftwarePcmCapabilities_2_1.channelMode &&
+ pcm_config.dataIntervalUs != 0) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported PCM Configuration=" << toString(pcm_config);
+ return false;
+}
+
+bool IsOffloadCodecConfigurationValid(const SessionType& session_type,
+ const CodecConfiguration& codec_config) {
+ if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ LOG(ERROR) << __func__
+ << ": Invalid SessionType=" << toString(session_type);
+ return false;
+ } else if (codec_config.encodedAudioBitrate < 0x00000001 ||
+ 0x00ffffff < codec_config.encodedAudioBitrate) {
+ LOG(ERROR) << __func__ << ": Unsupported Codec Configuration="
+ << toString(codec_config);
+ return false;
+ }
+ const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
+ switch (codec_config.codecType) {
+ case CodecType::SBC:
+ if (IsOffloadSbcConfigurationValid(codec_specific)) {
+ return true;
+ }
+ return false;
+ case CodecType::AAC:
+ if (IsOffloadAacConfigurationValid(codec_specific)) {
+ return true;
+ }
+ return false;
+ case CodecType::LDAC:
+ if (IsOffloadLdacConfigurationValid(codec_specific)) {
+ return true;
+ }
+ return false;
+ case CodecType::APTX:
+ if (IsOffloadAptxConfigurationValid(codec_specific)) {
+ return true;
+ }
+ return false;
+ case CodecType::APTX_HD:
+ if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
+ return true;
+ }
+ return false;
+ case CodecType::UNKNOWN:
+ return false;
+ }
+ return false;
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h
new file mode 100644
index 0000000..9b2f680
--- /dev/null
+++ b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.0/types.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_1::SessionType;
+
+std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
+GetSoftwarePcmCapabilities();
+std::vector<PcmParameters> GetSoftwarePcmCapabilities_2_1();
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+ const SessionType& session_type);
+std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
+ const ::android::hardware::bluetooth::audio::V2_0::SessionType&
+ session_type);
+
+bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config);
+bool IsSoftwarePcmConfigurationValid(
+ const ::android::hardware::bluetooth::audio::V2_0::PcmParameters&
+ pcm_config);
+bool IsOffloadCodecConfigurationValid(const SessionType& session_type,
+ const CodecConfiguration& codec_config);
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace android
diff --git a/bluetooth/audio/2.1/types.hal b/bluetooth/audio/2.1/types.hal
new file mode 100644
index 0000000..5604c38
--- /dev/null
+++ b/bluetooth/audio/2.1/types.hal
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.1;
+
+import @2.0::PcmParameters;
+import @2.0::SessionType;
+import @2.0::SampleRate;
+import @2.0::ChannelMode;
+import @2.0::BitsPerSample;
+import @2.0::CodecConfiguration;
+import @2.0::CodecCapabilities;
+
+enum SessionType : @2.0::SessionType {
+ /** Used when encoded by Bluetooth Stack and streaming to LE Audio device */
+ LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+ /** Used when decoded by Bluetooth Stack and streaming to audio framework */
+ LE_AUDIO_SOFTWARE_DECODED_DATAPATH,
+ /** Encoding is done by HW an there is control only */
+ LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ /** Decoding is done by HW an there is control only */
+ LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+};
+
+enum SampleRate : @2.0::SampleRate {
+ RATE_8000 = 0x100,
+ RATE_32000 = 0x200,
+};
+
+/** Used for Software Encoding audio feed parameters */
+struct PcmParameters {
+ SampleRate sampleRate;
+ ChannelMode channelMode;
+ BitsPerSample bitsPerSample;
+ /** Data interval for data transfer */
+ uint32_t dataIntervalUs;
+};
+
+/** Used to configure either a Hardware or Software Encoding session based on session type */
+safe_union AudioConfiguration {
+ PcmParameters pcmConfig;
+ CodecConfiguration codecConfig;
+};
+
+/** Used to specify the capabilities of the different session types */
+safe_union AudioCapabilities {
+ PcmParameters pcmCapabilities;
+ CodecCapabilities codecCapabilities;
+};
diff --git a/bluetooth/audio/2.1/vts/OWNERS b/bluetooth/audio/2.1/vts/OWNERS
new file mode 100644
index 0000000..b6c0813
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/OWNERS
@@ -0,0 +1,3 @@
+include platform/system/bt:/OWNERS
+
+cheneyni@google.com
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..6ec5537
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -0,0 +1,14 @@
+cc_test {
+ name: "VtsHalBluetoothAudioV2_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.audio.common@5.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "android.hardware.bluetooth.audio@2.0",
+ ],
+ shared_libs: [
+ "libfmq",
+ ],
+ test_suites: ["general-tests", "vts"],
+}
diff --git a/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
new file mode 100644
index 0000000..37d1281
--- /dev/null
+++ b/bluetooth/audio/2.1/vts/functional/VtsHalBluetoothAudioV2_1TargetTest.cpp
@@ -0,0 +1,1213 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "bluetooth_audio_hidl_hal_test"
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h>
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using ::android::hardware::bluetooth::audio::V2_1::
+ IBluetoothAudioProvidersFactory;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using BluetoothAudioStatus =
+ ::android::hardware::bluetooth::audio::V2_0::Status;
+using CodecSpecificConfig = ::android::hardware::bluetooth::audio::V2_0::
+ CodecConfiguration::CodecSpecific;
+
+namespace {
+constexpr android::hardware::bluetooth::audio::V2_0::SampleRate
+ a2dp_sample_rates[5] = {
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000};
+constexpr BitsPerSample a2dp_bits_per_samples[4] = {
+ BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24,
+ BitsPerSample::BITS_32};
+constexpr ChannelMode a2dp_channel_modes[3] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+constexpr CodecType a2dp_codec_types[6] = {CodecType::UNKNOWN, CodecType::SBC,
+ CodecType::AAC, CodecType::APTX,
+ CodecType::APTX_HD, CodecType::LDAC};
+
+template <typename T>
+std::vector<T> ExtractValuesFromBitmask(T bitmasks, uint32_t bitfield,
+ bool supported) {
+ std::vector<T> retval;
+ if (!supported) {
+ retval.push_back(static_cast<T>(bitfield));
+ }
+ uint32_t test_bit = 0x00000001;
+ while (test_bit <= static_cast<uint32_t>(bitmasks) && test_bit <= bitfield) {
+ if ((bitfield & test_bit)) {
+ if ((!(bitmasks & test_bit) && !supported) ||
+ ((bitmasks & test_bit) && supported)) {
+ retval.push_back(static_cast<T>(test_bit));
+ }
+ }
+ if (test_bit == 0x80000000) {
+ break;
+ }
+ test_bit <<= 1;
+ }
+ return retval;
+}
+} // namespace
+
+// The base test class for Bluetooth Audio HAL.
+class BluetoothAudioProvidersFactoryHidlTest
+ : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ providers_factory_ =
+ IBluetoothAudioProvidersFactory::getService(GetParam());
+ ASSERT_NE(providers_factory_, nullptr);
+ }
+
+ virtual void TearDown() override { providers_factory_ = nullptr; }
+
+ // A simple test implementation of IBluetoothAudioPort.
+ class BluetoothAudioPort : public ::testing::VtsHalHidlTargetCallbackBase<
+ BluetoothAudioProvidersFactoryHidlTest>,
+ public IBluetoothAudioPort {
+ BluetoothAudioProvidersFactoryHidlTest& parent_;
+
+ public:
+ BluetoothAudioPort(BluetoothAudioProvidersFactoryHidlTest& parent)
+ : parent_(parent) {}
+ virtual ~BluetoothAudioPort() = default;
+
+ Return<void> startStream() override {
+ parent_.audio_provider_->streamStarted(BluetoothAudioStatus::SUCCESS);
+ return Void();
+ }
+
+ Return<void> suspendStream() override {
+ parent_.audio_provider_->streamSuspended(BluetoothAudioStatus::SUCCESS);
+ return Void();
+ }
+
+ Return<void> stopStream() override { return Void(); }
+
+ Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, 0, 0, {.tvSec = 0, .tvNSec = 0});
+ return Void();
+ }
+
+ Return<void> updateMetadata(const SourceMetadata& sourceMetadata __unused) {
+ return Void();
+ }
+ };
+
+ void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+ temp_provider_capabilities_.clear();
+ auto hidl_cb = [&temp_capabilities = this->temp_provider_capabilities_](
+ const hidl_vec<AudioCapabilities>& audioCapabilities) {
+ for (auto audioCapability : audioCapabilities)
+ temp_capabilities.push_back(audioCapability);
+ };
+ auto hidl_retval =
+ providers_factory_->getProviderCapabilities(session_type, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (session_type == SessionType::UNKNOWN) {
+ ASSERT_TRUE(temp_provider_capabilities_.empty());
+ } else if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ // All software paths are mandatory and must have exact 1 "PcmParameters"
+ ASSERT_EQ(temp_provider_capabilities_.size(), 1);
+ ASSERT_EQ(temp_provider_capabilities_[0].getDiscriminator(),
+ AudioCapabilities::hidl_discriminator::pcmCapabilities);
+ } else {
+ uint32_t codec_type_bitmask = 0x00000000;
+ // empty capability means offload is unsupported
+ for (auto audio_capability : temp_provider_capabilities_) {
+ ASSERT_EQ(audio_capability.getDiscriminator(),
+ AudioCapabilities::hidl_discriminator::codecCapabilities);
+ const CodecCapabilities& codec_capabilities =
+ audio_capability.codecCapabilities();
+ // Every codec can present once at most
+ ASSERT_EQ(codec_type_bitmask &
+ static_cast<uint32_t>(codec_capabilities.codecType),
+ 0);
+ switch (codec_capabilities.codecType) {
+ case CodecType::SBC:
+ ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+ CodecCapabilities::Capabilities::hidl_discriminator::
+ sbcCapabilities);
+ break;
+ case CodecType::AAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+ CodecCapabilities::Capabilities::hidl_discriminator::
+ aacCapabilities);
+ break;
+ case CodecType::APTX:
+ FALLTHROUGH_INTENDED;
+ case CodecType::APTX_HD:
+ ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+ CodecCapabilities::Capabilities::hidl_discriminator::
+ aptxCapabilities);
+ break;
+ case CodecType::LDAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+ CodecCapabilities::Capabilities::hidl_discriminator::
+ ldacCapabilities);
+ break;
+ case CodecType::UNKNOWN:
+ break;
+ }
+ codec_type_bitmask |= codec_capabilities.codecType;
+ }
+ }
+ }
+
+ void GetProviderCapabilitiesHelper_2_1(
+ const android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type) {
+ temp_provider_capabilities_2_1_.clear();
+ auto hidl_cb =
+ [&temp_capabilities = this->temp_provider_capabilities_2_1_](
+ const hidl_vec<
+ android::hardware::bluetooth::audio::V2_1::AudioCapabilities>&
+ audioCapabilities) {
+ for (auto audioCapability : audioCapabilities)
+ temp_capabilities.push_back(audioCapability);
+ };
+ auto hidl_retval =
+ providers_factory_->getProviderCapabilities_2_1(session_type, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+
+ // All software paths are mandatory and must have exact 1 "PcmParameters"
+ ASSERT_EQ(temp_provider_capabilities_2_1_.size(), 1);
+ ASSERT_EQ(temp_provider_capabilities_2_1_[0].getDiscriminator(),
+ android::hardware::bluetooth::audio::V2_1::AudioCapabilities::
+ hidl_discriminator::pcmCapabilities);
+ }
+
+ // This helps to open the specified provider and check the openProvider()
+ // has corruct return values. BUT, to keep it simple, it does not consider
+ // the capability, and please do so at the SetUp of each session's test.
+ void OpenProviderHelper(const SessionType& session_type) {
+ BluetoothAudioStatus cb_status;
+ auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_](
+ BluetoothAudioStatus status,
+ const sp<IBluetoothAudioProvider>& provider) {
+ cb_status = status;
+ local_provider = provider;
+ };
+ auto hidl_retval = providers_factory_->openProvider(session_type, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (cb_status == BluetoothAudioStatus::SUCCESS) {
+ ASSERT_NE(session_type, SessionType::UNKNOWN);
+ ASSERT_NE(audio_provider_, nullptr);
+ audio_port_ = new BluetoothAudioPort(*this);
+ } else {
+ // A2DP_HARDWARE_OFFLOAD_DATAPATH is optional
+ ASSERT_TRUE(session_type == SessionType::UNKNOWN ||
+ session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+ ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE);
+ ASSERT_EQ(audio_provider_, nullptr);
+ }
+ }
+
+ // This helps to open the specified provider and check the openProvider_2_1()
+ // has corruct return values. BUT, to keep it simple, it does not consider
+ // the capability, and please do so at the SetUp of each session's test.
+ void OpenProviderHelper_2_1(
+ const android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type) {
+ BluetoothAudioStatus cb_status;
+ auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_2_1_](
+ BluetoothAudioStatus status,
+ const sp<android::hardware::bluetooth::audio::V2_1::
+ IBluetoothAudioProvider>& provider) {
+ cb_status = status;
+ local_provider = provider;
+ };
+ auto hidl_retval =
+ providers_factory_->openProvider_2_1(session_type, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (cb_status == BluetoothAudioStatus::SUCCESS) {
+ ASSERT_NE(
+ session_type,
+ android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN);
+ ASSERT_NE(audio_provider_2_1_, nullptr);
+ audio_port_ = new BluetoothAudioPort(*this);
+ } else {
+ ASSERT_TRUE(
+ session_type ==
+ android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN);
+ ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE);
+ ASSERT_EQ(audio_provider_2_1_, nullptr);
+ }
+ }
+
+ bool IsPcmParametersSupported(const PcmParameters& pcm_parameters) {
+ if (temp_provider_capabilities_.size() != 1 ||
+ temp_provider_capabilities_[0].getDiscriminator() !=
+ AudioCapabilities::hidl_discriminator::pcmCapabilities) {
+ return false;
+ }
+ auto pcm_capability = temp_provider_capabilities_[0].pcmCapabilities();
+ bool is_parameter_valid =
+ (pcm_parameters.sampleRate != android::hardware::bluetooth::audio::
+ V2_0::SampleRate::RATE_UNKNOWN &&
+ pcm_parameters.channelMode != ChannelMode::UNKNOWN &&
+ pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN);
+ bool is_parameter_in_capability =
+ (pcm_capability.sampleRate & pcm_parameters.sampleRate &&
+ pcm_capability.channelMode & pcm_parameters.channelMode &&
+ pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample);
+ return is_parameter_valid && is_parameter_in_capability;
+ }
+
+ bool IsPcmParametersSupported_2_1(
+ const android::hardware::bluetooth::audio::V2_1::PcmParameters&
+ pcm_parameters) {
+ if (temp_provider_capabilities_2_1_.size() != 1 ||
+ temp_provider_capabilities_2_1_[0].getDiscriminator() !=
+ android::hardware::bluetooth::audio::V2_1::AudioCapabilities::
+ hidl_discriminator::pcmCapabilities) {
+ return false;
+ }
+ auto pcm_capability = temp_provider_capabilities_2_1_[0].pcmCapabilities();
+ bool is_parameter_valid =
+ (pcm_parameters.sampleRate != SampleRate::RATE_UNKNOWN &&
+ pcm_parameters.channelMode != ChannelMode::UNKNOWN &&
+ pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
+ pcm_parameters.dataIntervalUs != 0);
+ bool is_parameter_in_capability =
+ (pcm_capability.sampleRate & pcm_parameters.sampleRate &&
+ pcm_capability.channelMode & pcm_parameters.channelMode &&
+ pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample);
+ return is_parameter_valid && is_parameter_in_capability;
+ }
+
+ sp<IBluetoothAudioProvidersFactory> providers_factory_;
+
+ // temp storage saves the specified provider capability by
+ // GetProviderCapabilitiesHelper()
+ std::vector<AudioCapabilities> temp_provider_capabilities_;
+ std::vector<android::hardware::bluetooth::audio::V2_1::AudioCapabilities>
+ temp_provider_capabilities_2_1_;
+
+ // audio_provider_ is for the Bluetooth stack to report session started/ended
+ // and handled audio stream started / suspended
+ sp<IBluetoothAudioProvider> audio_provider_;
+ sp<android::hardware::bluetooth::audio::V2_1::IBluetoothAudioProvider>
+ audio_provider_2_1_;
+
+ // audio_port_ is for the Audio HAL to send stream start/suspend/stop commands
+ // to Bluetooth stack
+ sp<IBluetoothAudioPort> audio_port_;
+
+ static constexpr SessionType session_types_[4] = {
+ SessionType::UNKNOWN, SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH};
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_P(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_P(BluetoothAudioProvidersFactoryHidlTest,
+ OpenProviderAndCheckCapabilitiesBySession) {
+ for (auto session_type : session_types_) {
+ GetProviderCapabilitiesHelper(session_type);
+ OpenProviderHelper(session_type);
+ // We must be able to open a provider if its getProviderCapabilities()
+ // returns non-empty list.
+ EXPECT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+}
+
+/**
+ * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpSoftwareHidlTest
+ : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProvidersFactoryHidlTest::SetUp();
+ GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProvidersFactoryHidlTest::TearDown();
+ }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest,
+ StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
+ bool is_codec_config_valid;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+ BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ if (is_codec_config_valid) {
+ ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ ASSERT_TRUE(dataMQ.isHandleValid());
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ } else {
+ EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ }
+ };
+ AudioConfiguration audio_config = {};
+ PcmParameters pcm_parameters = {};
+ for (auto sample_rate : a2dp_sample_rates) {
+ pcm_parameters.sampleRate = sample_rate;
+ for (auto bits_per_sample : a2dp_bits_per_samples) {
+ pcm_parameters.bitsPerSample = bits_per_sample;
+ for (auto channel_mode : a2dp_channel_modes) {
+ pcm_parameters.channelMode = channel_mode;
+ is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+ audio_config.pcmConfig(pcm_parameters);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ } // ChannelMode
+ } // BitsPerSampple
+ } // SampleRate
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
+ */
+class BluetoothAudioProviderA2dpHardwareHidlTest
+ : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProvidersFactoryHidlTest::SetUp();
+ GetProviderCapabilitiesHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+ OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProvidersFactoryHidlTest::TearDown();
+ }
+
+ bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+
+ void GetOffloadCodecCapabilityHelper(const CodecType& codec_type) {
+ temp_codec_capabilities_ = {};
+ for (auto codec_capability : temp_provider_capabilities_) {
+ if (codec_capability.codecCapabilities().codecType != codec_type) {
+ continue;
+ }
+ temp_codec_capabilities_ = codec_capability.codecCapabilities();
+ }
+ }
+
+ std::vector<CodecSpecificConfig> GetSbcCodecSpecificSupportedList(
+ bool supported) {
+ std::vector<CodecSpecificConfig> sbc_codec_specifics;
+ GetOffloadCodecCapabilityHelper(CodecType::SBC);
+ if (temp_codec_capabilities_.codecType != CodecType::SBC) {
+ return sbc_codec_specifics;
+ }
+ // parse the capability
+ SbcParameters sbc_capability =
+ temp_codec_capabilities_.capabilities.sbcCapabilities();
+ if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+ return sbc_codec_specifics;
+ }
+ std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+ sample_rates = ExtractValuesFromBitmask<
+ android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ sbc_capability.sampleRate, 0xff, supported);
+ std::vector<SbcChannelMode> channel_modes =
+ ExtractValuesFromBitmask<SbcChannelMode>(sbc_capability.channelMode,
+ 0x0f, supported);
+ std::vector<SbcBlockLength> block_lengths =
+ ExtractValuesFromBitmask<SbcBlockLength>(sbc_capability.blockLength,
+ 0xf0, supported);
+ std::vector<SbcNumSubbands> num_subbandss =
+ ExtractValuesFromBitmask<SbcNumSubbands>(sbc_capability.numSubbands,
+ 0x0c, supported);
+ std::vector<SbcAllocMethod> alloc_methods =
+ ExtractValuesFromBitmask<SbcAllocMethod>(sbc_capability.allocMethod,
+ 0x03, supported);
+ std::vector<BitsPerSample> bits_per_samples =
+ ExtractValuesFromBitmask<BitsPerSample>(sbc_capability.bitsPerSample,
+ 0x07, supported);
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ CodecSpecificConfig codec_specific = {};
+ SbcParameters sbc_data;
+ for (auto sample_rate : sample_rates) {
+ for (auto channel_mode : channel_modes) {
+ for (auto block_length : block_lengths) {
+ for (auto num_subbands : num_subbandss) {
+ for (auto alloc_method : alloc_methods) {
+ for (auto bits_per_sample : bits_per_samples) {
+ sbc_data = {.sampleRate = sample_rate,
+ .channelMode = channel_mode,
+ .blockLength = block_length,
+ .numSubbands = num_subbands,
+ .allocMethod = alloc_method,
+ .bitsPerSample = bits_per_sample,
+ .minBitpool = sbc_capability.minBitpool,
+ .maxBitpool = sbc_capability.maxBitpool};
+ codec_specific.sbcConfig(sbc_data);
+ sbc_codec_specifics.push_back(codec_specific);
+ }
+ }
+ }
+ }
+ }
+ }
+ return sbc_codec_specifics;
+ }
+
+ std::vector<CodecSpecificConfig> GetAacCodecSpecificSupportedList(
+ bool supported) {
+ std::vector<CodecSpecificConfig> aac_codec_specifics;
+ GetOffloadCodecCapabilityHelper(CodecType::AAC);
+ if (temp_codec_capabilities_.codecType != CodecType::AAC) {
+ return aac_codec_specifics;
+ }
+ // parse the capability
+ AacParameters aac_capability =
+ temp_codec_capabilities_.capabilities.aacCapabilities();
+ std::vector<AacObjectType> object_types =
+ ExtractValuesFromBitmask<AacObjectType>(aac_capability.objectType, 0xf0,
+ supported);
+ std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+ sample_rates = ExtractValuesFromBitmask<
+ android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ aac_capability.sampleRate, 0xff, supported);
+ std::vector<ChannelMode> channel_modes =
+ ExtractValuesFromBitmask<ChannelMode>(aac_capability.channelMode, 0x03,
+ supported);
+ std::vector<AacVariableBitRate> variable_bit_rate_enableds = {
+ AacVariableBitRate::DISABLED};
+ if (aac_capability.variableBitRateEnabled == AacVariableBitRate::ENABLED) {
+ variable_bit_rate_enableds.push_back(AacVariableBitRate::ENABLED);
+ }
+ std::vector<BitsPerSample> bits_per_samples =
+ ExtractValuesFromBitmask<BitsPerSample>(aac_capability.bitsPerSample,
+ 0x07, supported);
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ CodecSpecificConfig codec_specific = {};
+ AacParameters aac_data;
+ for (auto object_type : object_types) {
+ for (auto sample_rate : sample_rates) {
+ for (auto channel_mode : channel_modes) {
+ for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+ for (auto bits_per_sample : bits_per_samples) {
+ aac_data = {.objectType = object_type,
+ .sampleRate = sample_rate,
+ .channelMode = channel_mode,
+ .variableBitRateEnabled = variable_bit_rate_enabled,
+ .bitsPerSample = bits_per_sample};
+ codec_specific.aacConfig(aac_data);
+ aac_codec_specifics.push_back(codec_specific);
+ }
+ }
+ }
+ }
+ }
+ return aac_codec_specifics;
+ }
+
+ std::vector<CodecSpecificConfig> GetLdacCodecSpecificSupportedList(
+ bool supported) {
+ std::vector<CodecSpecificConfig> ldac_codec_specifics;
+ GetOffloadCodecCapabilityHelper(CodecType::LDAC);
+ if (temp_codec_capabilities_.codecType != CodecType::LDAC) {
+ return ldac_codec_specifics;
+ }
+ // parse the capability
+ LdacParameters ldac_capability =
+ temp_codec_capabilities_.capabilities.ldacCapabilities();
+ std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+ sample_rates = ExtractValuesFromBitmask<
+ android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ ldac_capability.sampleRate, 0xff, supported);
+ std::vector<LdacChannelMode> channel_modes =
+ ExtractValuesFromBitmask<LdacChannelMode>(ldac_capability.channelMode,
+ 0x07, supported);
+ std::vector<LdacQualityIndex> quality_indexes = {
+ LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
+ LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
+ std::vector<BitsPerSample> bits_per_samples =
+ ExtractValuesFromBitmask<BitsPerSample>(ldac_capability.bitsPerSample,
+ 0x07, supported);
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ CodecSpecificConfig codec_specific = {};
+ LdacParameters ldac_data;
+ for (auto sample_rate : sample_rates) {
+ for (auto channel_mode : channel_modes) {
+ for (auto quality_index : quality_indexes) {
+ for (auto bits_per_sample : bits_per_samples) {
+ ldac_data = {.sampleRate = sample_rate,
+ .channelMode = channel_mode,
+ .qualityIndex = quality_index,
+ .bitsPerSample = bits_per_sample};
+ codec_specific.ldacConfig(ldac_data);
+ ldac_codec_specifics.push_back(codec_specific);
+ }
+ }
+ }
+ }
+ return ldac_codec_specifics;
+ }
+
+ std::vector<CodecSpecificConfig> GetAptxCodecSpecificSupportedList(
+ bool is_hd, bool supported) {
+ std::vector<CodecSpecificConfig> aptx_codec_specifics;
+ GetOffloadCodecCapabilityHelper(
+ (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+ if ((is_hd && temp_codec_capabilities_.codecType != CodecType::APTX_HD) ||
+ (!is_hd && temp_codec_capabilities_.codecType != CodecType::APTX)) {
+ return aptx_codec_specifics;
+ }
+ // parse the capability
+ AptxParameters aptx_capability =
+ temp_codec_capabilities_.capabilities.aptxCapabilities();
+ std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate>
+ sample_rates = ExtractValuesFromBitmask<
+ android::hardware::bluetooth::audio::V2_0::SampleRate>(
+ aptx_capability.sampleRate, 0xff, supported);
+ std::vector<ChannelMode> channel_modes =
+ ExtractValuesFromBitmask<ChannelMode>(aptx_capability.channelMode, 0x03,
+ supported);
+ std::vector<BitsPerSample> bits_per_samples =
+ ExtractValuesFromBitmask<BitsPerSample>(aptx_capability.bitsPerSample,
+ 0x07, supported);
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ CodecSpecificConfig codec_specific = {};
+ AptxParameters aptx_data;
+ for (auto sample_rate : sample_rates) {
+ for (auto channel_mode : channel_modes) {
+ for (auto bits_per_sample : bits_per_samples) {
+ aptx_data = {.sampleRate = sample_rate,
+ .channelMode = channel_mode,
+ .bitsPerSample = bits_per_sample};
+ codec_specific.aptxConfig(aptx_data);
+ aptx_codec_specifics.push_back(codec_specific);
+ }
+ }
+ }
+ return aptx_codec_specifics;
+ }
+
+ // temp storage saves the specified codec capability by
+ // GetOffloadCodecCapabilityHelper()
+ CodecCapabilities temp_codec_capabilities_;
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+ StartAndEndA2dpSbcHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {};
+ codec_config.codecType = CodecType::SBC;
+ codec_config.encodedAudioBitrate = 328000;
+ codec_config.peerMtu = 1005;
+ codec_config.isScmstEnabled = false;
+ AudioConfiguration audio_config = {};
+ std::vector<CodecSpecificConfig> sbc_codec_specifics =
+ GetSbcCodecSpecificSupportedList(true);
+ auto hidl_cb = [](BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ };
+ for (auto codec_specific : sbc_codec_specifics) {
+ codec_config.config = codec_specific;
+ audio_config.codecConfig(codec_config);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+ StartAndEndA2dpAacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {};
+ codec_config.codecType = CodecType::AAC;
+ codec_config.encodedAudioBitrate = 320000;
+ codec_config.peerMtu = 1005;
+ codec_config.isScmstEnabled = false;
+ AudioConfiguration audio_config = {};
+ std::vector<CodecSpecificConfig> aac_codec_specifics =
+ GetAacCodecSpecificSupportedList(true);
+ auto hidl_cb = [](BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ };
+ for (auto codec_specific : aac_codec_specifics) {
+ codec_config.config = codec_specific;
+ audio_config.codecConfig(codec_config);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+ StartAndEndA2dpLdacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {};
+ codec_config.codecType = CodecType::LDAC;
+ codec_config.encodedAudioBitrate = 990000;
+ codec_config.peerMtu = 1005;
+ codec_config.isScmstEnabled = false;
+ AudioConfiguration audio_config = {};
+ std::vector<CodecSpecificConfig> ldac_codec_specifics =
+ GetLdacCodecSpecificSupportedList(true);
+ auto hidl_cb = [](BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ };
+ for (auto codec_specific : ldac_codec_specifics) {
+ codec_config.config = codec_specific;
+ audio_config.codecConfig(codec_config);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AptX hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+ StartAndEndA2dpAptxHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+ CodecConfiguration codec_config = {};
+ codec_config.codecType = codec_type;
+ codec_config.encodedAudioBitrate =
+ (codec_type == CodecType::APTX ? 352000 : 576000);
+ codec_config.peerMtu = 1005;
+ codec_config.isScmstEnabled = false;
+ AudioConfiguration audio_config = {};
+ std::vector<CodecSpecificConfig> aptx_codec_specifics =
+ GetAptxCodecSpecificSupportedList(
+ (codec_type == CodecType::APTX_HD ? true : false), true);
+ auto hidl_cb = [](BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ };
+ for (auto codec_specific : aptx_codec_specifics) {
+ codec_config.config = codec_specific;
+ audio_config.codecConfig(codec_config);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * an invalid codec config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
+ StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+ ASSERT_NE(audio_provider_, nullptr);
+
+ std::vector<CodecSpecificConfig> codec_specifics;
+ for (auto codec_type : a2dp_codec_types) {
+ switch (codec_type) {
+ case CodecType::SBC:
+ codec_specifics = GetSbcCodecSpecificSupportedList(false);
+ break;
+ case CodecType::AAC:
+ codec_specifics = GetAacCodecSpecificSupportedList(false);
+ break;
+ case CodecType::LDAC:
+ codec_specifics = GetLdacCodecSpecificSupportedList(false);
+ break;
+ case CodecType::APTX:
+ codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
+ break;
+ case CodecType::APTX_HD:
+ codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
+ break;
+ case CodecType::UNKNOWN:
+ codec_specifics.clear();
+ break;
+ }
+ if (codec_specifics.empty()) {
+ continue;
+ }
+
+ CodecConfiguration codec_config = {};
+ codec_config.codecType = codec_type;
+ codec_config.encodedAudioBitrate = 328000;
+ codec_config.peerMtu = 1005;
+ codec_config.isScmstEnabled = false;
+ AudioConfiguration audio_config = {};
+ auto hidl_cb = [](BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ };
+ for (auto codec_specific : codec_specifics) {
+ codec_config.config = codec_specific;
+ audio_config.codecConfig(codec_config);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareHidlTest
+ : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProvidersFactoryHidlTest::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProvidersFactoryHidlTest::TearDown();
+ }
+
+ static constexpr android::hardware::bluetooth::audio::V2_0::SampleRate
+ hearing_aid_sample_rates_[3] = {
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000,
+ android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000};
+ static constexpr BitsPerSample hearing_aid_bits_per_samples_[3] = {
+ BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+ BitsPerSample::BITS_24};
+ static constexpr ChannelMode hearing_aid_channel_modes_[3] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and
+ * stopped with SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+ OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+ StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+ bool is_codec_config_valid;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+ BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ if (is_codec_config_valid) {
+ ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ ASSERT_TRUE(dataMQ.isHandleValid());
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ } else {
+ EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ }
+ };
+ AudioConfiguration audio_config = {};
+ PcmParameters pcm_parameters = {};
+ for (auto sample_rate : hearing_aid_sample_rates_) {
+ pcm_parameters.sampleRate = sample_rate;
+ for (auto bits_per_sample : hearing_aid_bits_per_samples_) {
+ pcm_parameters.bitsPerSample = bits_per_sample;
+ for (auto channel_mode : hearing_aid_channel_modes_) {
+ pcm_parameters.channelMode = channel_mode;
+ is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+ audio_config.pcmConfig(pcm_parameters);
+ auto hidl_retval =
+ audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ } // ChannelMode
+ } // BitsPerSampple
+ } // SampleRate
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputSoftwareHidlTest
+ : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProvidersFactoryHidlTest::SetUp();
+ GetProviderCapabilitiesHelper_2_1(
+ android::hardware::bluetooth::audio::V2_1::SessionType::
+ LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper_2_1(
+ android::hardware::bluetooth::audio::V2_1::SessionType::
+ LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_2_1_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_2_1_ = nullptr;
+ BluetoothAudioProvidersFactoryHidlTest::TearDown();
+ }
+
+ static constexpr SampleRate le_audio_output_sample_rates_[3] = {
+ SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+ static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
+ BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+ BitsPerSample::BITS_24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[3] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr uint32_t le_audio_output_data_interval_us_[2] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+ OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+ StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+ bool is_codec_config_valid;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+ BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ if (is_codec_config_valid) {
+ ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ ASSERT_TRUE(dataMQ.isHandleValid());
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ } else {
+ EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ tempDataMQ.reset(nullptr);
+ }
+ };
+ android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
+ {};
+ android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {};
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ pcm_parameters.sampleRate = sample_rate;
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ pcm_parameters.bitsPerSample = bits_per_sample;
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ pcm_parameters.channelMode = channel_mode;
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ pcm_parameters.dataIntervalUs = data_interval_us;
+ is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters);
+ audio_config.pcmConfig(pcm_parameters);
+ auto hidl_retval = audio_provider_2_1_->startSession_2_1(
+ audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+ } else {
+ EXPECT_TRUE(tempDataMQ == nullptr);
+ }
+ EXPECT_TRUE(audio_provider_2_1_->endSession().isOk());
+ } // uint32_t (data interval in microseconds)
+ } // ChannelMode
+ } // BitsPerSampple
+ } // SampleRate
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputSoftwareHidlTest
+ : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProvidersFactoryHidlTest::SetUp();
+ GetProviderCapabilitiesHelper_2_1(
+ android::hardware::bluetooth::audio::V2_1::SessionType::
+ LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+ OpenProviderHelper_2_1(android::hardware::bluetooth::audio::V2_1::
+ SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
+ ASSERT_NE(audio_provider_2_1_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_2_1_ = nullptr;
+ BluetoothAudioProvidersFactoryHidlTest::TearDown();
+ }
+
+ static constexpr SampleRate le_audio_output_sample_rates_[3] = {
+ SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+ static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = {
+ BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+ BitsPerSample::BITS_24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[3] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr uint32_t le_audio_output_data_interval_us_[2] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+ OpenLeAudioInputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+ StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
+ bool is_codec_config_valid;
+ std::unique_ptr<DataMQ> tempDataMQ;
+ auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+ BluetoothAudioStatus status,
+ const DataMQ::Descriptor& dataMQ) {
+ if (is_codec_config_valid) {
+ ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+ ASSERT_TRUE(dataMQ.isHandleValid());
+ tempDataMQ.reset(new DataMQ(dataMQ));
+ } else {
+ EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+ EXPECT_FALSE(dataMQ.isHandleValid());
+ tempDataMQ.reset(nullptr);
+ }
+ };
+ android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config =
+ {};
+ android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {};
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ pcm_parameters.sampleRate = sample_rate;
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ pcm_parameters.bitsPerSample = bits_per_sample;
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ pcm_parameters.channelMode = channel_mode;
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ pcm_parameters.dataIntervalUs = data_interval_us;
+ is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters);
+ audio_config.pcmConfig(pcm_parameters);
+ auto hidl_retval = audio_provider_2_1_->startSession_2_1(
+ audio_port_, audio_config, hidl_cb);
+ // HIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(hidl_retval.isOk());
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+ } else {
+ EXPECT_TRUE(tempDataMQ == nullptr);
+ }
+ EXPECT_TRUE(audio_provider_2_1_->endSession().isOk());
+ } // uint32_t (data interval in microseconds)
+ } // ChannelMode
+ } // BitsPerSampple
+ } // SampleRate
+}
+
+static const std::vector<std::string> kAudioInstances =
+ android::hardware::getAllHalInstanceNames(
+ IBluetoothAudioProvidersFactory::descriptor);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProvidersFactoryHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderA2dpSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpHardwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderA2dpHardwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderHearingAidSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderHearingAidSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioOutputSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioOutputSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioInputSoftwareHidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioInputSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
diff --git a/boot/1.0/Android.bp b/boot/1.0/Android.bp
index 5568436..844cf9b 100644
--- a/boot/1.0/Android.bp
+++ b/boot/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.boot@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBootControl.hal",
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index 613c528..e4ad1b9 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -80,7 +80,6 @@
}
}
-// Sanity check Boot::setActiveBootSlot() on good and bad inputs.
TEST_P(BootHidlTest, SetActiveBootSlot) {
Slot curSlot = boot->getCurrentSlot();
Slot otherSlot = curSlot ? 0 : 1;
@@ -117,7 +116,6 @@
}
}
-// Sanity check Boot::setSlotAsUnbootable() on good and bad inputs.
TEST_P(BootHidlTest, SetSlotAsUnbootable) {
Slot curSlot = boot->getCurrentSlot();
Slot otherSlot = curSlot ? 0 : 1;
@@ -193,6 +191,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BootHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BootHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
diff --git a/boot/1.1/Android.bp b/boot/1.1/Android.bp
index 6a8d57a..3f505e6 100644
--- a/boot/1.1/Android.bp
+++ b/boot/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.boot@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBootControl.hal",
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
index 30b965d..c38f257 100644
--- a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -84,6 +84,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BootHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BootHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
diff --git a/broadcastradio/1.0/Android.bp b/broadcastradio/1.0/Android.bp
index 8239d74..5fc120d 100644
--- a/broadcastradio/1.0/Android.bp
+++ b/broadcastradio/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.broadcastradio@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBroadcastRadio.hal",
diff --git a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
index 9897ab7..cac3dd0 100644
--- a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
+++ b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
@@ -728,6 +728,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BroadcastRadioHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, BroadcastRadioHidlTest,
testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index 1cc9b62..5efa3d4 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.broadcastradio@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBroadcastRadio.hal",
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index 4833beb..caf6cbd 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -600,6 +600,7 @@
} while (nextBand());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BroadcastRadioHalTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, BroadcastRadioHalTest,
testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 1040ba1..0ef635e 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.broadcastradio@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAnnouncementListener.hal",
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 694d52a..ca57243 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -813,6 +813,7 @@
closeHandle->close();
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BroadcastRadioHalTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BroadcastRadioHalTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBroadcastRadio::descriptor)),
diff --git a/camera/common/1.0/Android.bp b/camera/common/1.0/Android.bp
index ed64060..bd00dbb 100644
--- a/camera/common/1.0/Android.bp
+++ b/camera/common/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.common@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 668884d..f2125af 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDevice.hal",
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 2dd6094..80733d1 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -15,6 +15,9 @@
*/
#define LOG_TAG "CamDev@1.0-impl"
+
+#include <fcntl.h>
+
#include <hardware/camera.h>
#include <hardware/gralloc1.h>
#include <hidlmemory/mapping.h>
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index 2e5349f..93d1e75 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@3.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDevice.hal",
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 99cdccb..769991c 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -790,8 +790,9 @@
auto it = batch->mBatchBufs.find(buffer.streamId);
if (it != batch->mBatchBufs.end()) {
InflightBatch::BufferBatch& bb = it->second;
+ auto id = buffer.streamId;
pushStreamBuffer(std::move(buffer), bb.mBuffers);
- filledStreams.push_back(buffer.streamId);
+ filledStreams.push_back(id);
} else {
pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
}
diff --git a/camera/device/3.3/Android.bp b/camera/device/3.3/Android.bp
index 679fad6..0f8502b 100644
--- a/camera/device/3.3/Android.bp
+++ b/camera/device/3.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@3.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDeviceSession.hal",
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index e6f42d6..5575366 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@3.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDeviceCallback.hal",
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index b4ebe22..3f088a3 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -656,8 +656,9 @@
auto it = batch->mBatchBufs.find(buffer.streamId);
if (it != batch->mBatchBufs.end()) {
InflightBatch::BufferBatch& bb = it->second;
+ auto id = buffer.streamId;
pushStreamBuffer(std::move(buffer), bb.mBuffers);
- filledStreams.push_back(buffer.streamId);
+ filledStreams.push_back(id);
} else {
pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
}
diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp
index 362a5e6..9496216 100644
--- a/camera/device/3.5/Android.bp
+++ b/camera/device/3.5/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@3.5",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDevice.hal",
diff --git a/camera/device/3.6/Android.bp b/camera/device/3.6/Android.bp
index 19adb34..e6f458c 100644
--- a/camera/device/3.6/Android.bp
+++ b/camera/device/3.6/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.device@3.6",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraDevice.hal",
diff --git a/camera/metadata/3.2/Android.bp b/camera/metadata/3.2/Android.bp
index f58fb28..6e55139 100644
--- a/camera/metadata/3.2/Android.bp
+++ b/camera/metadata/3.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.metadata@3.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/camera/metadata/3.3/Android.bp b/camera/metadata/3.3/Android.bp
index 885f4f9..f11fe2b 100644
--- a/camera/metadata/3.3/Android.bp
+++ b/camera/metadata/3.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.metadata@3.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp
index 6a92458..31218be 100644
--- a/camera/metadata/3.4/Android.bp
+++ b/camera/metadata/3.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.metadata@3.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/camera/metadata/3.5/Android.bp b/camera/metadata/3.5/Android.bp
index 224c369..a28ba43 100644
--- a/camera/metadata/3.5/Android.bp
+++ b/camera/metadata/3.5/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.metadata@3.5",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 876814d..8b67f3f 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.provider@2.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ICameraProvider.hal",
"ICameraProviderCallback.hal",
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 627ddf4..bbb21c7 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -76,7 +76,7 @@
header_libs: [
"camera.device@3.4-external-impl_headers",
"camera.device@3.5-external-impl_headers",
- "camera.device@3.6-external-impl_headers"
+ "camera.device@3.6-external-impl_headers",
],
export_include_dirs: ["."],
}
@@ -150,6 +150,7 @@
"android.hidl.memory@1.0",
"libbinder",
"libcamera_metadata",
+ "libcutils",
"libhardware",
"libhidlbase",
"liblog",
diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp
index 4475f7d..84f4839 100644
--- a/camera/provider/2.4/default/service.cpp
+++ b/camera/provider/2.4/default/service.cpp
@@ -22,6 +22,8 @@
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <binder/ProcessState.h>
+#include <cutils/memory.h>
+#include <cutils/properties.h>
#include <hidl/LegacySupport.h>
using android::status_t;
@@ -41,6 +43,12 @@
// The camera HAL may communicate to other vendor components via
// /dev/vndbinder
android::ProcessState::initWithDriver("/dev/vndbinder");
+
+ // b/166675194
+ if (property_get_bool("ro.vendor.camera.provider24.disable_mem_init", false)) {
+ process_disable_memory_mitigations();
+ }
+
status_t status;
if (kLazyService) {
status = defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index b0aae8e..2099dc0 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -1209,7 +1209,12 @@
return notify;
}
- if (physicalCameraMetadata.size() != request->expectedPhysicalResults.size()) {
+ // Physical device results are only expected in the last/final
+ // partial result notification.
+ bool expectPhysicalResults = !(request->usePartialResult &&
+ (results.partialResult < request->numPartialResults));
+ if (expectPhysicalResults &&
+ (physicalCameraMetadata.size() != request->expectedPhysicalResults.size())) {
ALOGE("%s: Frame %d: Returned physical metadata count %zu "
"must be equal to expected count %zu", __func__, frameNumber,
physicalCameraMetadata.size(), request->expectedPhysicalResults.size());
@@ -1670,7 +1675,7 @@
Return<void> ret;
::android::sp<ICameraDevice> device3_x;
bool retVal = false;
- if (getCameraDeviceVersion(mProviderType, name) == CAMERA_DEVICE_API_VERSION_1_0) {
+ if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
return false;
}
ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp
index 4ca1efb..be71806 100644
--- a/camera/provider/2.5/Android.bp
+++ b/camera/provider/2.5/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.provider@2.5",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraProvider.hal",
diff --git a/camera/provider/2.6/Android.bp b/camera/provider/2.6/Android.bp
index e69819c..6934c17 100644
--- a/camera/provider/2.6/Android.bp
+++ b/camera/provider/2.6/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.camera.provider@2.6",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICameraProvider.hal",
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
index 4982e20..9f289a1 100644
--- a/cas/1.0/Android.bp
+++ b/cas/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.cas@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICas.hal",
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index f9977ff..802dce1 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -12,8 +12,6 @@
"TypeConvert.cpp",
],
- compile_multilib: "32",
-
shared_libs: [
"android.hardware.cas@1.0",
"android.hardware.cas.native@1.0",
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
index 9b09751..f79b32d 100644
--- a/cas/1.0/default/DescramblerImpl.cpp
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "android.hardware.cas@1.0-DescramblerImpl"
#include <hidlmemory/mapping.h>
+#include <inttypes.h>
#include <media/cas/DescramblerAPI.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/AString.h>
@@ -101,7 +102,7 @@
// size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
// but the mapped memory's actual size will be smaller than the reported size.
if (srcBuffer.heapBase.size() > SIZE_MAX) {
- ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+ ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
android_errorWriteLog(0x534e4554, "79376389");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -118,8 +119,8 @@
}
if (!validateRangeForSize(
srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
- ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
- srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+ ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+ "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -135,8 +136,8 @@
// is consistent with the source shared buffer size.
if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid srcOffset and subsample size: "
- "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- srcOffset, totalBytesInSubSamples, srcBuffer.size);
+ "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -153,8 +154,8 @@
// dstOffset against the buffer size too.
if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid dstOffset and subsample size: "
- "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- dstOffset, totalBytesInSubSamples, srcBuffer.size);
+ "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp
index 13217b6..e20298b 100644
--- a/cas/1.1/Android.bp
+++ b/cas/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.cas@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ICas.hal",
"ICasListener.hal",
diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp
index 66a1eb8..dc42a42 100644
--- a/cas/1.1/default/Android.bp
+++ b/cas/1.1/default/Android.bp
@@ -12,8 +12,6 @@
"TypeConvert.cpp",
],
- compile_multilib: "32",
-
shared_libs: [
"android.hardware.cas@1.0",
"android.hardware.cas@1.1",
diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp
index 36dc1a5..309cd3c 100644
--- a/cas/1.1/default/DescramblerImpl.cpp
+++ b/cas/1.1/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl"
#include <hidlmemory/mapping.h>
+#include <inttypes.h>
#include <media/cas/DescramblerAPI.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -92,7 +93,7 @@
// size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
// but the mapped memory's actual size will be smaller than the reported size.
if (srcBuffer.heapBase.size() > SIZE_MAX) {
- ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+ ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
android_errorWriteLog(0x534e4554, "79376389");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -108,8 +109,8 @@
return Void();
}
if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
- ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
- srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+ ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+ "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -125,8 +126,8 @@
// is consistent with the source shared buffer size.
if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid srcOffset and subsample size: "
- "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- srcOffset, totalBytesInSubSamples, srcBuffer.size);
+ "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -143,8 +144,8 @@
// dstOffset against the buffer size too.
if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid dstOffset and subsample size: "
- "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- dstOffset, totalBytesInSubSamples, srcBuffer.size);
+ "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
diff --git a/cas/1.2/Android.bp b/cas/1.2/Android.bp
index fbb38b0..f03b6b7 100644
--- a/cas/1.2/Android.bp
+++ b/cas/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.cas@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICas.hal",
diff --git a/cas/1.2/default/Android.bp b/cas/1.2/default/Android.bp
index 9e53148..94d5b3d 100644
--- a/cas/1.2/default/Android.bp
+++ b/cas/1.2/default/Android.bp
@@ -12,8 +12,6 @@
"TypeConvert.cpp",
],
- compile_multilib: "32",
-
shared_libs: [
"android.hardware.cas@1.0",
"android.hardware.cas@1.1",
diff --git a/cas/1.2/default/DescramblerImpl.cpp b/cas/1.2/default/DescramblerImpl.cpp
index 36dc1a5..309cd3c 100644
--- a/cas/1.2/default/DescramblerImpl.cpp
+++ b/cas/1.2/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl"
#include <hidlmemory/mapping.h>
+#include <inttypes.h>
#include <media/cas/DescramblerAPI.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -92,7 +93,7 @@
// size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
// but the mapped memory's actual size will be smaller than the reported size.
if (srcBuffer.heapBase.size() > SIZE_MAX) {
- ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+ ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
android_errorWriteLog(0x534e4554, "79376389");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -108,8 +109,8 @@
return Void();
}
if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
- ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
- srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+ ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+ "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -125,8 +126,8 @@
// is consistent with the source shared buffer size.
if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid srcOffset and subsample size: "
- "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- srcOffset, totalBytesInSubSamples, srcBuffer.size);
+ "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
@@ -143,8 +144,8 @@
// dstOffset against the buffer size too.
if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
ALOGE("Invalid dstOffset and subsample size: "
- "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- dstOffset, totalBytesInSubSamples, srcBuffer.size);
+ "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+ "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
android_errorWriteLog(0x534e4554, "67962232");
_hidl_cb(toStatus(BAD_VALUE), 0, NULL);
return Void();
diff --git a/cas/native/1.0/Android.bp b/cas/native/1.0/Android.bp
index 633ceb9..6aa4204 100644
--- a/cas/native/1.0/Android.bp
+++ b/cas/native/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.cas.native@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDescrambler.hal",
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 9ea4cdf..8029efa 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -6,13 +6,14 @@
enabled: true,
support_system_process: true,
},
+ vndk_use_version: "2",
srcs: [
"android/hardware/common/*.aidl",
],
stability: "vintf",
backend: {
java: {
- enabled: false,
+ sdk_version: "module_current",
},
cpp: {
enabled: false,
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
new file mode 100644
index 0000000..004adab
--- /dev/null
+++ b/common/fmq/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+ name: "android.hardware.common.fmq",
+ host_supported: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ srcs: [
+ "android/hardware/common/fmq/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+}
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
new file mode 100644
index 0000000..7ac1930
--- /dev/null
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.common.fmq;
+@VintfStability
+parcelable GrantorDescriptor {
+ int offset;
+ long extent;
+}
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
new file mode 100644
index 0000000..2607369
--- /dev/null
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.common.fmq;
+@VintfStability
+parcelable MQDescriptor {
+ android.hardware.common.fmq.GrantorDescriptor[] grantors;
+ ParcelFileDescriptor fileDescriptor;
+ int quantum;
+ int flags;
+}
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
new file mode 100644
index 0000000..2142bdb
--- /dev/null
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.common.fmq;
+@VintfStability
+enum SynchronizedReadWrite {
+ EMPTY = 0,
+}
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
new file mode 100644
index 0000000..1220674
--- /dev/null
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.common.fmq;
+@VintfStability
+enum UnsynchronizedWrite {
+ EMPTY = 0,
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
similarity index 60%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
index cdaf847..ca69d94 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,19 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.common.fmq;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+/*
+ * Included in MQDescriptor, for use with libfmq.
+ */
+@VintfStability
+parcelable GrantorDescriptor {
+ /*
+ * The offset of this descriptor in the shared memory in bytes.
+ */
+ int offset;
+ /*
+ * The size of this descriptor in bytes.
+ */
+ long extent;
+}
diff --git a/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
new file mode 100644
index 0000000..82917d6
--- /dev/null
+++ b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.common.fmq;
+
+import android.hardware.common.fmq.GrantorDescriptor;
+
+/*
+ * For use with libfmq. This is created from an instance of AidlMessageQueue,
+ * and is used to pass information required to create another instance of that
+ * queue for fast communication.
+ * T - is used to specify the type of the payload
+ * Flavor - is used to specify the type of the queue using
+ * android.hardware.common.SynchronizedReadWrite or UnsynchronizedWrite
+ */
+@VintfStability
+parcelable MQDescriptor<T, Flavor> {
+ /*
+ * Describes each of the grantors for the message queue. They are used to
+ * get the readptr, writeptr, dataptr, and the optional EventFlag word
+ * for blocking operations in the shared memory.
+ */
+ GrantorDescriptor[] grantors;
+ /* File descriptor for shared memory used in the message queue */
+ ParcelFileDescriptor fileDescriptor;
+ /* Size of each item, T, in bytes */
+ int quantum;
+ /* EventFlag word for blocking operations */
+ int flags;
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
similarity index 60%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index cdaf847..8c33442 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,14 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.common.fmq;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+/*
+ * For use with android.hardware.common.MQDescriptor to specify which type of
+ * queue to use. SynchronizedReadWrite is single reader, single writer, with no
+ * overflow. All messages written need to be read.
+ */
+@VintfStability
+enum SynchronizedReadWrite {
+ EMPTY,
+}
diff --git a/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
new file mode 100644
index 0000000..24c4cce
--- /dev/null
+++ b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.common.fmq;
+
+/*
+ * For use with android.hardware.common.MQDescriptor to specify which type of
+ * queue to use. UnsynchronizedWrite is single writer, multiple reader, with
+ * overflow. If messages are not read fast enough, they can be overwritten.
+ */
+@VintfStability
+enum UnsynchronizedWrite {
+ EMPTY,
+}
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index ba56832..b2a815f 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -13,46 +13,6 @@
// limitations under the License.
vintf_compatibility_matrix {
- name: "framework_compatibility_matrix.legacy.xml",
- stem: "compatibility_matrix.legacy.xml",
- srcs: [
- "compatibility_matrix.legacy.xml",
- ],
- kernel_configs: [
- // legacy uses O kernel requirements
- "kernel_config_o_3.18",
- "kernel_config_o_4.4",
- "kernel_config_o_4.9",
- ],
-}
-
-vintf_compatibility_matrix {
- name: "framework_compatibility_matrix.1.xml",
- stem: "compatibility_matrix.1.xml",
- srcs: [
- "compatibility_matrix.1.xml",
- ],
- kernel_configs: [
- "kernel_config_o_3.18",
- "kernel_config_o_4.4",
- "kernel_config_o_4.9",
- ],
-}
-
-vintf_compatibility_matrix {
- name: "framework_compatibility_matrix.2.xml",
- stem: "compatibility_matrix.2.xml",
- srcs: [
- "compatibility_matrix.2.xml",
- ],
- kernel_configs: [
- "kernel_config_o_mr1_3.18",
- "kernel_config_o_mr1_4.4",
- "kernel_config_o_mr1_4.9",
- ],
-}
-
-vintf_compatibility_matrix {
name: "framework_compatibility_matrix.3.xml",
stem: "compatibility_matrix.3.xml",
srcs: [
@@ -90,3 +50,15 @@
"kernel_config_r_5.4",
],
}
+
+vintf_compatibility_matrix {
+ name: "framework_compatibility_matrix.current.xml",
+ stem: "compatibility_matrix.current.xml",
+ srcs: [
+ "compatibility_matrix.current.xml",
+ ],
+ kernel_configs: [
+ "kernel_config_current_4.19",
+ "kernel_config_current_5.4",
+ ],
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index e69fc8d..3951666 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -33,7 +33,7 @@
LOCAL_SRC_FILES := compatibility_matrix.empty.xml
else
-# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specify an absolute path
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specifies absolute paths
LOCAL_GENERATED_SOURCES := $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE)
# Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
@@ -77,7 +77,7 @@
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_RELATIVE_PATH := vintf
-# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specify an absolute path
+# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specifies absolute paths
LOCAL_GENERATED_SOURCES := $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)
# Enforce that DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE does not specify required HALs
@@ -92,12 +92,10 @@
endif # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
my_system_matrix_deps := \
- framework_compatibility_matrix.legacy.xml \
- framework_compatibility_matrix.1.xml \
- framework_compatibility_matrix.2.xml \
framework_compatibility_matrix.3.xml \
framework_compatibility_matrix.4.xml \
framework_compatibility_matrix.5.xml \
+ framework_compatibility_matrix.current.xml \
framework_compatibility_matrix.device.xml \
my_framework_matrix_deps += \
diff --git a/compatibility_matrices/CleanSpec.mk b/compatibility_matrices/CleanSpec.mk
index 9b150ed..5b351a5 100644
--- a/compatibility_matrices/CleanSpec.mk
+++ b/compatibility_matrices/CleanSpec.mk
@@ -45,3 +45,6 @@
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.device.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.legacy.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.1.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.2.xml)
diff --git a/compatibility_matrices/compatibility_matrix.1.xml b/compatibility_matrices/compatibility_matrix.1.xml
deleted file mode 100644
index cccf24f..0000000
--- a/compatibility_matrices/compatibility_matrix.1.xml
+++ /dev/null
@@ -1,326 +0,0 @@
-<compatibility-matrix version="1.0" type="framework" level="1">
- <hal format="hidl" optional="false">
- <name>android.hardware.audio</name>
- <version>2.0</version>
- <interface>
- <name>IDevicesFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.audio.effect</name>
- <version>2.0</version>
- <interface>
- <name>IEffectsFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.automotive.evs</name>
- <version>1.0</version>
- <interface>
- <name>IEvsEnumerator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.automotive.vehicle</name>
- <version>2.0</version>
- <interface>
- <name>IVehicle</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.biometrics.fingerprint</name>
- <version>2.1</version>
- <interface>
- <name>IBiometricsFingerprint</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.bluetooth</name>
- <version>1.0</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.boot</name>
- <version>1.0</version>
- <interface>
- <name>IBootControl</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.broadcastradio</name>
- <version>1.0</version>
- <interface>
- <name>IBroadcastRadioFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.camera.provider</name>
- <version>2.4</version>
- <interface>
- <name>ICameraProvider</name>
- <instance>legacy/0</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.configstore</name>
- <version>1.0</version>
- <interface>
- <name>ISurfaceFlingerConfigs</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.contexthub</name>
- <version>1.0</version>
- <interface>
- <name>IContexthub</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.drm</name>
- <version>1.0</version>
- <interface>
- <name>ICryptoFactory</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IDrmFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.dumpstate</name>
- <version>1.0</version>
- <interface>
- <name>IDumpstateDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.gatekeeper</name>
- <version>1.0</version>
- <interface>
- <name>IGatekeeper</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.gnss</name>
- <version>1.0</version>
- <interface>
- <name>IGnss</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.allocator</name>
- <version>2.0</version>
- <interface>
- <name>IAllocator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.composer</name>
- <version>2.1</version>
- <interface>
- <name>IComposer</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.mapper</name>
- <version>2.0</version>
- <interface>
- <name>IMapper</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.health</name>
- <version>1.0</version>
- <interface>
- <name>IHealth</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.ir</name>
- <version>1.0</version>
- <interface>
- <name>IConsumerIr</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.keymaster</name>
- <version>3.0</version>
- <interface>
- <name>IKeymasterDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.light</name>
- <version>2.0</version>
- <interface>
- <name>ILight</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.media.omx</name>
- <version>1.0</version>
- <interface>
- <name>IOmx</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IOmxStore</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.memtrack</name>
- <version>1.0</version>
- <interface>
- <name>IMemtrack</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.nfc</name>
- <version>1.0</version>
- <interface>
- <name>INfc</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.power</name>
- <version>1.0</version>
- <interface>
- <name>IPower</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.radio</name>
- <version>1.0</version>
- <interface>
- <name>IRadio</name>
- <instance>slot1</instance>
- </interface>
- <interface>
- <name>ISap</name>
- <instance>slot1</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.radio.deprecated</name>
- <version>1.0</version>
- <interface>
- <name>IOemHook</name>
- <instance>slot1</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.renderscript</name>
- <version>1.0</version>
- <interface>
- <name>IDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.sensors</name>
- <version>1.0</version>
- <interface>
- <name>ISensors</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.soundtrigger</name>
- <version>2.0</version>
- <interface>
- <name>ISoundTriggerHw</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.thermal</name>
- <version>1.0</version>
- <interface>
- <name>IThermal</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tv.cec</name>
- <version>1.0</version>
- <interface>
- <name>IHdmiCec</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tv.input</name>
- <version>1.0</version>
- <interface>
- <name>ITvInput</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.usb</name>
- <version>1.0</version>
- <interface>
- <name>IUsb</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.vibrator</name>
- <version>1.0</version>
- <interface>
- <name>IVibrator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.vr</name>
- <version>1.0</version>
- <interface>
- <name>IVr</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.wifi</name>
- <version>1.0</version>
- <interface>
- <name>IWifi</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.wifi.supplicant</name>
- <version>1.0</version>
- <interface>
- <name>ISupplicant</name>
- <instance>default</instance>
- </interface>
- </hal>
-</compatibility-matrix>
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index e5e012c..5e1266e 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -432,6 +432,7 @@
<hal format="hidl" optional="true">
<name>android.hardware.tv.cec</name>
<version>1.0</version>
+ <version>2.0</version>
<interface>
<name>IHdmiCec</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index e772b6f..8bc663d 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -467,6 +467,7 @@
<hal format="hidl" optional="true">
<name>android.hardware.tv.cec</name>
<version>1.0</version>
+ <version>2.0</version>
<interface>
<name>IHdmiCec</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.2.xml b/compatibility_matrices/compatibility_matrix.current.xml
similarity index 60%
rename from compatibility_matrices/compatibility_matrix.2.xml
rename to compatibility_matrices/compatibility_matrix.current.xml
index d4f9809..6c8cb58 100644
--- a/compatibility_matrices/compatibility_matrix.2.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -1,7 +1,17 @@
-<compatibility-matrix version="1.0" type="framework" level="2">
+<compatibility-matrix version="1.0" type="framework" level="6">
+ <hal format="hidl" optional="true">
+ <name>android.hardware.atrace</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAtraceDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="false">
<name>android.hardware.audio</name>
- <version>2.0</version>
+ <!-- TODO(b/142480271): remove 6.0 when implemented on reference device. -->
+ <version>6.0</version>
+ <version>7.0</version>
<interface>
<name>IDevicesFactory</name>
<instance>default</instance>
@@ -9,18 +19,65 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.audio.effect</name>
- <version>2.0</version>
+ <!-- TODO(b/142480271): remove 6.0 when implemented on reference device. -->
+ <version>6.0</version>
+ <version>7.0</version>
<interface>
<name>IEffectsFactory</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.automotive.evs</name>
+ <name>android.hardware.authsecret</name>
<version>1.0</version>
<interface>
+ <name>IAuthSecret</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.audiocontrol</name>
+ <version>1.0</version>
+ <version>2.0</version>
+ <interface>
+ <name>IAudioControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.can</name>
+ <version>1.0</version>
+ <interface>
+ <name>ICanBus</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>ICanController</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.evs</name>
+ <version>1.0-1</version>
+ <interface>
<name>IEvsEnumerator</name>
<instance>default</instance>
+ <regex-instance>[a-z]+/[0-9]+</regex-instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.automotive.occupant_awareness</name>
+ <interface>
+ <name>IOccupantAwareness</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.sv</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISurroundView</name>
+ <instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
@@ -32,8 +89,16 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.biometrics.face</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IBiometricsFace</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
- <version>2.1</version>
+ <version>2.1-2</version>
<interface>
<name>IBiometricsFingerprint</name>
<instance>default</instance>
@@ -41,15 +106,23 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.bluetooth</name>
- <version>1.0</version>
+ <version>1.0-1</version>
<interface>
<name>IBluetoothHci</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.bluetooth.audio</name>
+ <version>2.0-1</version>
+ <interface>
+ <name>IBluetoothAudioProvidersFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.boot</name>
- <version>1.0</version>
+ <version>1.1</version>
<interface>
<name>IBootControl</name>
<instance>default</instance>
@@ -64,52 +137,60 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.broadcastradio</name>
+ <version>2.0</version>
+ <interface>
+ <name>IBroadcastRadio</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.camera.provider</name>
- <version>2.4</version>
+ <version>2.4-6</version>
<interface>
<name>ICameraProvider</name>
- <instance>legacy/0</instance>
+ <regex-instance>[^/]+/[0-9]+</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.cas</name>
- <version>1.0</version>
+ <version>1.1-2</version>
<interface>
<name>IMediaCasService</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.configstore</name>
+ <name>android.hardware.confirmationui</name>
<version>1.0</version>
<interface>
- <name>ISurfaceFlingerConfigs</name>
+ <name>IConfirmationUI</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.contexthub</name>
- <version>1.0</version>
+ <version>1.0-1</version>
<interface>
<name>IContexthub</name>
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.drm</name>
- <version>1.0</version>
+ <version>1.3</version>
<interface>
<name>ICryptoFactory</name>
- <instance>default</instance>
+ <regex-instance>.*</regex-instance>
</interface>
<interface>
<name>IDrmFactory</name>
- <instance>default</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.dumpstate</name>
- <version>1.0</version>
+ <version>1.1</version>
<interface>
<name>IDumpstateDevice</name>
<instance>default</instance>
@@ -125,7 +206,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.gnss</name>
- <version>1.0</version>
+ <version>2.0-1</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
@@ -133,7 +214,10 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.allocator</name>
+ <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
<version>2.0</version>
+ <version>3.0</version>
+ <version>4.0</version>
<interface>
<name>IAllocator</name>
<instance>default</instance>
@@ -141,7 +225,7 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.composer</name>
- <version>2.1</version>
+ <version>2.1-4</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
@@ -149,21 +233,39 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.mapper</name>
- <version>2.0</version>
+ <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
+ <version>2.1</version>
+ <version>3.0</version>
+ <version>4.0</version>
<interface>
<name>IMapper</name>
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="hidl" optional="false">
<name>android.hardware.health</name>
- <version>1.0</version>
+ <version>2.1</version>
<interface>
<name>IHealth</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.health.storage</name>
+ <version>1.0</version>
+ <interface>
+ <name>IStorage</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.identity</name>
+ <interface>
+ <name>IIdentityCredentialStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.ir</name>
<version>1.0</version>
<interface>
@@ -171,23 +273,56 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.input.classifier</name>
+ <version>1.0</version>
+ <interface>
+ <name>IInputClassifier</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="false">
<name>android.hardware.keymaster</name>
<version>3.0</version>
+ <version>4.0-1</version>
<interface>
<name>IKeymasterDevice</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.light</name>
- <version>2.0</version>
+ <name>android.hardware.keymaster</name>
+ <version>4.0-1</version>
<interface>
- <name>ILight</name>
+ <name>IKeymasterDevice</name>
+ <instance>strongbox</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.keymint</name>
+ <interface>
+ <name>IKeyMintDevice</name>
+ <instance>default</instance>
+ <instance>strongbox</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.light</name>
+ <interface>
+ <name>ILights</name>
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IComponentStore</name>
+ <regex-instance>default[0-9]*</regex-instance>
+ <regex-instance>vendor[0-9]*_software</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
<version>1.0</version>
<interface>
@@ -208,8 +343,16 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.neuralnetworks</name>
+ <version>1.0-3</version>
+ <interface>
+ <name>IDevice</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.nfc</name>
- <version>1.0</version>
+ <version>1.2</version>
<interface>
<name>INfc</name>
<instance>default</instance>
@@ -223,32 +366,48 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="false">
<name>android.hardware.power</name>
- <version>1.0-1</version>
<interface>
<name>IPower</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.power.stats</name>
+ <version>1.0</version>
+ <interface>
+ <name>IPowerStats</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.radio</name>
- <version>1.0-1</version>
+ <version>1.6</version>
<interface>
<name>IRadio</name>
<instance>slot1</instance>
+ <instance>slot2</instance>
+ <instance>slot3</instance>
</interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.radio</name>
+ <version>1.2</version>
<interface>
<name>ISap</name>
<instance>slot1</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.radio.deprecated</name>
- <version>1.0</version>
+ <name>android.hardware.radio.config</name>
+ <!--
+ See compatibility_matrix.4.xml on versioning of radio config HAL.
+ -->
+ <version>1.1</version>
<interface>
- <name>IOemHook</name>
- <instance>slot1</instance>
+ <name>IRadioConfig</name>
+ <instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
@@ -259,9 +418,26 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.rebootescrow</name>
+ <interface>
+ <name>IRebootEscrow</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>ISecureElement</name>
+ <regex-instance>eSE[1-9][0-9]*</regex-instance>
+ <regex-instance>SIM[1-9][0-9]*</regex-instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.sensors</name>
<version>1.0</version>
+ <version>2.0-1</version>
<interface>
<name>ISensors</name>
<instance>default</instance>
@@ -269,7 +445,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.soundtrigger</name>
- <version>2.0</version>
+ <version>2.0-3</version>
<interface>
<name>ISoundTriggerHw</name>
<instance>default</instance>
@@ -293,7 +469,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.thermal</name>
- <version>1.0-1</version>
+ <version>2.0</version>
<interface>
<name>IThermal</name>
<instance>default</instance>
@@ -302,6 +478,7 @@
<hal format="hidl" optional="true">
<name>android.hardware.tv.cec</name>
<version>1.0</version>
+ <version>2.0</version>
<interface>
<name>IHdmiCec</name>
<instance>default</instance>
@@ -316,17 +493,32 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.tv.tuner</name>
+ <version>1.0</version>
+ <interface>
+ <name>ITuner</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.usb</name>
- <version>1.0-1</version>
+ <version>1.0-2</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.vibrator</name>
+ <name>android.hardware.usb.gadget</name>
<version>1.0-1</version>
<interface>
+ <name>IUsbGadget</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.vibrator</name>
+ <interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
@@ -349,23 +541,23 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.wifi</name>
- <version>1.0-1</version>
+ <version>1.3-4</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.wifi.offload</name>
- <version>1.0</version>
+ <name>android.hardware.wifi.hostapd</name>
+ <version>1.0-2</version>
<interface>
- <name>IOffload</name>
+ <name>IHostapd</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.wifi.supplicant</name>
- <version>1.0</version>
+ <version>1.2-3</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.legacy.xml b/compatibility_matrices/compatibility_matrix.legacy.xml
deleted file mode 100644
index 8a4d2ee..0000000
--- a/compatibility_matrices/compatibility_matrix.legacy.xml
+++ /dev/null
@@ -1,326 +0,0 @@
-<compatibility-matrix version="1.0" type="framework" level="legacy">
- <hal format="hidl" optional="false">
- <name>android.hardware.audio</name>
- <version>2.0</version>
- <interface>
- <name>IDevicesFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.audio.effect</name>
- <version>2.0</version>
- <interface>
- <name>IEffectsFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.automotive.evs</name>
- <version>1.0</version>
- <interface>
- <name>IEvsEnumerator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.automotive.vehicle</name>
- <version>2.0</version>
- <interface>
- <name>IVehicle</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.biometrics.fingerprint</name>
- <version>2.1</version>
- <interface>
- <name>IBiometricsFingerprint</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.bluetooth</name>
- <version>1.0</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.boot</name>
- <version>1.0</version>
- <interface>
- <name>IBootControl</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.broadcastradio</name>
- <version>1.0</version>
- <interface>
- <name>IBroadcastRadioFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.camera.provider</name>
- <version>2.4</version>
- <interface>
- <name>ICameraProvider</name>
- <instance>legacy/0</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.configstore</name>
- <version>1.0</version>
- <interface>
- <name>ISurfaceFlingerConfigs</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.contexthub</name>
- <version>1.0</version>
- <interface>
- <name>IContexthub</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.drm</name>
- <version>1.0</version>
- <interface>
- <name>ICryptoFactory</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IDrmFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.dumpstate</name>
- <version>1.0</version>
- <interface>
- <name>IDumpstateDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.gatekeeper</name>
- <version>1.0</version>
- <interface>
- <name>IGatekeeper</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.gnss</name>
- <version>1.0</version>
- <interface>
- <name>IGnss</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.allocator</name>
- <version>2.0</version>
- <interface>
- <name>IAllocator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.composer</name>
- <version>2.1</version>
- <interface>
- <name>IComposer</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.graphics.mapper</name>
- <version>2.0</version>
- <interface>
- <name>IMapper</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.health</name>
- <version>1.0</version>
- <interface>
- <name>IHealth</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.ir</name>
- <version>1.0</version>
- <interface>
- <name>IConsumerIr</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.keymaster</name>
- <version>3.0</version>
- <interface>
- <name>IKeymasterDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.light</name>
- <version>2.0</version>
- <interface>
- <name>ILight</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.media.omx</name>
- <version>1.0</version>
- <interface>
- <name>IOmx</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IOmxStore</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.memtrack</name>
- <version>1.0</version>
- <interface>
- <name>IMemtrack</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.nfc</name>
- <version>1.0</version>
- <interface>
- <name>INfc</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.power</name>
- <version>1.0</version>
- <interface>
- <name>IPower</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.radio</name>
- <version>1.0</version>
- <interface>
- <name>IRadio</name>
- <instance>slot1</instance>
- </interface>
- <interface>
- <name>ISap</name>
- <instance>slot1</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.radio.deprecated</name>
- <version>1.0</version>
- <interface>
- <name>IOemHook</name>
- <instance>slot1</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.renderscript</name>
- <version>1.0</version>
- <interface>
- <name>IDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.sensors</name>
- <version>1.0</version>
- <interface>
- <name>ISensors</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.soundtrigger</name>
- <version>2.0</version>
- <interface>
- <name>ISoundTriggerHw</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.thermal</name>
- <version>1.0</version>
- <interface>
- <name>IThermal</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tv.cec</name>
- <version>1.0</version>
- <interface>
- <name>IHdmiCec</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tv.input</name>
- <version>1.0</version>
- <interface>
- <name>ITvInput</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.usb</name>
- <version>1.0</version>
- <interface>
- <name>IUsb</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.vibrator</name>
- <version>1.0</version>
- <interface>
- <name>IVibrator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.vr</name>
- <version>1.0</version>
- <interface>
- <name>IVr</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.wifi</name>
- <version>1.0</version>
- <interface>
- <name>IWifi</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.wifi.supplicant</name>
- <version>1.0</version>
- <interface>
- <name>ISupplicant</name>
- <instance>default</instance>
- </interface>
- </hal>
-</compatibility-matrix>
diff --git a/prebuilt_hashes/Android.bp b/compatibility_matrices/exclude/Android.bp
similarity index 60%
rename from prebuilt_hashes/Android.bp
rename to compatibility_matrices/exclude/Android.bp
index 4692b76..d7bf635 100644
--- a/prebuilt_hashes/Android.bp
+++ b/compatibility_matrices/exclude/Android.bp
@@ -1,10 +1,10 @@
-// Copyright (C) 2018 The Android Open Source Project
+// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,19 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-python_binary_host {
- name: "dump_hals_for_release",
-
- srcs: [
- "dump_hals_for_release.py",
+cc_library_host_static {
+ name: "libvintf_fcm_exclude",
+ cflags: [
+ "-Wall",
+ "-Werror",
],
-
- version: {
- py2: {
- enabled: true,
- },
- py3: {
- enabled: false,
- },
- },
+ static_libs: [
+ "libbase",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ srcs: [
+ "fcm_exclude.cpp",
+ ],
}
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
new file mode 100644
index 0000000..849df94
--- /dev/null
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+
+#include <android-base/strings.h>
+#include <vintf/fcm_exclude.h>
+
+namespace android::vintf::details {
+
+// The predicate to VintfObject::checkMissingHalsInMatrices.
+bool ShouldCheckMissingHalsInFcm(const std::string& package) {
+ using std::placeholders::_1;
+
+ static std::vector<std::string> included_prefixes{
+ // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
+ // matrix is checked.
+ "android.hardware.",
+ };
+
+ static std::vector<std::string> excluded_prefixes{
+ // Packages without top level interfaces (including types-only packages) are exempted.
+ "android.hardware.camera.device@",
+ "android.hardware.gnss.measurement_corrections@1.",
+ "android.hardware.graphics.bufferqueue@",
+
+ // Test packages are exempted.
+ "android.hardware.tests.",
+ };
+
+ static std::vector<std::string> excluded_exact{
+ // Packages without top level interfaces (including types-only packages) are exempted.
+ // HIDL
+ "android.hardware.cas.native@1.0",
+ "android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.radio.config@1.2",
+ // AIDL
+ "android.hardware.common",
+ "android.hardware.common.fmq",
+ "android.hardware.graphics.common",
+ "android.hardware.keymaster",
+
+ // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
+ // does not depend on this HAL, hence it is not declared in any manifests or matrices.
+ "android.hardware.fastboot@1.0",
+ "android.hardware.fastboot@1.1",
+
+ // Deprecated HALs.
+ // HIDL
+ // TODO(b/171260360) Remove when HAL definition is removed
+ "android.hardware.audio.effect@2.0",
+ "android.hardware.audio@2.0",
+ // TODO(b/171260613) Remove when HAL definition is removed
+ "android.hardware.health@1.0",
+ // TODO(b/171260670) Remove when HAL definition is removed
+ "android.hardware.nfc@1.0",
+ // TODO(b/171260715) Remove when HAL definition is removed
+ "android.hardware.radio.deprecated@1.0",
+ };
+
+ auto package_has_prefix = [&](const std::string& prefix) {
+ return android::base::StartsWith(package, prefix);
+ };
+
+ // Only check packageAndVersions that are in the include list and not in the exclude list.
+ if (!std::any_of(included_prefixes.begin(), included_prefixes.end(), package_has_prefix)) {
+ return false;
+ }
+
+ if (std::find(excluded_exact.begin(), excluded_exact.end(), package) != excluded_exact.end()) {
+ return false;
+ }
+
+ return !std::any_of(excluded_prefixes.begin(), excluded_prefixes.end(), package_has_prefix);
+}
+
+} // namespace android::vintf::details
diff --git a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
new file mode 100644
index 0000000..f74c217
--- /dev/null
+++ b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace android::vintf::details {
+
+// Determine whether VINTF checks |package| is missing from FCMs.
+// |package| can be a HIDL package and version like
+// "android.hardware.foo@1.0", or an AIDL package name like
+// "android.hardware.foo".
+bool ShouldCheckMissingHalsInFcm(const std::string& package);
+
+} // namespace android::vintf::details
diff --git a/configstore/1.0/vts/functional/VtsHalConfigstoreV1_0TargetTest.cpp b/configstore/1.0/vts/functional/VtsHalConfigstoreV1_0TargetTest.cpp
index 8a1a313..34a40cf 100644
--- a/configstore/1.0/vts/functional/VtsHalConfigstoreV1_0TargetTest.cpp
+++ b/configstore/1.0/vts/functional/VtsHalConfigstoreV1_0TargetTest.cpp
@@ -140,6 +140,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfigstoreHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ConfigstoreHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISurfaceFlingerConfigs::descriptor)),
diff --git a/confirmationui/1.0/Android.bp b/confirmationui/1.0/Android.bp
index a22067a..15c4f18 100644
--- a/confirmationui/1.0/Android.bp
+++ b/confirmationui/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.confirmationui@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IConfirmationResultCallback.hal",
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
index d953ab0..1b21b0a 100644
--- a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -473,6 +473,7 @@
ASSERT_EQ(expected, result.value());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfirmationUIHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ConfirmationUIHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConfirmationUI::descriptor)),
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
index 71dd978..be30d61 100644
--- a/contexthub/1.0/Android.bp
+++ b/contexthub/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.contexthub@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IContexthub.hal",
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
index 5f83a22..a08c520 100644
--- a/contexthub/1.0/default/Contexthub.cpp
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -155,10 +155,10 @@
.message = static_cast<const uint8_t *>(msg.msg.data()),
};
- // Use a dummy to prevent send_message with empty message from failing prematurely
- static uint8_t dummy;
+ // Use a placeholder to prevent send_message with empty message from failing prematurely
+ static uint8_t placeholder;
if (txMsg.message_len == 0 && txMsg.message == nullptr) {
- txMsg.message = &dummy;
+ txMsg.message = &placeholder;
}
ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
@@ -255,7 +255,7 @@
memcpy(rsp, msg, sizeof(*rsp));
- // No sanity checks on return values
+ // No validations on return values
return true;
}
diff --git a/contexthub/1.1/Android.bp b/contexthub/1.1/Android.bp
index 649f1db..9ee8e76 100644
--- a/contexthub/1.1/Android.bp
+++ b/contexthub/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.contexthub@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IContexthub.hal",
diff --git a/current.txt b/current.txt
index 6696516..8c7682e 100644
--- a/current.txt
+++ b/current.txt
@@ -765,3 +765,19 @@
2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
+
+# ABI preserving changes to HALs during Android S
+2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient
+3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types
+9679f27a42f75781c8993ef163ed92808a1928de186639834841d0b8e326e63d android.hardware.gatekeeper@1.0::IGatekeeper
+40456eb90ea88b62d18ad3fbf1da8917981cd55ac04ce69c8e058d49ff5beff4 android.hardware.keymaster@3.0::IKeymasterDevice
+6017b4f2481feb0fffceae81c62bc372c898998b2d8fe69fbd39859d3a315e5e android.hardware.keymaster@4.0::IKeymasterDevice
+dabe23dde7c9e3ad65c61def7392f186d7efe7f4216f9b6f9cf0863745b1a9f4 android.hardware.keymaster@4.1::IKeymasterDevice
+cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
+9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
+9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
+0f53d70e1eadf8d987766db4bf6ae2048004682168f4cab118da576787def3fa android.hardware.radio@1.0::types
+
+# HALs released in Android S
+# NOTE: waiting to freeze HALs until later in the release
+# NOTE: new HALs are recommended to be in AIDL
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
index 9049af2..44fb837 100644
--- a/drm/1.0/Android.bp
+++ b/drm/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.drm@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICryptoFactory.hal",
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index ed6bcde..93b3278 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -1,3 +1,17 @@
+// Copyright (C) 2016-2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
cc_library_static {
name: "android.hardware.drm@1.0-helper",
vendor_available: true,
@@ -21,3 +35,111 @@
],
export_include_dirs : ["include"]
}
+
+soong_config_module_type {
+ name: "android_hardware_drm_1_0_multilib",
+ module_type: "cc_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: ["TARGET_ENABLE_MEDIADRM_64"],
+ properties: ["compile_multilib"],
+}
+
+android_hardware_drm_1_0_multilib {
+ name: "android.hardware.drm@1.0-multilib-lib",
+ compile_multilib: "32",
+ soong_config_variables: {
+ TARGET_ENABLE_MEDIADRM_64: {
+ compile_multilib: "both",
+ }
+ }
+}
+
+android_hardware_drm_1_0_multilib {
+ name: "android.hardware.drm@1.0-multilib-exe",
+ compile_multilib: "32",
+ soong_config_variables: {
+ TARGET_ENABLE_MEDIADRM_64: {
+ compile_multilib: "first",
+ }
+ }
+}
+
+cc_defaults {
+ name: "android.hardware.drm@1.0-service-defaults",
+ proprietary: true,
+ relative_install_path: "hw",
+ include_dirs: ["hardware/interfaces/drm"],
+ header_libs: ["media_plugin_headers"],
+ static_libs: ["android.hardware.drm@1.0-helper"],
+
+ shared_libs: [
+ "android.hardware.drm@1.0",
+ "android.hidl.memory@1.0",
+ "libhidlbase",
+ "libhardware",
+ "liblog",
+ "libutils",
+ "libbinder",
+ ],
+}
+
+//############ Build legacy drm service ############
+
+cc_binary {
+ name: "android.hardware.drm@1.0-service",
+ defaults: [
+ "android.hardware.drm@1.0-multilib-exe",
+ "android.hardware.drm@1.0-service-defaults"
+ ],
+ init_rc: ["android.hardware.drm@1.0-service.rc"],
+ srcs: ["service.cpp"],
+}
+
+//############ Build legacy drm lazy service ############
+
+cc_binary {
+ name: "android.hardware.drm@1.0-service-lazy",
+ defaults: [
+ "android.hardware.drm@1.0-multilib-exe",
+ "android.hardware.drm@1.0-service-defaults"
+ ],
+ overrides: ["android.hardware.drm@1.0-service"],
+ init_rc: ["android.hardware.drm@1.0-service-lazy.rc"],
+ srcs: ["serviceLazy.cpp"],
+}
+
+//############ Build legacy drm impl library ############
+
+cc_library_shared {
+ name: "android.hardware.drm@1.0-impl",
+ defaults: ["android.hardware.drm@1.0-multilib-lib"],
+ proprietary: true,
+ relative_install_path: "hw",
+
+ include_dirs: [
+ "frameworks/native/include",
+ "frameworks/av/include",
+ ],
+
+ shared_libs: [
+ "android.hardware.drm@1.0",
+ "android.hidl.memory@1.0",
+ "libcutils",
+ "libhidlbase",
+ "libhidlmemory",
+ "liblog",
+ "libstagefright_foundation",
+ "libutils",
+ ],
+
+ static_libs: ["android.hardware.drm@1.0-helper"],
+
+ srcs: [
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ "CryptoFactory.cpp",
+ "CryptoPlugin.cpp",
+ "LegacyPluginPath.cpp",
+ "TypeConvert.cpp",
+ ],
+}
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
deleted file mode 100644
index 9016dc3..0000000
--- a/drm/1.0/default/Android.mk
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2016 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.
-
-
-############# Build legacy drm service ############
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_SRC_FILES := service.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm lazy service ############
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
-LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
-LOCAL_SRC_FILES := serviceLazy.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm impl library ############
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.drm@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
- DrmFactory.cpp \
- DrmPlugin.cpp \
- CryptoFactory.cpp \
- CryptoPlugin.cpp \
- LegacyPluginPath.cpp \
- TypeConvert.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- android.hardware.drm@1.0 \
- android.hidl.memory@1.0 \
- libcutils \
- libhidlbase \
- libhidlmemory \
- liblog \
- libstagefright_foundation \
- libutils \
-
-LOCAL_STATIC_LIBRARIES := \
- android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
- frameworks/native/include \
- frameworks/av/include
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this impl as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
deleted file mode 100644
index 1b5a975..0000000
--- a/drm/1.0/default/common_default_service.mk
+++ /dev/null
@@ -1,44 +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 $(CLEAR_VARS)
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SHARED_LIBRARIES := \
- android.hardware.drm@1.0 \
- android.hidl.memory@1.0 \
- libhidlbase \
- libhardware \
- liblog \
- libutils \
- libbinder \
-
-LOCAL_STATIC_LIBRARIES := \
- android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
- hardware/interfaces/drm
-
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers
-
-# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
-# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 8fd258a..0545c70 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -43,12 +43,12 @@
"android.hardware.drm@1.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
export_shared_lib_headers: [
@@ -76,12 +76,12 @@
"android.hardware.drm@1.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
arch: {
diff --git a/drm/1.0/vts/functional/drm_hal_test_main.cpp b/drm/1.0/vts/functional/drm_hal_test_main.cpp
index fd2538b..ccbf51e 100644
--- a/drm/1.0/vts/functional/drm_hal_test_main.cpp
+++ b/drm/1.0/vts/functional/drm_hal_test_main.cpp
@@ -51,21 +51,27 @@
return allInstanceUuidCombos;
}();
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorFactoryTest);
INSTANTIATE_TEST_CASE_P(DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorPluginTest);
INSTANTIATE_TEST_CASE_P(DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorDecryptTest);
INSTANTIATE_TEST_CASE_P(DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyFactoryTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyFactoryTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyPluginTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyPluginTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyDecryptTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyDecryptTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
diff --git a/drm/1.1/Android.bp b/drm/1.1/Android.bp
index 16010a6..0af4cf4 100644
--- a/drm/1.1/Android.bp
+++ b/drm/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.drm@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICryptoFactory.hal",
diff --git a/drm/1.1/vts/functional/drm_hal_test_main.cpp b/drm/1.1/vts/functional/drm_hal_test_main.cpp
index c6965bd..2ecc6b4 100644
--- a/drm/1.1/vts/functional/drm_hal_test_main.cpp
+++ b/drm/1.1/vts/functional/drm_hal_test_main.cpp
@@ -48,5 +48,6 @@
return allInstancesWithClearKeyUuid;
}();
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyTest, testing::ValuesIn(kAllInstances),
PrintParamInstanceToString);
diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp
index 9104aa9..f1c60de 100644
--- a/drm/1.2/Android.bp
+++ b/drm/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.drm@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ICryptoFactory.hal",
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index 9aed4ee..271cc04 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -31,12 +31,12 @@
"android.hardware.drm@1.2",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
export_shared_lib_headers: [
@@ -63,11 +63,11 @@
"android.hardware.drm@1.0",
"android.hardware.drm@1.2",
"android.hidl.allocator@1.0",
+ "libcrypto",
"libhidlmemory",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
arch: {
diff --git a/drm/1.2/vts/functional/drm_hal_test_main.cpp b/drm/1.2/vts/functional/drm_hal_test_main.cpp
index ea6e63d..2eb18f1 100644
--- a/drm/1.2/vts/functional/drm_hal_test_main.cpp
+++ b/drm/1.2/vts/functional/drm_hal_test_main.cpp
@@ -57,8 +57,10 @@
return allInstanceUuidCombos;
}();
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalTest, testing::ValuesIn(kAllInstances),
PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyTestV1_2);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyTestV1_2, testing::ValuesIn(kAllInstances),
PrintParamInstanceToString);
diff --git a/drm/1.3/Android.bp b/drm/1.3/Android.bp
index b0ffcb9..9a2b9e1 100644
--- a/drm/1.3/Android.bp
+++ b/drm/1.3/Android.bp
@@ -3,12 +3,9 @@
hidl_interface {
name: "android.hardware.drm@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
- "IDrmFactory.hal",
"ICryptoFactory.hal",
+ "IDrmFactory.hal",
],
interfaces: [
"android.hardware.drm@1.0",
diff --git a/drm/1.3/vts/functional/drm_hal_test_main.cpp b/drm/1.3/vts/functional/drm_hal_test_main.cpp
index 02b45ea..b8f64c0 100644
--- a/drm/1.3/vts/functional/drm_hal_test_main.cpp
+++ b/drm/1.3/vts/functional/drm_hal_test_main.cpp
@@ -81,12 +81,15 @@
return allInstanceUuidCombos;
}();
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorFactoryTest);
INSTANTIATE_TEST_CASE_P(PerInstanceUuidV1_0, DrmHalVendorFactoryTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorPluginTest);
INSTANTIATE_TEST_CASE_P(PerInstanceUuidV1_0, DrmHalVendorPluginTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalVendorDecryptTest);
INSTANTIATE_TEST_CASE_P(PerInstanceUuidV1_0, DrmHalVendorDecryptTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
index 3d47550..5d9eefc 100644
--- a/dumpstate/1.0/Android.bp
+++ b/dumpstate/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.dumpstate@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IDumpstateDevice.hal",
],
diff --git a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
index 343d4c9..0c747b2 100644
--- a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
+++ b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
@@ -100,6 +100,7 @@
native_handle_delete(handle);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, DumpstateHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)),
diff --git a/dumpstate/1.1/Android.bp b/dumpstate/1.1/Android.bp
index 2aa8c82..75805df 100644
--- a/dumpstate/1.1/Android.bp
+++ b/dumpstate/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.dumpstate@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDumpstateDevice.hal",
diff --git a/dumpstate/1.1/default/main.cpp b/dumpstate/1.1/default/main.cpp
index 3c17e18..4510f63 100644
--- a/dumpstate/1.1/default/main.cpp
+++ b/dumpstate/1.1/default/main.cpp
@@ -116,7 +116,7 @@
configureRpcThreadpool(1, true);
- sp<DumpstateDevice> dumpstate(new DumpstateDevice);
+ auto dumpstate = sp<DumpstateDevice>::make();
auto serviceRegistrar = LazyServiceRegistrar::getInstance();
if (serviceRegistrar.registerService(dumpstate) != ::android::OK) {
diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
index cbdd87b..1bef663 100644
--- a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
+++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <functional>
+#include <tuple>
#include <vector>
#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
@@ -27,6 +28,7 @@
#include <cutils/native_handle.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <log/log.h>
@@ -39,13 +41,18 @@
using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
using ::android::hardware::dumpstate::V1_1::toString;
-class DumpstateHidl1_1Test : public ::testing::TestWithParam<std::string> {
+// Base class common to all dumpstate HAL v1.1 tests.
+template <typename T>
+class DumpstateHidl1_1TestBase : public ::testing::TestWithParam<T> {
protected:
virtual void SetUp() override { GetService(); }
+ virtual std::string GetInstanceName() = 0;
+
void GetService() {
- dumpstate = IDumpstateDevice::getService(GetParam());
- ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance";
+ const std::string instance_name = GetInstanceName();
+ dumpstate = IDumpstateDevice::getService(instance_name);
+ ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance " << instance_name;
}
void ToggleVerboseLogging(bool enable) {
@@ -78,77 +85,76 @@
sp<IDumpstateDevice> dumpstate;
};
-#define TEST_FOR_DUMPSTATE_MODE(name, body, mode) \
- TEST_P(DumpstateHidl1_1Test, name##_##mode) { body(DumpstateMode::mode); }
+// Tests that don't need to iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1GeneralTest : public DumpstateHidl1_1TestBase<std::string> {
+ protected:
+ virtual std::string GetInstanceName() override { return GetParam(); }
+};
-// We use a macro to define individual test cases instead of hidl_enum_range<> because some HAL
-// implementations are lazy and may call exit() at the end of dumpstateBoard(), which would cause
-// DEAD_OBJECT errors after the first iteration. Separate cases re-get the service each time as part
-// of SetUp(), and also provide better separation of concerns when specific modes are problematic.
-#define TEST_FOR_ALL_DUMPSTATE_MODES(name, body) \
- TEST_FOR_DUMPSTATE_MODE(name, body, FULL); \
- TEST_FOR_DUMPSTATE_MODE(name, body, INTERACTIVE); \
- TEST_FOR_DUMPSTATE_MODE(name, body, REMOTE); \
- TEST_FOR_DUMPSTATE_MODE(name, body, WEAR); \
- TEST_FOR_DUMPSTATE_MODE(name, body, CONNECTIVITY); \
- TEST_FOR_DUMPSTATE_MODE(name, body, WIFI); \
- TEST_FOR_DUMPSTATE_MODE(name, body, DEFAULT); \
- TEST_FOR_DUMPSTATE_MODE(name, body, PROTO);
+// Tests that iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1PerModeTest
+ : public DumpstateHidl1_1TestBase<std::tuple<std::string, DumpstateMode>> {
+ protected:
+ virtual std::string GetInstanceName() override { return std::get<0>(GetParam()); }
+
+ DumpstateMode GetMode() { return std::get<1>(GetParam()); }
+
+ // Will only execute additional_assertions when status == expected.
+ void AssertStatusForMode(const Return<DumpstateStatus>& status, const DumpstateStatus expected,
+ std::function<void()> additional_assertions = nullptr) {
+ ASSERT_TRUE(status.isOk())
+ << "Status should be ok and return a more specific DumpstateStatus: "
+ << status.description();
+ if (GetMode() == DumpstateMode::DEFAULT) {
+ ASSERT_EQ(expected, status)
+ << "Required mode (DumpstateMode::" << toString(GetMode())
+ << "): status should be DumpstateStatus::" << toString(expected)
+ << ", but got DumpstateStatus::" << toString(status);
+ } else {
+ // The rest of the modes are optional to support, but they MUST return either the
+ // expected value or UNSUPPORTED_MODE.
+ ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
+ << "Optional mode (DumpstateMode::" << toString(GetMode())
+ << "): status should be DumpstateStatus::" << toString(expected)
+ << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
+ << toString(status);
+ }
+ if (status == expected && additional_assertions != nullptr) {
+ additional_assertions();
+ }
+ }
+};
constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000; // 30 seconds
-// Will only execute additional_assertions when status == expected.
-void AssertStatusForMode(const DumpstateMode mode, const Return<DumpstateStatus>& status,
- const DumpstateStatus expected,
- std::function<void()> additional_assertions = nullptr) {
- ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
- << status.description();
- if (mode == DumpstateMode::DEFAULT) {
- ASSERT_EQ(expected, status) << "Required mode (DumpstateMode::" << toString(mode)
- << "): status should be DumpstateStatus::" << toString(expected)
- << ", but got DumpstateStatus::" << toString(status);
- } else {
- // The rest of the modes are optional to support, but they MUST return either the expected
- // value or UNSUPPORTED_MODE.
- ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
- << "Optional mode (DumpstateMode::" << toString(mode)
- << "): status should be DumpstateStatus::" << toString(expected)
- << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
- << toString(status);
- }
- if (status == expected && additional_assertions != nullptr) {
- additional_assertions();
- }
-}
-
// Negative test: make sure dumpstateBoard() doesn't crash when passed a null pointer.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestNullHandle, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestNullHandle) {
EnableVerboseLogging();
Return<DumpstateStatus> status =
- dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+ dumpstate->dumpstateBoard_1_1(nullptr, GetMode(), kDefaultTimeoutMillis);
- AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
-});
+ AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
+}
// Negative test: make sure dumpstateBoard() ignores a handle with no FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithNoFd, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithNoFd) {
EnableVerboseLogging();
native_handle_t* handle = native_handle_create(0, 0);
ASSERT_NE(handle, nullptr) << "Could not create native_handle";
Return<DumpstateStatus> status =
- dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+ dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
- AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
+ AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
native_handle_close(handle);
native_handle_delete(handle);
-});
+}
// Positive test: make sure dumpstateBoard() writes something to the FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestOk, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestOk) {
EnableVerboseLogging();
// Index 0 corresponds to the read end of the pipe; 1 to the write end.
@@ -160,9 +166,9 @@
handle->data[0] = fds[1];
Return<DumpstateStatus> status =
- dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+ dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
- AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds]() {
+ AssertStatusForMode(status, DumpstateStatus::OK, [&fds]() {
// Check that at least one byte was written.
char buff;
ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
@@ -170,10 +176,10 @@
native_handle_close(handle);
native_handle_delete(handle);
-});
+}
// Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithTwoFds, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithTwoFds) {
EnableVerboseLogging();
int fds1[2];
@@ -187,9 +193,9 @@
handle->data[1] = fds2[1];
Return<DumpstateStatus> status =
- dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+ dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
- AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds1, &fds2]() {
+ AssertStatusForMode(status, DumpstateStatus::OK, [&fds1, &fds2]() {
// Check that at least one byte was written to one of the FDs.
char buff;
size_t read1 = read(fds1[0], &buff, 1);
@@ -200,10 +206,10 @@
native_handle_close(handle);
native_handle_delete(handle);
-});
+}
// Make sure dumpstateBoard_1_1 actually validates its arguments.
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Negative) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Negative) {
EnableVerboseLogging();
int fds[2];
@@ -225,7 +231,7 @@
native_handle_delete(handle);
}
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Undefined) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Undefined) {
EnableVerboseLogging();
int fds[2];
@@ -248,7 +254,7 @@
}
// Positive test: make sure dumpstateBoard() from 1.0 doesn't fail.
-TEST_P(DumpstateHidl1_1Test, Test1_0MethodOk) {
+TEST_P(DumpstateHidl1_1GeneralTest, Test1_0MethodOk) {
EnableVerboseLogging();
int fds[2];
@@ -272,7 +278,7 @@
// Make sure disabling verbose logging behaves correctly. Some info is still allowed to be emitted,
// but it can't have privacy/storage/battery impacts.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestVerboseLoggingDisabled, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestDeviceLoggingDisabled) {
DisableVerboseLogging();
// Index 0 corresponds to the read end of the pipe; 1 to the write end.
@@ -284,31 +290,31 @@
handle->data[0] = fds[1];
Return<DumpstateStatus> status =
- dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+ dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
// We don't include additional assertions here about the file passed in. If verbose logging is
// disabled, the OEM may choose to include nothing at all, but it is allowed to include some
// essential information based on the mode as long as it isn't private user information.
- AssertStatusForMode(mode, status, DumpstateStatus::OK);
+ AssertStatusForMode(status, DumpstateStatus::OK);
native_handle_close(handle);
native_handle_delete(handle);
-});
+}
// Double-enable is perfectly valid, but the second call shouldn't do anything.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedEnable) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedEnable) {
EnableVerboseLogging();
EnableVerboseLogging();
}
// Double-disable is perfectly valid, but the second call shouldn't do anything.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedDisable) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedDisable) {
DisableVerboseLogging();
DisableVerboseLogging();
}
// Toggling in short order is perfectly valid.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedToggle) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedToggle) {
EnableVerboseLogging();
DisableVerboseLogging();
EnableVerboseLogging();
@@ -316,8 +322,23 @@
}
INSTANTIATE_TEST_SUITE_P(
- PerInstance, DumpstateHidl1_1Test,
+ PerInstance, DumpstateHidl1_1GeneralTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)),
android::hardware::PrintInstanceNameToString);
+// Includes the mode's name as part of the description string.
+static inline std::string PrintInstanceNameToStringWithMode(
+ const testing::TestParamInfo<std::tuple<std::string, DumpstateMode>>& info) {
+ return android::hardware::PrintInstanceNameToString(
+ testing::TestParamInfo(std::get<0>(info.param), info.index)) +
+ "_" + toString(std::get<1>(info.param));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstanceAndMode, DumpstateHidl1_1PerModeTest,
+ testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IDumpstateDevice::descriptor)),
+ testing::ValuesIn(android::hardware::hidl_enum_range<DumpstateMode>())),
+ PrintInstanceNameToStringWithMode);
+
} // namespace
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
index ec447b8..60dfb2d 100644
--- a/fastboot/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.fastboot@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IFastboot.hal",
diff --git a/fastboot/1.1/Android.bp b/fastboot/1.1/Android.bp
new file mode 100644
index 0000000..46306cf
--- /dev/null
+++ b/fastboot/1.1/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.fastboot@1.1",
+ root: "android.hardware",
+ srcs: [
+ "IFastboot.hal",
+ ],
+ interfaces: [
+ "android.hardware.fastboot@1.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/fastboot/1.1/IFastboot.hal b/fastboot/1.1/IFastboot.hal
new file mode 100644
index 0000000..c8f1ad0
--- /dev/null
+++ b/fastboot/1.1/IFastboot.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fastboot@1.1;
+import android.hardware.fastboot@1.0;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+interface IFastboot extends @1.0::IFastboot {
+ /**
+ * Executes an OEM specific erase after fastboot erase userdata.
+ *
+ * @return result Returns the status SUCCESS if the operation is successful,
+ * NOT_SUPPORTED for unsupported command.
+ * INVALID_ARGUMENT for bad arguments,
+ * FAILURE_UNKNOWN for unknown error in the oem specific command.
+ */
+ doOemSpecificErase() generates (Result result);
+};
diff --git a/fastboot/1.1/default/Android.bp b/fastboot/1.1/default/Android.bp
new file mode 100644
index 0000000..980586b
--- /dev/null
+++ b/fastboot/1.1/default/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library {
+ name: "android.hardware.fastboot@1.1-impl-mock",
+ recovery: true,
+ srcs: [
+ "Fastboot.cpp",
+ ],
+ relative_install_path: "hw",
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libutils",
+ "libcutils",
+ "android.hardware.fastboot@1.0",
+ "android.hardware.fastboot@1.1",
+ ],
+}
diff --git a/fastboot/1.1/default/Fastboot.cpp b/fastboot/1.1/default/Fastboot.cpp
new file mode 100644
index 0000000..0b502e0
--- /dev/null
+++ b/fastboot/1.1/default/Fastboot.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Fastboot.h"
+
+namespace android {
+namespace hardware {
+namespace fastboot {
+namespace V1_1 {
+namespace implementation {
+
+// Methods from ::android::hardware::fastboot::V1_1::IFastboot follow.
+Return<void> Fastboot::getPartitionType(const hidl_string& /* partitionName */,
+ getPartitionType_cb _hidl_cb) {
+ _hidl_cb(FileSystemType::RAW, {Status::SUCCESS, ""});
+ return Void();
+}
+
+Return<void> Fastboot::doOemCommand(const hidl_string& /* oemCmd */, doOemCommand_cb _hidl_cb) {
+ _hidl_cb({Status::FAILURE_UNKNOWN, "Command not supported in default implementation"});
+ return Void();
+}
+
+Return<void> Fastboot::getVariant(getVariant_cb _hidl_cb) {
+ _hidl_cb("NA", {Status::SUCCESS, ""});
+ return Void();
+}
+
+Return<void> Fastboot::getOffModeChargeState(getOffModeChargeState_cb _hidl_cb) {
+ _hidl_cb(false, {Status::SUCCESS, ""});
+ return Void();
+}
+
+Return<void> Fastboot::getBatteryVoltageFlashingThreshold(
+ getBatteryVoltageFlashingThreshold_cb _hidl_cb) {
+ _hidl_cb(0, {Status::SUCCESS, ""});
+ return Void();
+}
+
+Return<void> Fastboot::doOemSpecificErase(doOemSpecificErase_cb _hidl_cb) {
+ _hidl_cb({Status::NOT_SUPPORTED, "Command not supported in default implementation"});
+ return Void();
+}
+
+extern "C" IFastboot* HIDL_FETCH_IFastboot(const char* /* name */) {
+ return new Fastboot();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
diff --git a/fastboot/1.1/default/Fastboot.h b/fastboot/1.1/default/Fastboot.h
new file mode 100644
index 0000000..09b39c2
--- /dev/null
+++ b/fastboot/1.1/default/Fastboot.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android/hardware/fastboot/1.1/IFastboot.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace fastboot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::fastboot::V1_0::FileSystemType;
+using ::android::hardware::fastboot::V1_0::Status;
+using ::android::hardware::fastboot::V1_0::Result;
+
+struct Fastboot : public IFastboot {
+ // Methods from ::android::hardware::fastboot::V1_0::IFastboot follow.
+ Return<void> getPartitionType(const hidl_string& partitionName,
+ getPartitionType_cb _hidl_cb) override;
+ Return<void> doOemCommand(const hidl_string& oemCmd, doOemCommand_cb _hidl_cb) override;
+ Return<void> getVariant(getVariant_cb _hidl_cb) override;
+ Return<void> getOffModeChargeState(getOffModeChargeState_cb _hidl_cb) override;
+ Return<void> getBatteryVoltageFlashingThreshold(
+ getBatteryVoltageFlashingThreshold_cb _hidl_cb) override;
+ Return<void> doOemSpecificErase(doOemSpecificErase_cb _hidl_cb) override;
+};
+
+extern "C" IFastboot* HIDL_FETCH_IFastboot(const char* name);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index 5d63eaf..f5cb8e4 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gatekeeper@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IGatekeeper.hal",
@@ -13,5 +10,5 @@
interfaces: [
"android.hidl.base@1.0",
],
- gen_java: true,
+ gen_java: false,
}
diff --git a/gatekeeper/1.0/IGatekeeper.hal b/gatekeeper/1.0/IGatekeeper.hal
index 59dd7d1..84e8e06 100644
--- a/gatekeeper/1.0/IGatekeeper.hal
+++ b/gatekeeper/1.0/IGatekeeper.hal
@@ -15,6 +15,7 @@
*/
package android.hardware.gatekeeper@1.0;
+@SensitiveData
interface IGatekeeper {
/**
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index afc737c..e74cca9 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -433,6 +433,7 @@
ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GatekeeperHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GatekeeperHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGatekeeper::descriptor)),
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
index d97588c..22f47e8 100644
--- a/gnss/1.0/Android.bp
+++ b/gnss/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gnss@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAGnss.hal",
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index c04b4d0..237e8ec 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -39,6 +39,10 @@
using android::hardware::gnss::V1_0::IGnssMeasurement;
using android::sp;
+/*
+ * Since Utils.cpp depends on Gnss Hal 2.0, the tests for Gnss Hal 1.0 will use
+ * there own version of IsAutomotiveDevice() instead of the common version.
+ */
static bool IsAutomotiveDevice() {
char buffer[PROPERTY_VALUE_MAX] = {0};
property_get("ro.hardware.type", buffer, "");
@@ -492,9 +496,9 @@
* Verifies that modern hardware supports measurement capabilities.
*/
TEST_P(GnssHalTest, MeasurementCapabilites) {
- if (info_called_count_ > 0 && last_info_.yearOfHw >= 2016) {
- EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS);
- }
+ if (!IsAutomotiveDevice() && info_called_count_ > 0 && last_info_.yearOfHw >= 2016) {
+ EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS);
+ }
}
/*
@@ -507,6 +511,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GnssHalTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)),
@@ -528,4 +533,4 @@
}
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp
index 5294a6b..1c38e97 100644
--- a/gnss/1.1/Android.bp
+++ b/gnss/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gnss@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IGnss.hal",
"IGnssCallback.hal",
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index db5075f..b7a98b7 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gnss@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAGnss.hal",
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 51dcf0d..3e0058f 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -62,6 +62,15 @@
auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
ASSERT_TRUE(gnssMeasurement_2_0.isOk() && gnssMeasurement_1_1.isOk() &&
gnssMeasurement_1_0.isOk());
+
+ // CDD does not require Android Automotive OS devices to support
+ // GnssMeasurements.
+ if (Utils::isAutomotiveDevice()) {
+ ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS deice is not required "
+ "to support GNSS measurements.");
+ return;
+ }
+
sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
diff --git a/gnss/2.1/Android.bp b/gnss/2.1/Android.bp
index 2122399..affbeae 100644
--- a/gnss/2.1/Android.bp
+++ b/gnss/2.1/Android.bp
@@ -3,22 +3,19 @@
hidl_interface {
name: "android.hardware.gnss@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IGnss.hal",
"IGnssAntennaInfo.hal",
"IGnssAntennaInfoCallback.hal",
"IGnssCallback.hal",
+ "IGnssConfiguration.hal",
"IGnssMeasurement.hal",
"IGnssMeasurementCallback.hal",
- "IGnssConfiguration.hal",
],
interfaces: [
- "android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss.measurement_corrections@1.0",
+ "android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss.visibility_control@1.0",
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
@@ -26,4 +23,5 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ gen_java_constants: true,
}
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 16e634f..2902809 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -63,6 +63,15 @@
auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
+
+ // CDD does not require Android Automotive OS devices to support
+ // GnssMeasurements.
+ if (Utils::isAutomotiveDevice()) {
+ ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS de ice is not "
+ "required to support GNSS measurements.");
+ return;
+ }
+
sp<IGnssMeasurement_2_1> iGnssMeas_2_1 = gnssMeasurement_2_1;
sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 9bf68e6..9c84e80 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -17,6 +17,8 @@
#include <Utils.h>
#include "gtest/gtest.h"
+#include <cutils/properties.h>
+
namespace android {
namespace hardware {
namespace gnss {
@@ -194,6 +196,12 @@
}
}
+bool Utils::isAutomotiveDevice() {
+ char buffer[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware.type", buffer, "");
+ return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
} // namespace common
} // namespace gnss
} // namespace hardware
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index 9c838b2..a4aad80 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -49,6 +49,8 @@
static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
+
+ static bool isAutomotiveDevice();
};
} // namespace common
diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp
index 837cc7a..a140674 100644
--- a/gnss/measurement_corrections/1.0/Android.bp
+++ b/gnss/measurement_corrections/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gnss.measurement_corrections@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IMeasurementCorrections.hal",
diff --git a/gnss/measurement_corrections/1.1/Android.bp b/gnss/measurement_corrections/1.1/Android.bp
index d279af6..9363848 100644
--- a/gnss/measurement_corrections/1.1/Android.bp
+++ b/gnss/measurement_corrections/1.1/Android.bp
@@ -3,17 +3,14 @@
hidl_interface {
name: "android.hardware.gnss.measurement_corrections@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IMeasurementCorrections.hal",
],
interfaces: [
"android.hardware.gnss.measurement_corrections@1.0",
- "android.hardware.gnss@2.0",
"android.hardware.gnss@1.0",
+ "android.hardware.gnss@2.0",
"android.hidl.base@1.0",
],
gen_java: true,
diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp
index e58e932..975da78 100644
--- a/gnss/visibility_control/1.0/Android.bp
+++ b/gnss/visibility_control/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.gnss.visibility_control@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IGnssVisibilityControl.hal",
"IGnssVisibilityControlCallback.hal",
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index e594233..22e609d 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -6,6 +6,7 @@
enabled: true,
support_system_process: true,
},
+ vndk_use_version: "2",
srcs: [
"android/hardware/graphics/common/*.aidl",
],
diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp
index 4e4b81c..2358a8f 100644
--- a/graphics/composer/2.1/Android.bp
+++ b/graphics/composer/2.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.graphics.composer@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IComposer.hal",
diff --git a/graphics/composer/2.1/utils/resources/Android.bp b/graphics/composer/2.1/utils/resources/Android.bp
index ed827fe..dc20eae 100644
--- a/graphics/composer/2.1/utils/resources/Android.bp
+++ b/graphics/composer/2.1/utils/resources/Android.bp
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+cc_library {
name: "android.hardware.graphics.composer@2.1-resources",
defaults: ["hidl_defaults"],
vendor_available: true,
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
index 930cadc..234b9ac 100644
--- a/graphics/composer/2.2/Android.bp
+++ b/graphics/composer/2.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.graphics.composer@2.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IComposer.hal",
"IComposerClient.hal",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index cb43e64..b0eb4ef 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -1386,6 +1386,7 @@
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsBlendModeCompositionTest);
INSTANTIATE_TEST_CASE_P(
BlendModeTest, GraphicsBlendModeCompositionTest,
testing::Combine(
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
index a777556..96f301c 100644
--- a/graphics/composer/2.3/Android.bp
+++ b/graphics/composer/2.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.graphics.composer@2.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IComposer.hal",
"IComposerClient.hal",
diff --git a/graphics/composer/2.4/Android.bp b/graphics/composer/2.4/Android.bp
index 5f700be..2bbe751 100644
--- a/graphics/composer/2.4/Android.bp
+++ b/graphics/composer/2.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.graphics.composer@2.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IComposer.hal",
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 9e3cf0e..1a59bbd 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -34,7 +34,9 @@
/**
* The configuration group ID (as int32_t) this config is associated to.
* Switching between configurations within the same group may be done seamlessly
- * in some conditions via setActiveConfigWithConstraints.
+ * in some conditions via setActiveConfigWithConstraints. Configurations which
+ * share the same config group are similar in all attributes except for the
+ * vsync period.
*/
CONFIG_GROUP = 7,
};
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
index 8134174..0067105 100644
--- a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
@@ -85,11 +85,7 @@
return Error::BAD_BUFFER;
}
- Error error = mHal->freeBuffer(bufferHandle);
- if (error == Error::NONE) {
- removeImportedBuffer(buffer);
- }
- return error;
+ return freeImportedBuffer(bufferHandle);
}
Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
@@ -160,8 +156,8 @@
return static_cast<void*>(bufferHandle);
}
- virtual native_handle_t* removeImportedBuffer(void* buffer) {
- return static_cast<native_handle_t*>(buffer);
+ virtual Error freeImportedBuffer(native_handle_t* bufferHandle) {
+ return mHal->freeBuffer(bufferHandle);
}
virtual native_handle_t* getImportedBuffer(void* buffer) const {
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
index 85a91c3..f2e0064 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -56,17 +56,14 @@
return *singleton;
}
+ std::mutex* getMutex() { return &mMutex; }
+
void* add(native_handle_t* bufferHandle) {
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
}
- native_handle_t* remove(void* buffer) {
- auto bufferHandle = static_cast<native_handle_t*>(buffer);
-
- std::lock_guard<std::mutex> lock(mMutex);
- return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
- }
+ void removeLocked(native_handle* bufferHandle) { mBufferHandles.erase(bufferHandle); }
native_handle_t* get(void* buffer) {
auto bufferHandle = static_cast<native_handle_t*>(buffer);
@@ -95,8 +92,13 @@
return GrallocImportedBufferPool::getInstance().add(bufferHandle);
}
- native_handle_t* removeImportedBuffer(void* buffer) override {
- return GrallocImportedBufferPool::getInstance().remove(buffer);
+ Error freeImportedBuffer(native_handle_t* bufferHandle) override {
+ std::lock_guard<std::mutex> lock(*GrallocImportedBufferPool::getInstance().getMutex());
+ Error error = this->mHal->freeBuffer(bufferHandle);
+ if (error == Error::NONE) {
+ GrallocImportedBufferPool::getInstance().removeLocked(bufferHandle);
+ }
+ return error;
}
native_handle_t* getImportedBuffer(void* buffer) const override {
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index b079a4b..7d733ff 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -410,6 +410,7 @@
#endif
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, GraphicsMapperHidlTest,
testing::Combine(
diff --git a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
index 038f572..b4a2bedc 100644
--- a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
+++ b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
@@ -46,7 +46,7 @@
return Error::BAD_BUFFER;
}
- return mHal->validateBufferSize(bufferHandle, descriptorInfo, stride);
+ return this->mHal->validateBufferSize(bufferHandle, descriptorInfo, stride);
}
Return<void> getTransportSize(void* buffer, IMapper::getTransportSize_cb hidl_cb) {
@@ -58,7 +58,7 @@
uint32_t numFds = 0;
uint32_t numInts = 0;
- Error error = mHal->getTransportSize(bufferHandle, &numFds, &numInts);
+ Error error = this->mHal->getTransportSize(bufferHandle, &numFds, &numInts);
hidl_cb(error, numFds, numInts);
return Void();
}
@@ -66,7 +66,7 @@
Return<void> createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
IMapper::createDescriptor_2_1_cb hidl_cb) override {
BufferDescriptor descriptor;
- Error error = mHal->createDescriptor_2_1(descriptorInfo, &descriptor);
+ Error error = this->mHal->createDescriptor_2_1(descriptorInfo, &descriptor);
hidl_cb(error, descriptor);
return Void();
}
@@ -74,7 +74,6 @@
private:
using BaseType2_0 = V2_0::hal::detail::MapperImpl<Interface, Hal>;
using BaseType2_0::getImportedBuffer;
- using BaseType2_0::mHal;
};
} // namespace detail
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 3d792f9..9f927e5 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -204,6 +204,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, GraphicsMapperHidlTest,
testing::Combine(
@@ -218,4 +219,4 @@
} // namespace mapper
} // namespace graphics
} // namespace hardware
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
index 92b5994..4187dd1 100644
--- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -458,6 +458,7 @@
ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, GraphicsMapperHidlTest,
testing::Combine(
diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp
index 03abc89..8bda425 100644
--- a/graphics/mapper/4.0/vts/functional/Android.bp
+++ b/graphics/mapper/4.0/vts/functional/Android.bp
@@ -19,7 +19,7 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"],
static_libs: [
- "android.hardware.graphics.common-ndk_platform",
+ "android.hardware.graphics.common-unstable-ndk_platform",
"android.hardware.graphics.mapper@4.0-vts",
"libgralloctypes",
"libsync",
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index bb775dc..f55a6b7 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2592,6 +2592,7 @@
ASSERT_EQ(0, reservedSize);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, GraphicsMapperHidlTest,
testing::Combine(
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index ea6b0c8..7845871 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.health@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHealth.hal",
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 7581335..aab9cc7 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -4,7 +4,7 @@
recovery_available: true,
srcs: ["convert.cpp"],
include_dirs: [
- "system/core/base/include",
+ "system/libbase/include",
],
header_libs: ["libhealthd_headers"],
export_header_lib_headers: ["libhealthd_headers"],
@@ -51,6 +51,12 @@
"android.hardware.health@1.0-convert",
"libhealthd.default",
],
+
+ shared_libs: [
+ "libhidlbase",
+ "libutils",
+ "android.hardware.health@1.0",
+ ],
}
cc_binary {
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index 405784f..569dc88 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,4 +2,4 @@
class hal
user system
group system
- capabilities WAKE_ALARM
+ capabilities WAKE_ALARM BLOCK_SUSPEND
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
index 7f1e3c4..3680d4d 100644
--- a/health/1.0/default/convert.cpp
+++ b/health/1.0/default/convert.cpp
@@ -79,7 +79,7 @@
hc->batteryCurrentAvgPath =
android::String8(c.batteryCurrentAvgPath.c_str(),
- c.batteryCurrentNowPath.size());
+ c.batteryCurrentAvgPath.size());
hc->batteryChargeCounterPath =
android::String8(c.batteryChargeCounterPath.c_str(),
diff --git a/health/1.0/default/libhealthd/Android.bp b/health/1.0/default/libhealthd/Android.bp
index a90d50d..43463eb 100644
--- a/health/1.0/default/libhealthd/Android.bp
+++ b/health/1.0/default/libhealthd/Android.bp
@@ -6,6 +6,6 @@
vendor_available: true,
recovery_available: true,
cflags: ["-Werror"],
- include_dirs: ["system/core/base/include"],
+ include_dirs: ["system/libbase/include"],
header_libs: ["libhealthd_headers"],
}
diff --git a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp b/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
index b985a9f..8b3dcc1 100644
--- a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
+++ b/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
@@ -58,6 +58,7 @@
ASSERT_TRUE(result != Result::SUCCESS || energy > 0);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, HealthHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index b8323b6..420586e 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.health@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHealth.hal",
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index 441e2d7..7fabf2b 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -319,6 +319,7 @@
}));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, HealthHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
@@ -669,6 +670,7 @@
<< "You may want to try again later when getHealthInfo becomes stable.";
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BatteryTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, BatteryTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
diff --git a/health/2.1/Android.bp b/health/2.1/Android.bp
index 254bfc0..80a6501 100644
--- a/health/2.1/Android.bp
+++ b/health/2.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.health@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHealth.hal",
diff --git a/health/2.1/default/android.hardware.health@2.1-service.rc b/health/2.1/default/android.hardware.health@2.1-service.rc
index b6d9e3b..8728257 100644
--- a/health/2.1/default/android.hardware.health@2.1-service.rc
+++ b/health/2.1/default/android.hardware.health@2.1-service.rc
@@ -2,5 +2,5 @@
class hal charger
user system
group system
- capabilities WAKE_ALARM
+ capabilities WAKE_ALARM BLOCK_SUSPEND
file /dev/kmsg w
diff --git a/health/2.1/types.hal b/health/2.1/types.hal
index d775491..6d7b661 100644
--- a/health/2.1/types.hal
+++ b/health/2.1/types.hal
@@ -98,9 +98,8 @@
/**
* Estimated battery full charge design capacity (in microamp hours, uAh).
* Value must be 0 if unknown.
- * Value must be positive if known.
- * Value must be greater than 100 000 uAh.
- * Value must be less than 100 000 000 uAh.
+ * Value must be greater than 100 000 uAh if known.
+ * Value must be less than 100 000 000 uAh if known.
*/
int32_t batteryFullChargeDesignCapacityUah;
};
diff --git a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
index deb1a29..4ae443a 100644
--- a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
+++ b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
@@ -233,16 +233,17 @@
ASSERT_EQ(Result::SUCCESS, result);
EXPECT_TRUE(IsEnum(value.batteryCapacityLevel)) << " BatteryCapacityLevel";
- EXPECT_GE(value.batteryChargeTimeToFullNowSeconds, 0);
+ EXPECT_GE(value.batteryChargeTimeToFullNowSeconds, -1);
- EXPECT_GE(value.batteryFullChargeDesignCapacityUah, 0)
- << "batteryFullChargeDesignCapacityUah should not be negative";
+ if (value.batteryFullChargeDesignCapacityUah != 0) {
+ EXPECT_GT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MIN)
+ << "batteryFullChargeDesignCapacityUah should be greater than 100 mAh, or 0 if "
+ "unknown";
- EXPECT_GT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MIN)
- << "batteryFullChargeDesignCapacityUah should be greater than 100 mAh";
-
- EXPECT_LT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MAX)
- << "batteryFullChargeDesignCapacityUah should be less than 100,000 mAh";
+ EXPECT_LT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MAX)
+ << "batteryFullChargeDesignCapacityUah should be less than 100,000 mAh, or 0 "
+ "if unknown";
+ }
})));
}
@@ -258,6 +259,7 @@
})));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, HealthHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
diff --git a/health/storage/1.0/Android.bp b/health/storage/1.0/Android.bp
index e4620f8..b9d892d 100644
--- a/health/storage/1.0/Android.bp
+++ b/health/storage/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.health.storage@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IGarbageCollectCallback.hal",
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
index eaa44ec..24ddc5d 100644
--- a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -160,6 +160,7 @@
cb->waitForResult(kDevGcTimeout + kDevGcTolerance + kRpcTime, Result::SUCCESS);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthStorageHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, HealthStorageHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IStorage::descriptor)),
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 41d410d..dfcd4f5 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -108,7 +108,7 @@
}
ndk::ScopedAStatus IdentityCredential::deleteCredential(
- vector<int8_t>* outProofOfDeletionSignature) {
+ vector<uint8_t>* outProofOfDeletionSignature) {
cppbor::Array array = {"ProofOfDeletion", docType_, testCredential_};
vector<uint8_t> proofOfDeletion = array.encode();
@@ -121,11 +121,11 @@
IIdentityCredentialStore::STATUS_FAILED, "Error signing data"));
}
- *outProofOfDeletionSignature = byteStringToSigned(signature.value());
+ *outProofOfDeletionSignature = signature.value();
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<int8_t>* outKeyPair) {
+ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
optional<vector<uint8_t>> kp = support::createEcKeyPair();
if (!kp) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -141,13 +141,13 @@
}
ephemeralPublicKey_ = publicKey.value();
- *outKeyPair = byteStringToSigned(kp.value());
+ *outKeyPair = kp.value();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus IdentityCredential::setReaderEphemeralPublicKey(
- const vector<int8_t>& publicKey) {
- readerPublicKey_ = byteStringToUnsigned(publicKey);
+ const vector<uint8_t>& publicKey) {
+ readerPublicKey_ = publicKey;
return ndk::ScopedAStatus::ok();
}
@@ -176,8 +176,8 @@
// ahead of time.
bool checkReaderAuthentication(const SecureAccessControlProfile& profile,
const vector<uint8_t>& readerCertificateChain) {
- optional<vector<uint8_t>> acpPubKey = support::certificateChainGetTopMostKey(
- byteStringToUnsigned(profile.readerCertificate.encodedCertificate));
+ optional<vector<uint8_t>> acpPubKey =
+ support::certificateChainGetTopMostKey(profile.readerCertificate.encodedCertificate);
if (!acpPubKey) {
LOG(ERROR) << "Error extracting public key from readerCertificate in profile";
return false;
@@ -269,13 +269,9 @@
ndk::ScopedAStatus IdentityCredential::startRetrieval(
const vector<SecureAccessControlProfile>& accessControlProfiles,
- const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
- const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
- const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
- auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
- auto itemsRequest = byteStringToUnsigned(itemsRequestS);
- auto readerSignature = byteStringToUnsigned(readerSignatureS);
-
+ const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
+ const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
+ const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) {
std::unique_ptr<cppbor::Item> sessionTranscriptItem;
if (sessionTranscript.size() > 0) {
auto [item, _, message] = cppbor::parse(sessionTranscript);
@@ -498,7 +494,7 @@
currentNameSpace_ = "";
itemsRequest_ = itemsRequest;
- signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
+ signingKeyBlob_ = signingKeyBlob;
// Finally, calculate the size of DeviceNameSpaces. We need to know it ahead of time.
expectedDeviceNameSpacesSize_ = calcDeviceNameSpacesSize();
@@ -713,9 +709,8 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<int8_t>& encryptedContentS,
- vector<int8_t>* outContent) {
- auto encryptedContent = byteStringToUnsigned(encryptedContentS);
+ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<uint8_t>& encryptedContent,
+ vector<uint8_t>* outContent) {
optional<vector<uint8_t>> content =
support::decryptAes128Gcm(storageKey_, encryptedContent, entryAdditionalData_);
if (!content) {
@@ -754,12 +749,12 @@
currentNameSpaceDeviceNameSpacesMap_.add(currentName_, std::move(entryValueItem));
}
- *outContent = byteStringToSigned(content.value());
+ *outContent = content.value();
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
- vector<int8_t>* outDeviceNameSpaces) {
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
+ vector<uint8_t>* outDeviceNameSpaces) {
if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
deviceNameSpacesMap_.add(currentNameSpace_,
std::move(currentNameSpaceDeviceNameSpacesMap_));
@@ -806,13 +801,13 @@
}
}
- *outMac = byteStringToSigned(mac.value_or(vector<uint8_t>({})));
- *outDeviceNameSpaces = byteStringToSigned(encodedDeviceNameSpaces);
+ *outMac = mac.value_or(vector<uint8_t>({}));
+ *outDeviceNameSpaces = encodedDeviceNameSpaces;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
- vector<int8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
+ vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
string serialDecimal = "1";
string issuer = "Android Identity Credential Key";
string subject = "Android Identity Credential Authentication Key";
@@ -860,9 +855,9 @@
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED, "Error encrypting signingKey"));
}
- *outSigningKeyBlob = byteStringToSigned(encryptedSigningKey.value());
+ *outSigningKeyBlob = encryptedSigningKey.value();
*outSigningKeyCertificate = Certificate();
- outSigningKeyCertificate->encodedCertificate = byteStringToSigned(certificate.value());
+ outSigningKeyCertificate->encodedCertificate = certificate.value();
return ndk::ScopedAStatus::ok();
}
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index f44d731..a8a6409 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -51,26 +51,26 @@
int initialize();
// Methods from IIdentityCredential follow.
- ndk::ScopedAStatus deleteCredential(vector<int8_t>* outProofOfDeletionSignature) override;
- ndk::ScopedAStatus createEphemeralKeyPair(vector<int8_t>* outKeyPair) override;
- ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<int8_t>& publicKey) override;
+ ndk::ScopedAStatus deleteCredential(vector<uint8_t>* outProofOfDeletionSignature) override;
+ ndk::ScopedAStatus createEphemeralKeyPair(vector<uint8_t>* outKeyPair) override;
+ ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
ndk::ScopedAStatus setRequestedNamespaces(
const vector<RequestNamespace>& requestNamespaces) override;
ndk::ScopedAStatus setVerificationToken(const VerificationToken& verificationToken) override;
ndk::ScopedAStatus startRetrieval(
const vector<SecureAccessControlProfile>& accessControlProfiles,
- const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
- const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
- const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
+ const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
+ const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
+ const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
ndk::ScopedAStatus startRetrieveEntryValue(
const string& nameSpace, const string& name, int32_t entrySize,
const vector<int32_t>& accessControlProfileIds) override;
- ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
- vector<int8_t>* outContent) override;
- ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
- vector<int8_t>* outDeviceNameSpaces) override;
- ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
+ ndk::ScopedAStatus retrieveEntryValue(const vector<uint8_t>& encryptedContent,
+ vector<uint8_t>* outContent) override;
+ ndk::ScopedAStatus finishRetrieval(vector<uint8_t>* outMac,
+ vector<uint8_t>* outDeviceNameSpaces) override;
+ ndk::ScopedAStatus generateSigningKeyPair(vector<uint8_t>* outSigningKeyBlob,
Certificate* outSigningKeyCertificate) override;
private:
diff --git a/identity/aidl/default/IdentityCredentialStore.cpp b/identity/aidl/default/IdentityCredentialStore.cpp
index 1efb4b4..30dc6f3 100644
--- a/identity/aidl/default/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/IdentityCredentialStore.cpp
@@ -51,7 +51,7 @@
}
ndk::ScopedAStatus IdentityCredentialStore::getCredential(
- CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+ CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
shared_ptr<IIdentityCredential>* outCredential) {
// We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
@@ -60,8 +60,8 @@
"Unsupported cipher suite"));
}
- vector<uint8_t> data = vector<uint8_t>(credentialData.begin(), credentialData.end());
- shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(data);
+ shared_ptr<IdentityCredential> credential =
+ ndk::SharedRefBase::make<IdentityCredential>(credentialData);
auto ret = credential->initialize();
if (ret != IIdentityCredentialStore::STATUS_OK) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/default/IdentityCredentialStore.h b/identity/aidl/default/IdentityCredentialStore.h
index a205113..4f3a421 100644
--- a/identity/aidl/default/IdentityCredentialStore.h
+++ b/identity/aidl/default/IdentityCredentialStore.h
@@ -39,7 +39,7 @@
const string& docType, bool testCredential,
shared_ptr<IWritableIdentityCredential>* outWritableCredential) override;
- ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+ ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
shared_ptr<IIdentityCredential>* outCredential) override;
};
diff --git a/identity/aidl/default/Util.cpp b/identity/aidl/default/Util.cpp
index a0f86be..66b9f13 100644
--- a/identity/aidl/default/Util.cpp
+++ b/identity/aidl/default/Util.cpp
@@ -39,21 +39,12 @@
return hardwareBoundKey;
}
-vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value) {
- return vector<uint8_t>(value.begin(), value.end());
-}
-
-vector<int8_t> byteStringToSigned(const vector<uint8_t>& value) {
- return vector<int8_t>(value.begin(), value.end());
-}
-
vector<uint8_t> secureAccessControlProfileEncodeCbor(const SecureAccessControlProfile& profile) {
cppbor::Map map;
map.add("id", profile.id);
if (profile.readerCertificate.encodedCertificate.size() > 0) {
- map.add("readerCertificate",
- cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+ map.add("readerCertificate", cppbor::Bstr(profile.readerCertificate.encodedCertificate));
}
if (profile.userAuthenticationRequired) {
@@ -94,7 +85,7 @@
if (!mac) {
return false;
}
- if (mac.value() != byteStringToUnsigned(profile.mac)) {
+ if (mac.value() != profile.mac) {
return false;
}
return true;
diff --git a/identity/aidl/default/Util.h b/identity/aidl/default/Util.h
index ee41ad1..9fccba2 100644
--- a/identity/aidl/default/Util.h
+++ b/identity/aidl/default/Util.h
@@ -49,10 +49,6 @@
vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
const vector<int32_t> accessControlProfileIds);
-vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value);
-
-vector<int8_t> byteStringToSigned(const vector<uint8_t>& value);
-
} // namespace aidl::android::hardware::identity
#endif // ANDROID_HARDWARE_IDENTITY_UTIL_H
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 4428543..141b4de 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -57,8 +57,8 @@
// attestation certificate with current time and expires one year from now. The
// certificate shall contain all values as specified in hal.
ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
- const vector<int8_t>& attestationApplicationId, //
- const vector<int8_t>& attestationChallenge, //
+ const vector<uint8_t>& attestationApplicationId, //
+ const vector<uint8_t>& attestationChallenge, //
vector<Certificate>* outCertificateChain) {
if (!credentialPrivKey_.empty() || !credentialPubKey_.empty() || !certificateChain_.empty()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -105,7 +105,7 @@
*outCertificateChain = vector<Certificate>();
for (const vector<uint8_t>& cert : certificateChain_) {
Certificate c = Certificate();
- c.encodedCertificate = byteStringToSigned(cert);
+ c.encodedCertificate = cert;
outCertificateChain->push_back(std::move(c));
}
return ndk::ScopedAStatus::ok();
@@ -186,14 +186,13 @@
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED, "Error calculating MAC for profile"));
}
- profile.mac = byteStringToSigned(mac.value());
+ profile.mac = mac.value();
cppbor::Map profileMap;
profileMap.add("id", profile.id);
if (profile.readerCertificate.encodedCertificate.size() > 0) {
- profileMap.add(
- "readerCertificate",
- cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+ profileMap.add("readerCertificate",
+ cppbor::Bstr(profile.readerCertificate.encodedCertificate));
}
if (profile.userAuthenticationRequired) {
profileMap.add("userAuthenticationRequired", profile.userAuthenticationRequired);
@@ -273,9 +272,8 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t>& contentS,
- vector<int8_t>* outEncryptedContentS) {
- auto content = byteStringToUnsigned(contentS);
+ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<uint8_t>& content,
+ vector<uint8_t>* outEncryptedContent) {
size_t contentSize = content.size();
if (contentSize > IdentityCredentialStore::kGcmChunkSize) {
@@ -330,7 +328,7 @@
signedDataCurrentNamespace_.add(std::move(entryMap));
}
- *outEncryptedContentS = byteStringToSigned(encryptedContent.value());
+ *outEncryptedContent = encryptedContent.value();
return ndk::ScopedAStatus::ok();
}
@@ -379,7 +377,7 @@
}
ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
- vector<int8_t>* outCredentialData, vector<int8_t>* outProofOfProvisioningSignature) {
+ vector<uint8_t>* outCredentialData, vector<uint8_t>* outProofOfProvisioningSignature) {
if (numAccessControlProfileRemaining_ != 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA,
@@ -436,8 +434,8 @@
IIdentityCredentialStore::STATUS_FAILED, "Error generating CredentialData"));
}
- *outCredentialData = byteStringToSigned(credentialData);
- *outProofOfProvisioningSignature = byteStringToSigned(signature.value());
+ *outCredentialData = credentialData;
+ *outProofOfProvisioningSignature = signature.value();
return ndk::ScopedAStatus::ok();
}
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index 05104d7..5645852 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -39,8 +39,8 @@
bool initialize();
// Methods from IWritableIdentityCredential follow.
- ndk::ScopedAStatus getAttestationCertificate(const vector<int8_t>& attestationApplicationId,
- const vector<int8_t>& attestationChallenge,
+ ndk::ScopedAStatus getAttestationCertificate(const vector<uint8_t>& attestationApplicationId,
+ const vector<uint8_t>& attestationChallenge,
vector<Certificate>* outCertificateChain) override;
ndk::ScopedAStatus setExpectedProofOfProvisioningSize(
@@ -58,12 +58,12 @@
const string& nameSpace, const string& name,
int32_t entrySize) override;
- ndk::ScopedAStatus addEntryValue(const vector<int8_t>& content,
- vector<int8_t>* outEncryptedContent) override;
+ ndk::ScopedAStatus addEntryValue(const vector<uint8_t>& content,
+ vector<uint8_t>* outEncryptedContent) override;
ndk::ScopedAStatus finishAddingEntries(
- vector<int8_t>* outCredentialData,
- vector<int8_t>* outProofOfProvisioningSignature) override;
+ vector<uint8_t>* outCredentialData,
+ vector<uint8_t>* outProofOfProvisioningSignature) override;
private:
string docType_;
diff --git a/identity/aidl/vts/ReaderAuthTests.cpp b/identity/aidl/vts/ReaderAuthTests.cpp
index b11f6c5..0a9fdc0 100644
--- a/identity/aidl/vts/ReaderAuthTests.cpp
+++ b/identity/aidl/vts/ReaderAuthTests.cpp
@@ -594,6 +594,7 @@
status.serviceSpecificErrorCode());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReaderAuthTests);
INSTANTIATE_TEST_SUITE_P(
Identity, ReaderAuthTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
diff --git a/identity/aidl/vts/UserAuthTests.cpp b/identity/aidl/vts/UserAuthTests.cpp
index 5b4c8f1..327493c 100644
--- a/identity/aidl/vts/UserAuthTests.cpp
+++ b/identity/aidl/vts/UserAuthTests.cpp
@@ -465,6 +465,7 @@
true /* useSessionTranscript */);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UserAuthTests);
INSTANTIATE_TEST_SUITE_P(
Identity, UserAuthTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index e5871fb..5529853 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -105,6 +105,7 @@
attestationApplicationId, false);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VtsAttestationTests);
INSTANTIATE_TEST_SUITE_P(
Identity, VtsAttestationTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 7657943..cdecb97 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -498,6 +498,7 @@
EXPECT_EQ(mac, calculatedMac);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityAidl);
INSTANTIATE_TEST_SUITE_P(
Identity, IdentityAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 5435ed8..56e17ba 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -717,6 +717,7 @@
ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
INSTANTIATE_TEST_SUITE_P(
Identity, IdentityCredentialTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 08559c6..77b795b 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -55,6 +55,7 @@
#include <keymaster/contexts/soft_attestation_cert.h>
#include <keymaster/keymaster_tags.h>
#include <keymaster/km_openssl/attestation_utils.h>
+#include <keymaster/km_openssl/certificate_utils.h>
namespace android {
namespace hardware {
@@ -962,6 +963,18 @@
return {};
}
+ ::keymaster::X509_NAME_Ptr subjectName;
+ if (KM_ERROR_OK !=
+ ::keymaster::make_name_from_str("Android Identity Credential Key", &subjectName)) {
+ LOG(ERROR) << "Cannot create attestation subject";
+ return {};
+ }
+
+ vector<uint8_t> subject(i2d_X509_NAME(subjectName.get(), NULL));
+ unsigned char* subjectPtr = subject.data();
+
+ i2d_X509_NAME(subjectName.get(), &subjectPtr);
+
::keymaster::AuthorizationSet auth_set(
::keymaster::AuthorizationSetBuilder()
.Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
@@ -976,6 +989,8 @@
// includes app id.
.Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
applicationId.data(), applicationId.size())
+ .Authorization(::keymaster::TAG_CERTIFICATE_SUBJECT, subject.data(),
+ subject.size())
.Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
// Unique id and device id is not applicable for identity credential attestation,
@@ -1008,12 +1023,12 @@
// relying party is ever going to trust our batch key and those keys above
// it.
//
- ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+ ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
+ KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
- ::keymaster::kCurrentKeymasterVersion, *attestation_chain,
- *attestation_signing_key,
- "Android Identity Credential Key", &cert_chain_out);
+ *attestation_chain, *attestation_signing_key,
+ &cert_chain_out);
if (KM_ERROR_OK != error || !cert_chain_out) {
LOG(ERROR) << "Error generate attestation from EVP key" << error;
@@ -1611,12 +1626,6 @@
return {};
}
- int algoId = OBJ_obj2nid(certs[0]->cert_info->key->algor->algorithm);
- if (algoId != NID_X9_62_id_ecPublicKey) {
- LOG(ERROR) << "Expected NID_X9_62_id_ecPublicKey, got " << OBJ_nid2ln(algoId);
- return {};
- }
-
auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
if (pkey.get() == nullptr) {
LOG(ERROR) << "No public key";
@@ -1870,11 +1879,11 @@
ecdsaCoseSignature.clear();
ecdsaCoseSignature.resize(64);
- if (BN_bn2binpad(sig->r, ecdsaCoseSignature.data(), 32) != 32) {
+ if (BN_bn2binpad(ECDSA_SIG_get0_r(sig), ecdsaCoseSignature.data(), 32) != 32) {
LOG(ERROR) << "Error encoding r";
return false;
}
- if (BN_bn2binpad(sig->s, ecdsaCoseSignature.data() + 32, 32) != 32) {
+ if (BN_bn2binpad(ECDSA_SIG_get0_s(sig), ecdsaCoseSignature.data() + 32, 32) != 32) {
LOG(ERROR) << "Error encoding s";
return false;
}
@@ -2394,7 +2403,6 @@
return ret;
}
-
vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const vector<uint8_t>& getTestHardwareBoundKey() {
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
index 11e0f52..b6e54ca 100644
--- a/input/classifier/1.0/Android.bp
+++ b/input/classifier/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.input.classifier@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IInputClassifier.hal",
],
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 4d6c9c3..99fdb8c 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -18,6 +18,7 @@
name: "VtsHalInputClassifierV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"],
+ header_libs: ["jni_headers"],
static_libs: [
"android.hardware.input.classifier@1.0",
"android.hardware.input.common@1.0",
diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp
index 2c7c517..07ced7a 100644
--- a/input/common/1.0/Android.bp
+++ b/input/common/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.input.common@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
],
diff --git a/ir/1.0/Android.bp b/ir/1.0/Android.bp
index 5fca96d..6a521f7 100644
--- a/ir/1.0/Android.bp
+++ b/ir/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.ir@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IConsumerIr.hal",
diff --git a/ir/1.0/vts/functional/VtsHalIrV1_0TargetTest.cpp b/ir/1.0/vts/functional/VtsHalIrV1_0TargetTest.cpp
index a5dbdcc..81464f0 100644
--- a/ir/1.0/vts/functional/VtsHalIrV1_0TargetTest.cpp
+++ b/ir/1.0/vts/functional/VtsHalIrV1_0TargetTest.cpp
@@ -77,6 +77,7 @@
EXPECT_FALSE(ir->transmit(-1, vec));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConsumerIrHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ConsumerIrHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConsumerIr::descriptor)),
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
index 0fdc32c..d0c7a7c 100644
--- a/keymaster/3.0/Android.bp
+++ b/keymaster/3.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.keymaster@3.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IKeymasterDevice.hal",
diff --git a/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
index 2664765..9bd8602 100644
--- a/keymaster/3.0/IKeymasterDevice.hal
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -20,6 +20,7 @@
* Keymaster device definition. For thorough documentation see the implementer's reference, at
* https://source.android.com/security/keystore/implementer-ref.html
*/
+@SensitiveData
interface IKeymasterDevice {
/**
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index ae32764..554afe7 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -4179,39 +4179,51 @@
static const auto kKeymasterDeviceChoices =
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NewKeyGenerationTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, NewKeyGenerationTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(KeymasterVersionTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, KeymasterVersionTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetKeyCharacteristicsTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, GetKeyCharacteristicsTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SigningOperationsTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, SigningOperationsTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VerificationOperationsTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, VerificationOperationsTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExportKeyTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, ExportKeyTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImportKeyTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, ImportKeyTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EncryptionOperationsTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, EncryptionOperationsTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MaxOperationsTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, MaxOperationsTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AddEntropyTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, AddEntropyTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AttestationTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, AttestationTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(KeyDeletionTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, KeyDeletionTest, kKeymasterDeviceChoices,
android::hardware::PrintInstanceNameToString);
diff --git a/keymaster/4.0/Android.bp b/keymaster/4.0/Android.bp
index ea328f4..5774718 100644
--- a/keymaster/4.0/Android.bp
+++ b/keymaster/4.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.keymaster@4.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IKeymasterDevice.hal",
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index 3475f79..dfde060 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -195,7 +195,7 @@
* Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
* IKeymasterDevice key, as described in the Key Access Control section above.
*/
-
+@SensitiveData
interface IKeymasterDevice {
/**
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index bc7f311..8d6e74a 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -112,6 +112,11 @@
DECLARE_TYPED_TAG(ASSOCIATED_DATA);
DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
+DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
DECLARE_TYPED_TAG(AUTH_TIMEOUT);
DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
DECLARE_TYPED_TAG(BLOCK_MODE);
@@ -155,21 +160,22 @@
template <typename... Elems>
struct MetaList {};
-using all_tags_t =
- MetaList<TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t,
- TAG_MIN_MAC_LENGTH_t, TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t,
- TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
- TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t,
- TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
- TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
- TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
- TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
- TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
- TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t,
- TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
- TAG_DIGEST_t, TAG_PADDING_t, TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t,
- TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t,
- TAG_TRUSTED_CONFIRMATION_REQUIRED_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
+using all_tags_t = MetaList<
+ TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+ TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
+ TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+ TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t, TAG_USER_SECURE_ID_t,
+ TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
+ TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
+ TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_HARDWARE_TYPE_t,
+ TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
+ TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
+ TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
+ TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+ TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
+ TAG_DIGEST_t, TAG_PADDING_t, TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t,
+ TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
template <typename TypedTagType>
struct TypedTag2ValueType;
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index f495516..2ca7ea7 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -234,6 +234,7 @@
};
#define INSTANTIATE_KEYMASTER_HIDL_TEST(name) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(KeymasterHidlTest::build_params()), \
android::hardware::PrintInstanceNameToString)
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index d669667..f196928 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -4564,7 +4564,7 @@
* that aborting the operations clears the operations.
*
*/
-TEST_P(ClearOperationsTest, TooManyOperations) {
+TEST_P(ClearOperationsTest, DISABLED_TooManyOperations) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaEncryptionKey(2048, 65537)
diff --git a/keymaster/4.1/Android.bp b/keymaster/4.1/Android.bp
index f6ac6f8..4e7e944 100644
--- a/keymaster/4.1/Android.bp
+++ b/keymaster/4.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.keymaster@4.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IKeymasterDevice.hal",
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
index bbeccaa..ccb9f2e 100644
--- a/keymaster/4.1/IKeymasterDevice.hal
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -37,6 +37,7 @@
* versions will be numbered as major_version * 10 + minor version. The addition of new attestable
* tags changes the attestation format again, slightly, so the attestationVersion must be 4.
*/
+@SensitiveData
interface IKeymasterDevice extends @4.0::IKeymasterDevice {
/**
* Called by client to notify the IKeymasterDevice that the device is now locked, and keys with
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
index 152c063..f8c1fad 100644
--- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -153,6 +153,7 @@
}
#define INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(name) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(Keymaster4_1HidlTest::build_params()), \
android::hardware::PrintInstanceNameToString)
diff --git a/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
index f129783..00578a4 100644
--- a/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
index 4b2f108..19ea944 100644
--- a/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
@@ -16,6 +16,14 @@
package android.hardware.keymaster;
+
+/**
+ * Time in milliseconds since some arbitrary point in time. Time must be monotonically increasing,
+ * and a secure environment's notion of "current time" must not repeat until the Android device
+ * reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
+ * by setting the clock to zero during each boot, and then counting time accurately).
+ */
+
@VintfStability
parcelable Timestamp {
long milliSeconds;
diff --git a/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
index eff9ca6..f053254 100644
--- a/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
import android.hardware.keymaster.SecurityLevel;
import android.hardware.keymaster.Timestamp;
-import android.hardware.keymaster.HardwareAuthenticatorType;
/**
* VerificationToken instances are used for secure environments to authenticate one another.
@@ -40,6 +39,7 @@
*/
Timestamp timestamp;
+
/**
* SecurityLevel of the secure environment that generated the token.
*/
diff --git a/keymint/aidl/Android.bp b/keymint/aidl/Android.bp
new file mode 100644
index 0000000..0dae527
--- /dev/null
+++ b/keymint/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+ name: "android.hardware.keymint",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/keymint/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ rust: {
+ enabled: true,
+ },
+ },
+}
diff --git a/keymint/aidl/OWNERS b/keymint/aidl/OWNERS
new file mode 100644
index 0000000..5c79db8
--- /dev/null
+++ b/keymint/aidl/OWNERS
@@ -0,0 +1,3 @@
+jdanis@google.com
+seleneh@google.com
+swillden@google.com
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Algorithm.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Algorithm.aidl
new file mode 100644
index 0000000..f51a412
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Algorithm.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum Algorithm {
+ RSA = 1,
+ EC = 3,
+ AES = 32,
+ TRIPLE_DES = 33,
+ HMAC = 128,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BeginResult.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BeginResult.aidl
new file mode 100644
index 0000000..2f56be6
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BeginResult.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable BeginResult {
+ long challenge;
+ android.hardware.keymint.KeyParameter[] params;
+ android.hardware.keymint.IKeyMintOperation operation;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BlockMode.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BlockMode.aidl
new file mode 100644
index 0000000..94de930
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/BlockMode.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum BlockMode {
+ ECB = 1,
+ CBC = 2,
+ CTR = 3,
+ GCM = 32,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ByteArray.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ByteArray.aidl
new file mode 100644
index 0000000..2dc22a9
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ByteArray.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable ByteArray {
+ byte[] data;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Certificate.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Certificate.aidl
new file mode 100644
index 0000000..ca55054
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Certificate.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable Certificate {
+ byte[] encodedCertificate;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Digest.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Digest.aidl
new file mode 100644
index 0000000..cc4d2fd
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Digest.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum Digest {
+ NONE = 0,
+ MD5 = 1,
+ SHA1 = 2,
+ SHA_2_224 = 3,
+ SHA_2_256 = 4,
+ SHA_2_384 = 5,
+ SHA_2_512 = 6,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/EcCurve.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/EcCurve.aidl
new file mode 100644
index 0000000..4e446ad
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/EcCurve.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum EcCurve {
+ P_224 = 0,
+ P_256 = 1,
+ P_384 = 2,
+ P_521 = 3,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ErrorCode.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ErrorCode.aidl
new file mode 100644
index 0000000..2679243
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/ErrorCode.aidl
@@ -0,0 +1,100 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum ErrorCode {
+ OK = 0,
+ ROOT_OF_TRUST_ALREADY_SET = -1,
+ UNSUPPORTED_PURPOSE = -2,
+ INCOMPATIBLE_PURPOSE = -3,
+ UNSUPPORTED_ALGORITHM = -4,
+ INCOMPATIBLE_ALGORITHM = -5,
+ UNSUPPORTED_KEY_SIZE = -6,
+ UNSUPPORTED_BLOCK_MODE = -7,
+ INCOMPATIBLE_BLOCK_MODE = -8,
+ UNSUPPORTED_MAC_LENGTH = -9,
+ UNSUPPORTED_PADDING_MODE = -10,
+ INCOMPATIBLE_PADDING_MODE = -11,
+ UNSUPPORTED_DIGEST = -12,
+ INCOMPATIBLE_DIGEST = -13,
+ INVALID_EXPIRATION_TIME = -14,
+ INVALID_USER_ID = -15,
+ INVALID_AUTHORIZATION_TIMEOUT = -16,
+ UNSUPPORTED_KEY_FORMAT = -17,
+ INCOMPATIBLE_KEY_FORMAT = -18,
+ UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,
+ UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20,
+ INVALID_INPUT_LENGTH = -21,
+ KEY_EXPORT_OPTIONS_INVALID = -22,
+ DELEGATION_NOT_ALLOWED = -23,
+ KEY_NOT_YET_VALID = -24,
+ KEY_EXPIRED = -25,
+ KEY_USER_NOT_AUTHENTICATED = -26,
+ OUTPUT_PARAMETER_NULL = -27,
+ INVALID_OPERATION_HANDLE = -28,
+ INSUFFICIENT_BUFFER_SPACE = -29,
+ VERIFICATION_FAILED = -30,
+ TOO_MANY_OPERATIONS = -31,
+ UNEXPECTED_NULL_POINTER = -32,
+ INVALID_KEY_BLOB = -33,
+ IMPORTED_KEY_NOT_ENCRYPTED = -34,
+ IMPORTED_KEY_DECRYPTION_FAILED = -35,
+ IMPORTED_KEY_NOT_SIGNED = -36,
+ IMPORTED_KEY_VERIFICATION_FAILED = -37,
+ INVALID_ARGUMENT = -38,
+ UNSUPPORTED_TAG = -39,
+ INVALID_TAG = -40,
+ MEMORY_ALLOCATION_FAILED = -41,
+ IMPORT_PARAMETER_MISMATCH = -44,
+ SECURE_HW_ACCESS_DENIED = -45,
+ OPERATION_CANCELLED = -46,
+ CONCURRENT_ACCESS_CONFLICT = -47,
+ SECURE_HW_BUSY = -48,
+ SECURE_HW_COMMUNICATION_FAILED = -49,
+ UNSUPPORTED_EC_FIELD = -50,
+ MISSING_NONCE = -51,
+ INVALID_NONCE = -52,
+ MISSING_MAC_LENGTH = -53,
+ KEY_RATE_LIMIT_EXCEEDED = -54,
+ CALLER_NONCE_PROHIBITED = -55,
+ KEY_MAX_OPS_EXCEEDED = -56,
+ INVALID_MAC_LENGTH = -57,
+ MISSING_MIN_MAC_LENGTH = -58,
+ UNSUPPORTED_MIN_MAC_LENGTH = -59,
+ UNSUPPORTED_KDF = -60,
+ UNSUPPORTED_EC_CURVE = -61,
+ KEY_REQUIRES_UPGRADE = -62,
+ ATTESTATION_CHALLENGE_MISSING = -63,
+ KEYMINT_NOT_CONFIGURED = -64,
+ ATTESTATION_APPLICATION_ID_MISSING = -65,
+ CANNOT_ATTEST_IDS = -66,
+ ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
+ HARDWARE_TYPE_UNAVAILABLE = -68,
+ PROOF_OF_PRESENCE_REQUIRED = -69,
+ CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
+ NO_USER_CONFIRMATION = -71,
+ DEVICE_LOCKED = -72,
+ EARLY_BOOT_ENDED = -73,
+ ATTESTATION_KEYS_NOT_PROVISIONED = -74,
+ ATTESTATION_IDS_NOT_PROVISIONED = -75,
+ INVALID_OPERATION = -76,
+ STORAGE_KEY_UNSUPPORTED = -77,
+ UNIMPLEMENTED = -100,
+ VERSION_MISMATCH = -101,
+ UNKNOWN_ERROR = -1000,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthToken.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthToken.aidl
new file mode 100644
index 0000000..1f5f8e9
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthToken.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable HardwareAuthToken {
+ long challenge;
+ long userId;
+ long authenticatorId;
+ android.hardware.keymint.HardwareAuthenticatorType authenticatorType;
+ android.hardware.keymint.Timestamp timestamp;
+ byte[] mac;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthenticatorType.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..95ec5c5
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/HardwareAuthenticatorType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum HardwareAuthenticatorType {
+ NONE = 0,
+ PASSWORD = 1,
+ FINGERPRINT = 2,
+ ANY = -1,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintDevice.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintDevice.aidl
new file mode 100644
index 0000000..1616622
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintDevice.aidl
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+interface IKeyMintDevice {
+ android.hardware.keymint.KeyMintHardwareInfo getHardwareInfo();
+ android.hardware.keymint.VerificationToken verifyAuthorization(in long challenge, in android.hardware.keymint.HardwareAuthToken token);
+ void addRngEntropy(in byte[] data);
+ void generateKey(in android.hardware.keymint.KeyParameter[] keyParams, out android.hardware.keymint.ByteArray generatedKeyBlob, out android.hardware.keymint.KeyCharacteristics generatedKeyCharacteristics, out android.hardware.keymint.Certificate[] outCertChain);
+ void importKey(in android.hardware.keymint.KeyParameter[] inKeyParams, in android.hardware.keymint.KeyFormat inKeyFormat, in byte[] inKeyData, out android.hardware.keymint.ByteArray outImportedKeyBlob, out android.hardware.keymint.KeyCharacteristics outImportedKeyCharacteristics, out android.hardware.keymint.Certificate[] outCertChain);
+ void importWrappedKey(in byte[] inWrappedKeyData, in byte[] inWrappingKeyBlob, in byte[] inMaskingKey, in android.hardware.keymint.KeyParameter[] inUnwrappingParams, in long inPasswordSid, in long inBiometricSid, out android.hardware.keymint.ByteArray outImportedKeyBlob, out android.hardware.keymint.KeyCharacteristics outImportedKeyCharacteristics);
+ byte[] upgradeKey(in byte[] inKeyBlobToUpgrade, in android.hardware.keymint.KeyParameter[] inUpgradeParams);
+ void deleteKey(in byte[] inKeyBlob);
+ void deleteAllKeys();
+ void destroyAttestationIds();
+ android.hardware.keymint.BeginResult begin(in android.hardware.keymint.KeyPurpose inPurpose, in byte[] inKeyBlob, in android.hardware.keymint.KeyParameter[] inParams, in android.hardware.keymint.HardwareAuthToken inAuthToken);
+ const int AUTH_TOKEN_MAC_LENGTH = 32;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintOperation.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintOperation.aidl
new file mode 100644
index 0000000..5327345
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/IKeyMintOperation.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+interface IKeyMintOperation {
+ int update(in @nullable android.hardware.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable android.hardware.keymint.HardwareAuthToken inAuthToken, in @nullable android.hardware.keymint.VerificationToken inVerificationToken, out @nullable android.hardware.keymint.KeyParameterArray outParams, out @nullable android.hardware.keymint.ByteArray output);
+ byte[] finish(in @nullable android.hardware.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable byte[] inSignature, in @nullable android.hardware.keymint.HardwareAuthToken authToken, in @nullable android.hardware.keymint.VerificationToken inVerificationToken, out @nullable android.hardware.keymint.KeyParameterArray outParams);
+ void abort();
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyCharacteristics.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyCharacteristics.aidl
new file mode 100644
index 0000000..4e73381
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyCharacteristics.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable KeyCharacteristics {
+ android.hardware.keymint.KeyParameter[] softwareEnforced;
+ android.hardware.keymint.KeyParameter[] hardwareEnforced;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyDerivationFunction.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyDerivationFunction.aidl
new file mode 100644
index 0000000..8e2c774
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyDerivationFunction.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum KeyDerivationFunction {
+ NONE = 0,
+ RFC5869_SHA256 = 1,
+ ISO18033_2_KDF1_SHA1 = 2,
+ ISO18033_2_KDF1_SHA256 = 3,
+ ISO18033_2_KDF2_SHA1 = 4,
+ ISO18033_2_KDF2_SHA256 = 5,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyFormat.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyFormat.aidl
new file mode 100644
index 0000000..cfa585d
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyFormat.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum KeyFormat {
+ X509 = 0,
+ PKCS8 = 1,
+ RAW = 3,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyMintHardwareInfo.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyMintHardwareInfo.aidl
new file mode 100644
index 0000000..8263e60
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyMintHardwareInfo.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable KeyMintHardwareInfo {
+ int versionNumber;
+ android.hardware.keymint.SecurityLevel securityLevel;
+ @utf8InCpp String keyMintName;
+ @utf8InCpp String keyMintAuthorName;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyOrigin.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyOrigin.aidl
new file mode 100644
index 0000000..8d03d2b
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyOrigin.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum KeyOrigin {
+ GENERATED = 0,
+ DERIVED = 1,
+ IMPORTED = 2,
+ RESERVED = 3,
+ SECURELY_IMPORTED = 4,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameter.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameter.aidl
new file mode 100644
index 0000000..923cc68
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameter.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable KeyParameter {
+ android.hardware.keymint.Tag tag;
+ boolean boolValue;
+ int integer;
+ long longInteger;
+ byte[] blob;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameterArray.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameterArray.aidl
new file mode 100644
index 0000000..b9b9782
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyParameterArray.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable KeyParameterArray {
+ android.hardware.keymint.KeyParameter[] params;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyPurpose.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyPurpose.aidl
new file mode 100644
index 0000000..1aee56a
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/KeyPurpose.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum KeyPurpose {
+ ENCRYPT = 0,
+ DECRYPT = 1,
+ SIGN = 2,
+ VERIFY = 3,
+ WRAP_KEY = 5,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/PaddingMode.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/PaddingMode.aidl
new file mode 100644
index 0000000..97f93db
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/PaddingMode.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum PaddingMode {
+ NONE = 1,
+ RSA_OAEP = 2,
+ RSA_PSS = 3,
+ RSA_PKCS1_1_5_ENCRYPT = 4,
+ RSA_PKCS1_1_5_SIGN = 5,
+ PKCS7 = 64,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/SecurityLevel.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/SecurityLevel.aidl
new file mode 100644
index 0000000..1fb529d
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/SecurityLevel.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum SecurityLevel {
+ SOFTWARE = 0,
+ TRUSTED_ENVIRONMENT = 1,
+ STRONGBOX = 2,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
new file mode 100644
index 0000000..33a95fe
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum Tag {
+ INVALID = 0,
+ PURPOSE = 536870913,
+ ALGORITHM = 268435458,
+ KEY_SIZE = 805306371,
+ BLOCK_MODE = 536870916,
+ DIGEST = 536870917,
+ PADDING = 536870918,
+ CALLER_NONCE = 1879048199,
+ MIN_MAC_LENGTH = 805306376,
+ EC_CURVE = 268435466,
+ RSA_PUBLIC_EXPONENT = 1342177480,
+ INCLUDE_UNIQUE_ID = 1879048394,
+ BLOB_USAGE_REQUIREMENTS = 268435757,
+ BOOTLOADER_ONLY = 1879048494,
+ ROLLBACK_RESISTANCE = 1879048495,
+ HARDWARE_TYPE = 268435760,
+ EARLY_BOOT_ONLY = 1879048497,
+ ACTIVE_DATETIME = 1610613136,
+ ORIGINATION_EXPIRE_DATETIME = 1610613137,
+ USAGE_EXPIRE_DATETIME = 1610613138,
+ MIN_SECONDS_BETWEEN_OPS = 805306771,
+ MAX_USES_PER_BOOT = 805306772,
+ USER_ID = 805306869,
+ USER_SECURE_ID = -1610612234,
+ NO_AUTH_REQUIRED = 1879048695,
+ USER_AUTH_TYPE = 268435960,
+ AUTH_TIMEOUT = 805306873,
+ ALLOW_WHILE_ON_BODY = 1879048698,
+ TRUSTED_USER_PRESENCE_REQUIRED = 1879048699,
+ TRUSTED_CONFIRMATION_REQUIRED = 1879048700,
+ UNLOCKED_DEVICE_REQUIRED = 1879048701,
+ APPLICATION_ID = -1879047591,
+ APPLICATION_DATA = -1879047492,
+ CREATION_DATETIME = 1610613437,
+ ORIGIN = 268436158,
+ ROOT_OF_TRUST = -1879047488,
+ OS_VERSION = 805307073,
+ OS_PATCHLEVEL = 805307074,
+ UNIQUE_ID = -1879047485,
+ ATTESTATION_CHALLENGE = -1879047484,
+ ATTESTATION_APPLICATION_ID = -1879047483,
+ ATTESTATION_ID_BRAND = -1879047482,
+ ATTESTATION_ID_DEVICE = -1879047481,
+ ATTESTATION_ID_PRODUCT = -1879047480,
+ ATTESTATION_ID_SERIAL = -1879047479,
+ ATTESTATION_ID_IMEI = -1879047478,
+ ATTESTATION_ID_MEID = -1879047477,
+ ATTESTATION_ID_MANUFACTURER = -1879047476,
+ ATTESTATION_ID_MODEL = -1879047475,
+ VENDOR_PATCHLEVEL = 805307086,
+ BOOT_PATCHLEVEL = 805307087,
+ DEVICE_UNIQUE_ATTESTATION = 1879048912,
+ IDENTITY_CREDENTIAL_KEY = 1879048913,
+ STORAGE_KEY = 1879048914,
+ ASSOCIATED_DATA = -1879047192,
+ NONCE = -1879047191,
+ MAC_LENGTH = 805307371,
+ RESET_SINCE_ID_ROTATION = 1879049196,
+ CONFIRMATION_TOKEN = -1879047187,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/TagType.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/TagType.aidl
new file mode 100644
index 0000000..8214453
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/TagType.aidl
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@Backing(type="int") @VintfStability
+enum TagType {
+ INVALID = 0,
+ ENUM = 268435456,
+ ENUM_REP = 536870912,
+ UINT = 805306368,
+ UINT_REP = 1073741824,
+ ULONG = 1342177280,
+ DATE = 1610612736,
+ BOOL = 1879048192,
+ BIGNUM = -2147483648,
+ BYTES = -1879048192,
+ ULONG_REP = -1610612736,
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Timestamp.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Timestamp.aidl
new file mode 100644
index 0000000..f95d8db
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Timestamp.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable Timestamp {
+ long milliSeconds;
+}
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/VerificationToken.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/VerificationToken.aidl
new file mode 100644
index 0000000..7b4989a
--- /dev/null
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/VerificationToken.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files 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.keymint;
+@VintfStability
+parcelable VerificationToken {
+ long challenge;
+ android.hardware.keymint.Timestamp timestamp;
+ android.hardware.keymint.SecurityLevel securityLevel;
+ byte[] mac;
+}
diff --git a/keymint/aidl/android/hardware/keymint/Algorithm.aidl b/keymint/aidl/android/hardware/keymint/Algorithm.aidl
new file mode 100644
index 0000000..8c5d99c
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/Algorithm.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * Algorithms provided by IKeyMintDevice implementations.
+ */
+@VintfStability
+@Backing(type="int")
+enum Algorithm {
+ /** Asymmetric algorithms. */
+ RSA = 1,
+ /** 2 removed, do not reuse. */
+ EC = 3,
+
+ /** Block cipher algorithms */
+ AES = 32,
+ TRIPLE_DES = 33,
+
+ /** MAC algorithms */
+ HMAC = 128,
+}
diff --git a/keymint/aidl/android/hardware/keymint/BeginResult.aidl b/keymint/aidl/android/hardware/keymint/BeginResult.aidl
new file mode 100644
index 0000000..58eb024
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/BeginResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+import android.hardware.keymint.IKeyMintOperation;
+import android.hardware.keymint.KeyParameter;
+
+
+/**
+ * This is all the results returned by the IKeyMintDevice begin() function.
+ */
+@VintfStability
+parcelable BeginResult {
+ /* This is the challenge used in verifyAuthorization. It must be a nonce. */
+ long challenge;
+
+ /**
+ * begin() uses this field to return additional data from the operation
+ * initialization, notably to return the IV or nonce from operations
+ * that generate an IV or nonce.
+ */
+ KeyParameter[] params;
+ IKeyMintOperation operation;
+}
diff --git a/keymint/aidl/android/hardware/keymint/BlockMode.aidl b/keymint/aidl/android/hardware/keymint/BlockMode.aidl
new file mode 100644
index 0000000..b6b36cc
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/BlockMode.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * Symmetric block cipher modes provided by IKeyMintDevice implementations.
+ */
+@VintfStability
+@Backing(type="int")
+enum BlockMode {
+ /*
+ * Unauthenticated modes, usable only for encryption/decryption and not generally recommended
+ * except for compatibility with existing other protocols.
+ */
+ ECB = 1,
+ CBC = 2,
+ CTR = 3,
+
+ /*
+ * Authenticated modes, usable for encryption/decryption and signing/verification. Recommended
+ * over unauthenticated modes for all purposes.
+ */
+ GCM = 32,
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/keymint/aidl/android/hardware/keymint/ByteArray.aidl
similarity index 67%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to keymint/aidl/android/hardware/keymint/ByteArray.aidl
index cdaf847..18d187e 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/keymint/aidl/android/hardware/keymint/ByteArray.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,14 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.keymint;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+
+/**
+ * This is used to contain a byte[], to make out parameters of byte arrays
+ * more convenient for callers.
+ */
+@VintfStability
+parcelable ByteArray {
+ byte[] data;
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/keymint/aidl/android/hardware/keymint/Certificate.aidl
similarity index 62%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to keymint/aidl/android/hardware/keymint/Certificate.aidl
index cdaf847..3a70970 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/keymint/aidl/android/hardware/keymint/Certificate.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,16 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.keymint;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+/**
+ * This encodes the IKeyMintDevice attestation generated certificate.
+ */
+
+@VintfStability
+parcelable Certificate {
+ /**
+ * EncodedCertificate contains the bytes of a DER-encoded X.509 certificate.
+ */
+ byte[] encodedCertificate;
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/keymint/aidl/android/hardware/keymint/Digest.aidl
similarity index 63%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to keymint/aidl/android/hardware/keymint/Digest.aidl
index cdaf847..a92ac23 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/keymint/aidl/android/hardware/keymint/Digest.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,20 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.keymint;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+
+/**
+ * Digests provided by keyMint implementations.
+ */
+@VintfStability
+@Backing(type="int")
+enum Digest {
+ NONE = 0,
+ MD5 = 1,
+ SHA1 = 2,
+ SHA_2_224 = 3,
+ SHA_2_256 = 4,
+ SHA_2_384 = 5,
+ SHA_2_512 = 6,
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/keymint/aidl/android/hardware/keymint/EcCurve.aidl
similarity index 68%
copy from tests/safeunion/1.0/IOtherInterface.hal
copy to keymint/aidl/android/hardware/keymint/EcCurve.aidl
index cdaf847..abd44b4 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/keymint/aidl/android/hardware/keymint/EcCurve.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,17 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.keymint;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+
+/**
+ * Supported EC curves, used in ECDSA
+ */
+@VintfStability
+@Backing(type="int")
+enum EcCurve {
+ P_224 = 0,
+ P_256 = 1,
+ P_384 = 2,
+ P_521 = 3,
+}
diff --git a/keymint/aidl/android/hardware/keymint/ErrorCode.aidl b/keymint/aidl/android/hardware/keymint/ErrorCode.aidl
new file mode 100644
index 0000000..2a54954
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/ErrorCode.aidl
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * KeyMint error codes. Aidl will return these error codes as service specific
+ * errors in EX_SERVICE_SPECIFIC.
+ */
+@VintfStability
+@Backing(type="int")
+enum ErrorCode {
+ OK = 0,
+ ROOT_OF_TRUST_ALREADY_SET = -1,
+ UNSUPPORTED_PURPOSE = -2,
+ INCOMPATIBLE_PURPOSE = -3,
+ UNSUPPORTED_ALGORITHM = -4,
+ INCOMPATIBLE_ALGORITHM = -5,
+ UNSUPPORTED_KEY_SIZE = -6,
+ UNSUPPORTED_BLOCK_MODE = -7,
+ INCOMPATIBLE_BLOCK_MODE = -8,
+ UNSUPPORTED_MAC_LENGTH = -9,
+ UNSUPPORTED_PADDING_MODE = -10,
+ INCOMPATIBLE_PADDING_MODE = -11,
+ UNSUPPORTED_DIGEST = -12,
+ INCOMPATIBLE_DIGEST = -13,
+ INVALID_EXPIRATION_TIME = -14,
+ INVALID_USER_ID = -15,
+ INVALID_AUTHORIZATION_TIMEOUT = -16,
+ UNSUPPORTED_KEY_FORMAT = -17,
+ INCOMPATIBLE_KEY_FORMAT = -18,
+ UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19, /** For PKCS8 & PKCS12 */
+ UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, /** For PKCS8 & PKCS12 */
+ INVALID_INPUT_LENGTH = -21,
+ KEY_EXPORT_OPTIONS_INVALID = -22,
+ DELEGATION_NOT_ALLOWED = -23,
+ KEY_NOT_YET_VALID = -24,
+ KEY_EXPIRED = -25,
+ KEY_USER_NOT_AUTHENTICATED = -26,
+ OUTPUT_PARAMETER_NULL = -27,
+ INVALID_OPERATION_HANDLE = -28,
+ INSUFFICIENT_BUFFER_SPACE = -29,
+ VERIFICATION_FAILED = -30,
+ TOO_MANY_OPERATIONS = -31,
+ UNEXPECTED_NULL_POINTER = -32,
+ INVALID_KEY_BLOB = -33,
+ IMPORTED_KEY_NOT_ENCRYPTED = -34,
+ IMPORTED_KEY_DECRYPTION_FAILED = -35,
+ IMPORTED_KEY_NOT_SIGNED = -36,
+ IMPORTED_KEY_VERIFICATION_FAILED = -37,
+ INVALID_ARGUMENT = -38,
+ UNSUPPORTED_TAG = -39,
+ INVALID_TAG = -40,
+ MEMORY_ALLOCATION_FAILED = -41,
+ IMPORT_PARAMETER_MISMATCH = -44,
+ SECURE_HW_ACCESS_DENIED = -45,
+ OPERATION_CANCELLED = -46,
+ CONCURRENT_ACCESS_CONFLICT = -47,
+ SECURE_HW_BUSY = -48,
+ SECURE_HW_COMMUNICATION_FAILED = -49,
+ UNSUPPORTED_EC_FIELD = -50,
+ MISSING_NONCE = -51,
+ INVALID_NONCE = -52,
+ MISSING_MAC_LENGTH = -53,
+ KEY_RATE_LIMIT_EXCEEDED = -54,
+ CALLER_NONCE_PROHIBITED = -55,
+ KEY_MAX_OPS_EXCEEDED = -56,
+ INVALID_MAC_LENGTH = -57,
+ MISSING_MIN_MAC_LENGTH = -58,
+ UNSUPPORTED_MIN_MAC_LENGTH = -59,
+ UNSUPPORTED_KDF = -60,
+ UNSUPPORTED_EC_CURVE = -61,
+ KEY_REQUIRES_UPGRADE = -62,
+ ATTESTATION_CHALLENGE_MISSING = -63,
+ KEYMINT_NOT_CONFIGURED = -64,
+ ATTESTATION_APPLICATION_ID_MISSING = -65,
+ CANNOT_ATTEST_IDS = -66,
+ ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
+ HARDWARE_TYPE_UNAVAILABLE = -68,
+ PROOF_OF_PRESENCE_REQUIRED = -69,
+ CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
+ NO_USER_CONFIRMATION = -71,
+ DEVICE_LOCKED = -72,
+ EARLY_BOOT_ENDED = -73,
+ ATTESTATION_KEYS_NOT_PROVISIONED = -74,
+ ATTESTATION_IDS_NOT_PROVISIONED = -75,
+ INVALID_OPERATION = -76,
+ STORAGE_KEY_UNSUPPORTED = -77,
+
+ UNIMPLEMENTED = -100,
+ VERSION_MISMATCH = -101,
+
+ UNKNOWN_ERROR = -1000,
+
+ // Implementer's namespace for error codes starts at -10000.
+}
diff --git a/keymint/aidl/android/hardware/keymint/HardwareAuthToken.aidl b/keymint/aidl/android/hardware/keymint/HardwareAuthToken.aidl
new file mode 100644
index 0000000..9b56a2e
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/HardwareAuthToken.aidl
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.Timestamp;
+import android.hardware.keymint.HardwareAuthenticatorType;
+
+/**
+ * HardwareAuthToken is used to prove successful user authentication, to unlock the use of a key.
+ *
+ * HardwareAuthTokens are produced by other secure environment applications, notably GateKeeper and
+ * biometric authenticators, in response to successful user authentication events. These tokens are passed to
+ * begin(), update(), and finish() to prove that authentication occurred. See those methods for
+ * more details. It is up to the caller to determine which of the generated auth tokens is
+ * appropriate for a given key operation.
+ */
+@VintfStability
+parcelable HardwareAuthToken {
+
+ /**
+ * challenge is a value that's used to enable authentication tokens to authorize specific
+ * events. The primary use case for challenge is to authorize an IKeyMintDevice cryptographic
+ * operation, for keys that require authentication per operation. See begin() for details.
+ */
+ long challenge;
+
+ /**
+ * userId is the a "secure" user ID. It is not related to any Android user ID or UID, but is
+ * created in the Gatekeeper application in the secure environment.
+ */
+ long userId;
+
+ /**
+ * authenticatorId is the a "secure" user ID. It is not related to any Android user ID or UID,
+ * but is created in an authentication application in the secure environment, such as the
+ * Fingerprint application.
+ */
+ long authenticatorId;
+
+ /**
+ * authenticatorType describes the type of authentication that took place, e.g. password or
+ * fingerprint.
+ */
+ HardwareAuthenticatorType authenticatorType;
+
+ /**
+ * timestamp indicates when the user authentication took place, in milliseconds since some
+ * starting point (generally the most recent device boot) which all of the applications within
+ * one secure environment must agree upon. This timestamp is used to determine whether or not
+ * the authentication occurred recently enough to unlock a key (see Tag::AUTH_TIMEOUT).
+ */
+ Timestamp timestamp;
+
+ /**
+ * MACs are computed with a backward-compatible method, used by Keymaster 3.0, Gatekeeper 1.0
+ * and Fingerprint 1.0, as well as pre-treble HALs.
+ *
+ * The MAC is Constants::AUTH_TOKEN_MAC_LENGTH bytes in length and is computed as follows:
+ *
+ * HMAC_SHA256(
+ * H, 0 || challenge || user_id || authenticator_id || authenticator_type || timestamp)
+ *
+ * where ``||'' represents concatenation, the leading zero is a single byte, and all integers
+ * are represented as unsigned values, the full width of the type. The challenge, userId and
+ * authenticatorId values are in machine order, but authenticatorType and timestamp are in
+ * network order (big-endian). This odd construction is compatible with the hw_auth_token_t
+ * structure.
+ */
+ byte[] mac;
+}
diff --git a/keymint/aidl/android/hardware/keymint/HardwareAuthenticatorType.aidl b/keymint/aidl/android/hardware/keymint/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..5c25e2f
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/HardwareAuthenticatorType.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
+ * authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
+ * authenticating to activate a key.
+ */
+@VintfStability
+@Backing(type="int")
+enum HardwareAuthenticatorType {
+ NONE = 0,
+ PASSWORD = 1 << 0,
+ FINGERPRINT = 1 << 1,
+ // Additional entries must be powers of 2.
+ ANY = 0xFFFFFFFF,
+}
diff --git a/keymint/aidl/android/hardware/keymint/IKeyMintDevice.aidl b/keymint/aidl/android/hardware/keymint/IKeyMintDevice.aidl
new file mode 100644
index 0000000..8fbab79
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/IKeyMintDevice.aidl
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.BeginResult;
+import android.hardware.keymint.ByteArray;
+import android.hardware.keymint.Certificate;
+import android.hardware.keymint.HardwareAuthToken;
+import android.hardware.keymint.IKeyMintOperation;
+import android.hardware.keymint.KeyCharacteristics;
+import android.hardware.keymint.KeyFormat;
+import android.hardware.keymint.KeyParameter;
+import android.hardware.keymint.KeyMintHardwareInfo;
+import android.hardware.keymint.KeyPurpose;
+import android.hardware.keymint.SecurityLevel;
+import android.hardware.keymint.VerificationToken;
+
+/**
+ * KeyMint device definition.
+ *
+ * == Features ==
+ *
+ * An IKeyMintDevice provides cryptographic services, including the following categories of
+ * operations:
+ *
+ * o Key generation
+ * o Import of asymmetric keys
+ * o Import of raw symmetric keys
+ * o Asymmetric decryption with appropriate padding modes
+ * o Asymmetric signing with digesting and appropriate padding modes
+ * o Symmetric encryption and decryption in appropriate modes, including an AEAD mode
+ * o Generation and verification of symmetric message authentication codes
+ * o Attestation to the presence and configuration of asymmetric keys.
+ *
+ * Protocol elements, such as purpose, mode and padding, as well as access control constraints, must
+ * be specified by the caller when keys are generated or imported and must be permanently bound to
+ * the key, ensuring that the key cannot be used in any other way.
+ *
+ * In addition to the list above, IKeyMintDevice implementations must provide one more service
+ * which is not exposed as an API but used internally: Random number generation. The random number
+ * generator must be high-quality and must be used for generation of keys, initialization vectors,
+ * random padding and other elements of secure protocols that require randomness.
+ *
+ * == Types of IKeyMintDevices ==
+ *
+ * All of the operations and storage of key material must occur in a secure environment. Secure
+ * environments may be either:
+ *
+ * 1. Isolated execution environments, such as a separate virtual machine, hypervisor or
+ * purpose-built trusted execution environment like ARM TrustZone. The isolated environment
+ * must provide complete separation from the Android kernel and user space (collectively called
+ * the "non-secure world", or NSW) so that nothing running in the NSW can observe or manipulate
+ * the results of any computation in the isolated environment. Isolated execution environments
+ * are identified by the SecurityLevel TRUSTED_ENVIRONMENT.
+ *
+ * 2. Completely separate, purpose-built and certified secure CPUs, called "StrongBox" devices.
+ * Examples of StrongBox devices are embedded Secure Elements (eSE) or on-SoC secure processing
+ * units (iSE). StrongBox environments are identified by the SecurityLevel STRONGBOX. To
+ * qualify as a StrongBox, a device must meet the requirements specified in CDD 9.11.2.
+ *
+ * == Necessary Primitives ==
+ *
+ * All IKeyMintDevice implementations must provide support for the following:
+ *
+ * o RSA
+ *
+ * - TRUSTED_ENVIRONMENT IKeyMintDevices must support 2048, 3072 and 4096-bit keys.
+ * STRONGBOX IKeyMintDevices must support 2048-bit keys.
+ * - Public exponent F4 (2^16+1)
+ * - Unpadded, RSASSA-PSS and RSASSA-PKCS1-v1_5 padding modes for RSA signing
+ * - TRUSTED_ENVIRONMENT IKeyMintDevices must support MD5, SHA1, SHA-2 224, SHA-2 256, SHA-2
+ * 384 and SHA-2 512 digest modes for RSA signing. STRONGBOX IKeyMintDevices must support
+ * SHA-2 256.
+ * - Unpadded, RSAES-OAEP and RSAES-PKCS1-v1_5 padding modes for RSA encryption.
+ *
+ * o ECDSA
+ *
+ * - TRUSTED_ENVIRONMENT IKeyMintDevices must support NIST curves P-224, P-256, P-384 and
+ * P-521. STRONGBOX IKeyMintDevices must support NIST curve P-256.
+ * - TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256, SHA-2
+ * 384 and SHA-2 512 digest modes. STRONGBOX IKeyMintDevices must support SHA-2 256.
+ *
+ * o AES
+ *
+ * - 128 and 256-bit keys
+ * - CBC, CTR, ECB and GCM modes. The GCM mode must not allow the use of tags smaller than 96
+ * bits or nonce lengths other than 96 bits.
+ * - CBC and ECB modes must support unpadded and PKCS7 padding modes. With no padding CBC and
+ * ECB-mode operations must fail with ErrorCode::INVALID_INPUT_LENGTH if the input isn't a
+ * multiple of the AES block size. With PKCS7 padding, GCM and CTR operations must fail with
+ * ErrorCode::INCOMPATIBLE_PADDING_MODE.
+ *
+ * o 3DES
+ *
+ * - 168-bit keys.
+ * - CBC and ECB mode.
+
+ * - CBC and ECB modes must support unpadded and PKCS7 padding modes. With no padding CBC and
+ * ECB-mode operations must fail with ErrorCode::INVALID_INPUT_LENGTH if the input isn't a
+ * multiple of the DES block size.
+ *
+ * o HMAC
+ *
+ * - Any key size that is between 64 and 512 bits (inclusive) and a multiple of 8 must be
+ * supported. STRONGBOX IKeyMintDevices must not support keys larger than 512 bits.
+ * - TRUSTED_ENVIRONMENT IKeyMintDevices must support MD-5, SHA1, SHA-2-224, SHA-2-256,
+ * SHA-2-384 and SHA-2-512. STRONGBOX IKeyMintDevices must support SHA-2-256.
+ *
+ * == Key Access Control ==
+ *
+ * Hardware-based keys that can never be extracted from the device don't provide much security if an
+ * attacker can use them at will (though they're more secure than keys which can be
+ * exfiltrated). Therefore, IKeyMintDevice must enforce access controls.
+ *
+ * Access controls are defined as an "authorization list" of tag/value pairs. Authorization tags
+ * are 32-bit integers from the Tag enum, and the values are a variety of types, defined in the
+ * TagType enum. Some tags may be repeated to specify multiple values. Whether a tag may be
+ * repeated is specified in the documentation for the tag and in the TagType. When a key is
+ * created or imported, the caller specifies an authorization list. The IKeyMintDevice must divide
+ * the caller-provided authorizations into two lists, those it enforces in tee secure zone and
+ * those enforced in the strongBox hardware. These two lists are returned as the "teeEnforced"
+ * and "strongboxEnforced" elements of the KeyCharacteristics struct. Note that software enforced
+ * authorization list entries are not returned because they are not enforced by keymint. The
+ * IKeyMintDevice must also add the following authorizations to the appropriate list:
+ *
+ * o Tag::OS_VERSION
+ * o Tag::OS_PATCHLEVEL
+ * o Tag::VENDOR_PATCHLEVEL
+ * o Tag::BOOT_PATCHLEVEL
+ * o Tag::ORIGIN
+ *
+ * The IKeyMintDevice must ignore unknown tags.
+ *
+ * The caller must always provide the current date time in the keyParameter CREATION_DATETIME
+ * tags.
+ *
+ * All authorization tags and their values, both teeEnforced and strongboxEnforced, including
+ * unknown tags, must be cryptographically bound to the private/secret key material such that any
+ * modification of the portion of the key blob that contains the authorization list makes it
+ * impossible for the secure environment to obtain the private/secret key material. The
+ * recommended approach to meet this requirement is to use the full set of authorization tags
+ * associated with a key as input to a secure key derivation function used to derive a key that
+ * is used to encrypt the private/secret key material.
+ *
+ * IKeyMintDevice implementations ignore any tags they cannot enforce and do not return them
+ * in KeyCharacteristics. For example, Tag::ORIGINATION_EXPIRE_DATETIME provides the date and
+ * time after which a key may not be used to encrypt or sign new messages. Unless the
+ * IKeyMintDevice has access to a secure source of current date/time information, it is not
+ * possible for the IKeyMintDevice to enforce this tag. An IKeyMintDevice implementation will
+ * not rely on the non-secure world's notion of time, because it could be controlled by an
+ * attacker. Similarly, it cannot rely on GPSr time, even if it has exclusive control of the
+ * GPSr, because that might be spoofed by attacker RF signals.
+ *
+ * IKeyMintDevices do not use or enforce any tags they place in the softwareEnforced
+ * list. The IKeyMintDevice caller must enforce them, and it is unnecessary to enforce them
+ * twice.
+ *
+ * Some tags must be enforced by the IKeyMintDevice. See the detailed documentation on each Tag
+ * in Tag.aidl.
+ *
+ * == Root of Trust Binding ==
+ *
+ * IKeyMintDevice keys must be bound to a root of trust, which is a bitstring that must be
+ * provided to the secure environment (by an unspecified, implementation-defined mechanism) during
+ * startup, preferably by the bootloader. This bitstring must be cryptographically bound to every
+ * key managed by the IKeyMintDevice. As above, the recommended mechanism for this cryptographic
+ * binding is to include the Root of Trust data in the input to the key derivation function used to
+ * derive a key that is used to encryp the private/secret key material.
+ *
+ * The root of trust consists of a bitstring that must be derived from the public key used by
+ * Verified Boot to verify the signature on the boot image and from the lock state of the
+ * device. If the public key is changed to allow a different system image to be used or if the
+ * lock state is changed, then all of the IKeyMintDevice-protected keys created by the previous
+ * system state must be unusable, unless the previous state is restored. The goal is to increase
+ * the value of the software-enforced key access controls by making it impossible for an attacker-
+ * installed operating system to use IKeyMintDevice keys.
+ *
+ * == Version Binding ==
+ *
+ * All keys must also be bound to the operating system and patch level of the system image and the
+ * patch levels of the vendor image and boot image. This ensures that an attacker who discovers a
+ * weakness in an old version of the software cannot roll a device back to the vulnerable version
+ * and use keys created with the newer version. In addition, when a key with a given version and
+ * patch level is used on a device that has been upgraded to a newer version or patch level, the
+ * key must be upgraded (See IKeyMintDevice::upgradeKey()) before it can be used, and the previous
+ * version of the key must be invalidated. In this way, as the device is upgraded, the keys will
+ * "ratchet" forward along with the device, but any reversion of the device to a previous release
+ * will cause the keys to be unusable.
+ *
+ * This version information must be associated with every key as a set of tag/value pairs in the
+ * hardwareEnforced authorization list. Tag::OS_VERSION, Tag::OS_PATCHLEVEL,
+ * Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
+ * IKeyMintDevice key, as described in the Key Access Control section above.
+ */
+@VintfStability
+interface IKeyMintDevice {
+ const int AUTH_TOKEN_MAC_LENGTH = 32;
+
+ /**
+ * @return info which contains information about the underlying IKeyMintDevice hardware, such
+ * as version number, security level, keyMint name and author name.
+ */
+ KeyMintHardwareInfo getHardwareInfo();
+
+ /**
+ * Verify authorizations for another IKeyMintDevice instance.
+ *
+ * On systems with both a StrongBox and a TEE IKeyMintDevice instance it is sometimes useful
+ * to ask the TEE KeyMintDevice to verify authorizations for a key hosted in StrongBox.
+ *
+ * For every StrongBox operation, Keystore is required to call this method on the TEE KeyMint,
+ * passing in the StrongBox key's hardwareEnforced authorization list and the challenge
+ * returned by StrongBox begin(). Keystore must then pass the VerificationToken to the
+ * subsequent invocations of StrongBox update() and finish().
+ *
+ * StrongBox implementations must return ErrorCode::UNIMPLEMENTED.
+ *
+ * @param the challenge returned by StrongBox's keyMint's begin().
+ *
+ * @param authToken A HardwareAuthToken if needed to authorize key usage.
+ *
+ * @return error ErrorCode::OK on success or ErrorCode::UNIMPLEMENTED if the KeyMintDevice is
+ * a StrongBox. If the IKeyMintDevice cannot verify one or more elements of
+ * parametersToVerify it must not return an error code, but just omit the unverified
+ * parameter from the VerificationToken.
+ *
+ * @return token the verification token. See VerificationToken in VerificationToken.aidl for
+ * details.
+ */
+ VerificationToken verifyAuthorization(in long challenge,
+ in HardwareAuthToken token);
+
+ /**
+ * Adds entropy to the RNG used by KeyMint. Entropy added through this method must not be the
+ * only source of entropy used, and a secure mixing function must be used to mix the entropy
+ * provided by this method with internally-generated entropy. The mixing function must be
+ * secure in the sense that if any one of the mixing function inputs is provided with any data
+ * the attacker cannot predict (or control), then the output of the seeded CRNG is
+ * indistinguishable from random. Thus, if the entropy from any source is good, the output
+ * must be good.
+ *
+ * TODO(seleneh) specify what mixing functions and cprng we allow.
+ *
+ * @param data Bytes to be mixed into the CRNG seed. The caller must not provide more than 2
+ * KiB of data per invocation.
+ *
+ * @return error ErrorCode::OK on success; ErrorCode::INVALID_INPUT_LENGTH if the caller
+ * provides more than 2 KiB of data.
+ */
+ void addRngEntropy(in byte[] data);
+
+ /**
+ * Generates a new cryptographic key, specifying associated parameters, which must be
+ * cryptographically bound to the key. IKeyMintDevice implementations must disallow any use
+ * of a key in any way inconsistent with the authorizations specified at generation time. With
+ * respect to parameters that the secure environment cannot enforce, the secure envionment's
+ * obligation is limited to ensuring that the unenforceable parameters associated with the key
+ * cannot be modified. In addition, the characteristics returned by generateKey places
+ * parameters correctly in the tee-enforced and strongbox-enforced lists.
+ *
+ * In addition to the parameters provided, generateKey must add the following to the returned
+ * characteristics.
+ *
+ * o Tag::ORIGIN with the value KeyOrigin::GENERATED.
+ *
+ * o Tag::BLOB_USAGE_REQUIREMENTS with the appropriate value (see KeyBlobUsageRequirements in
+ * Tag.aidl).
+ *
+ * o Tag::OS_VERSION, Tag::OS_PATCHLEVEL, Tag::VENDOR_PATCHLEVEL and Tag::BOOT_PATCHLEVEL with
+ * appropriate values.
+ *
+ * The parameters provided to generateKey depend on the type of key being generated. This
+ * section summarizes the necessary and optional tags for each type of key. Tag::ALGORITHM is
+ * always necessary, to specify the type.
+ *
+ * == RSA Keys ==
+ *
+ * The following parameters are required to generate an RSA key:
+ *
+ * o Tag::Key_SIZE specifies the size of the public modulus, in bits. If omitted, generateKey
+ * must return ErrorCode::UNSUPPORTED_KEY_SIZE. Required values for TEE IKeyMintDevice
+ * implementations are 1024, 2048, 3072 and 4096. StrongBox IKeyMintDevice implementations
+ * must support 2048.
+ *
+ * o Tag::RSA_PUBLIC_EXPONENT specifies the RSA public exponent value. If omitted, generateKey
+ * must return ErrorCode::INVALID_ARGUMENT. The values 3 and 65537 must be supported. It is
+ * recommended to support all prime values up to 2^64. If provided with a non-prime value,
+ * generateKey must return ErrorCode::INVALID_ARGUMENT.
+ *
+ * The following parameters are not necessary to generate a usable RSA key, but generateKey must
+ * not return an error if they are omitted:
+ *
+ * o Tag::PURPOSE specifies allowed purposes. All KeyPurpose values (see KeyPurpose.aidl)
+ * except AGREE_KEY must be supported for RSA keys.
+ *
+ * o Tag::DIGEST specifies digest algorithms that may be used with the new key. TEE
+ * IKeyMintDevice implementatiosn must support all Digest values (see digest.aidl) for RSA
+ * keys. StrongBox IKeyMintDevice implementations must support SHA_2_256.
+ *
+ * o Tag::PADDING specifies the padding modes that may be used with the new
+ * key. IKeyMintDevice implementations must support PaddingMode::NONE,
+ * PaddingMode::RSA_OAEP, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
+ * PaddingMode::RSA_PKCS1_1_5_SIGN for RSA keys.
+ *
+ * == ECDSA Keys ==
+ *
+ * Either Tag::KEY_SIZE or Tag::EC_CURVE must be provided to generate an ECDSA key. If neither
+ * is provided, generateKey must return ErrorCode::UNSUPPORTED_KEY_SIZE. If Tag::KEY_SIZE is
+ * provided, the possible values are 224, 256, 384 and 521, and must be mapped to Tag::EC_CURVE
+ * values P_224, P_256, P_384 and P_521, respectively. TEE IKeyMintDevice implementations
+ * must support all curves. StrongBox implementations must support P_256.
+ *
+ * == AES Keys ==
+ *
+ * Only Tag::KEY_SIZE is required to generate an AES key. If omitted, generateKey must return
+ * ErrorCode::UNSUPPORTED_KEY_SIZE. 128 and 256-bit key sizes must be supported.
+ *
+ * If Tag::BLOCK_MODE is specified with value BlockMode::GCM, then the caller must also provide
+ * Tag::MIN_MAC_LENGTH. If omitted, generateKey must return ErrorCode::MISSING_MIN_MAC_LENGTH.
+ *
+ *
+ * @param keyParams Key generation parameters are defined as KeyMintDevice tag/value pairs,
+ * provided in params. See above for detailed specifications of which tags are required
+ * for which types of keys.
+ *
+ * @return generatedKeyBlob Opaque descriptor of the generated key. The recommended
+ * implementation strategy is to include an encrypted copy of the key material, wrapped
+ * in a key unavailable outside secure hardware.
+ *
+ * @return generatedKeyCharacteristics Description of the generated key, divided into two sets:
+ * hardware-enforced and software-enforced. The description here applies equally
+ * to the key characteristics lists returned by generateKey, importKey and
+ * importWrappedKey. The characteristics returned by this parameter completely
+ * describe the type and usage of the specified key.
+ *
+ * The rule that IKeyMintDevice implementations must use for deciding whether a
+ * given tag belongs in the hardware-enforced or software-enforced list is that if
+ * the meaning of the tag is fully assured by secure hardware, it is hardware
+ * enforced. Otherwise, it's software enforced.
+ *
+ * @return outCertChain If the key is an asymmetric key, and proper keyparameters for
+ * attestation (such as challenge) is provided, then this parameter will return the
+ * attestation certificate. If the signing of the attestation certificate is from a
+ * factory key, additional certificates back to the root attestation certificate will
+ * also be provided. Clients will need to check root certificate against a known-good
+ * value. The certificates must be DER-encoded. Caller needs to provide
+ * CREATION_DATETIME as one of the attestation parameters, otherwise the attestation
+ * certificate will not contain the creation datetime. The first certificate in the
+ * vector is the attestation for the generated key itself, the next certificate is
+ * the key that signs the first certificate, and so forth. The last certificate in
+ * the chain is the root certificate. If the key is a symmetric key, then no
+ * certificate will be returned and this variable will return empty. TODO: change
+ * certificate return to a single certificate and make it nullable b/163604282.
+ */
+ void generateKey(in KeyParameter[] keyParams, out ByteArray generatedKeyBlob,
+ out KeyCharacteristics generatedKeyCharacteristics,
+ out Certificate[] outCertChain);
+
+ /**
+ * Imports key material into an IKeyMintDevice. Key definition parameters and return values
+ * are the same as for generateKey, with the following exceptions:
+ *
+ * o Tag::KEY_SIZE is not necessary in the input parameters. If not provided, the
+ * IKeyMintDevice must deduce the value from the provided key material and add the tag and
+ * value to the key characteristics. If Tag::KEY_SIZE is provided, the IKeyMintDevice must
+ * validate it against the key material. In the event of a mismatch, importKey must return
+ * ErrorCode::IMPORT_PARAMETER_MISMATCH.
+ *
+ * o Tag::RSA_PUBLIC_EXPONENT (for RSA keys only) is not necessary in the input parameters. If
+ * not provided, the IKeyMintDevice must deduce the value from the provided key material and
+ * add the tag and value to the key characteristics. If Tag::RSA_PUBLIC_EXPONENT is provided,
+ * the IKeyMintDevice must validate it against the key material. In the event of a
+ * mismatch, importKey must return ErrorCode::IMPORT_PARAMETER_MISMATCH.
+ *
+ * o Tag::ORIGIN (returned in keyCharacteristics) must have the value KeyOrigin::IMPORTED.
+ *
+ * @param inKeyParams Key generation parameters are defined as KeyMintDevice tag/value pairs,
+ * provided in params.
+ *
+ * @param inKeyFormat The format of the key material to import. See KeyFormat in
+ * keyformat.aidl.
+ *
+ * @param inKeyData The key material to import, in the format specified in keyFormat.
+ *
+ * @return outImportedKeyBlob descriptor of the imported key. The format of the keyblob will
+ * be the google specified keyblob format.
+ *
+ * @return outImportedKeyCharacteristics Description of the generated key. See the
+ * keyCharacteristics description in generateKey.
+ *
+ * @return outCertChain If the key is an asymmetric key, and proper keyparameters for
+ * attestation (such as challenge) is provided, then this parameter will return the
+ * attestation certificate. If the signing of the attestation certificate is from a
+ * factory key, additional certificates back to the root attestation certificate will
+ * also be provided. Clients will need to check root certificate against a known-good
+ * value. The certificates must be DER-encoded. Caller needs to provide
+ * CREATION_DATETIME as one of the attestation parameters, otherwise the attestation
+ * certificate will not contain the creation datetime. The first certificate in the
+ * vector is the attestation for the generated key itself, the next certificate is
+ * the key that signs the first certificate, and so forth. The last certificate in
+ * the chain is the root certificate. If the key is a symmetric key, then no
+ * certificate will be returned and this variable will return empty.
+ */
+ void importKey(in KeyParameter[] inKeyParams, in KeyFormat inKeyFormat,
+ in byte[] inKeyData, out ByteArray outImportedKeyBlob,
+ out KeyCharacteristics outImportedKeyCharacteristics,
+ out Certificate[] outCertChain);
+
+ /**
+ * Securely imports a key, or key pair, returning a key blob and a description of the imported
+ * key.
+ *
+ * @param inWrappedKeyData The wrapped key material to import.
+ * TODO(seleneh) Decide if we want the wrapped key in DER-encoded ASN.1 format or CBOR
+ * format or both. And specify the standarized format.
+ *
+ * KeyDescription ::= SEQUENCE(
+ * keyFormat INTEGER, # Values from KeyFormat enum.
+ * keyParams AuthorizationList,
+ * )
+ *
+ * SecureKeyWrapper ::= SEQUENCE(
+ * version INTEGER, # Contains value 0
+ * encryptedTransportKey OCTET_STRING,
+ * initializationVector OCTET_STRING,
+ * keyDescription KeyDescription,
+ * encryptedKey OCTET_STRING,
+ * tag OCTET_STRING
+ * )
+ *
+ * Where:
+ *
+ * o keyFormat is an integer from the KeyFormat enum, defining the format of the plaintext
+ * key material.
+ * o keyParams is the characteristics of the key to be imported (as with generateKey or
+ * importKey). If the secure import is successful, these characteristics must be
+ * associated with the key exactly as if the key material had been insecurely imported
+ * with the IKeyMintDevice::importKey. See attestKey() for documentation of the
+ * AuthorizationList schema.
+ * o encryptedTransportKey is a 256-bit AES key, XORed with a masking key and then encrypted
+ * with the wrapping key specified by wrappingKeyBlob.
+ * o keyDescription is a KeyDescription, above.
+ * o encryptedKey is the key material of the key to be imported, in format keyFormat, and
+ * encrypted with encryptedEphemeralKey in AES-GCM mode, with the DER-encoded
+ * representation of keyDescription provided as additional authenticated data.
+ * o tag is the tag produced by the AES-GCM encryption of encryptedKey.
+ *
+ * So, importWrappedKey does the following:
+ *
+ * 1. Get the private key material for wrappingKeyBlob, verifying that the wrapping key has
+ * purpose KEY_WRAP, padding mode RSA_OAEP, and digest SHA_2_256, returning the
+ * error INCOMPATIBLE_PURPOSE, INCOMPATIBLE_PADDING_MODE, or INCOMPATIBLE_DIGEST if any
+ * of those requirements fail.
+ * 2. Extract the encryptedTransportKey field from the SecureKeyWrapper, and decrypt
+ * it with the wrapping key.
+ * 3. XOR the result of step 2 with maskingKey.
+ * 4. Use the result of step 3 as an AES-GCM key to decrypt encryptedKey, using the encoded
+ * value of keyDescription as the additional authenticated data. Call the result
+ * "keyData" for the next step.
+ * 5. Perform the equivalent of calling importKey(keyParams, keyFormat, keyData), except
+ * that the origin tag should be set to SECURELY_IMPORTED.
+ *
+ * @param inWrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey().
+ * This key must have been created with Purpose::WRAP_KEY.
+ *
+ * @param inMaskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
+ * structure.
+ *
+ * @param inUnwrappingParams must contain any parameters needed to perform the unwrapping
+ * operation. For example, if the wrapping key is an AES key the block and padding
+ * modes must be specified in this argument.
+ *
+ * @param inPasswordSid specifies the password secure ID (SID) of the user that owns the key
+ * being installed. If the authorization list in wrappedKeyData contains a
+ * Tag::USER_SECURE_IDwith a value that has the HardwareAuthenticatorType::PASSWORD
+ * bit set, the constructed key must be bound to the SID value provided by this
+ * argument. If the wrappedKeyData does not contain such a tag and value, this argument
+ * must be ignored.
+ *
+ * @param inBiometricSid specifies the biometric secure ID (SID) of the user that owns the key
+ * being installed. If the authorization list in wrappedKeyData contains a
+ * Tag::USER_SECURE_ID with a value that has the HardwareAuthenticatorType::FINGERPRINT
+ * bit set, the constructed key must be bound to the SID value provided by this argument.
+ * If the wrappedKeyData does not contain such a tag and value, this argument must be
+ * ignored.
+ *
+ * @return outImportedKeyBlob Opaque descriptor of the imported key. It is recommended that
+ * the keyBlob contain a copy of the key material, wrapped in a key unavailable outside
+ * secure hardware.
+ *
+ * @return outImportedKeyCharacteristics Description of the generated key. See the description
+ * of keyCharacteristics parameter in generateKey.
+ */
+ void importWrappedKey(in byte[] inWrappedKeyData,
+ in byte[] inWrappingKeyBlob,
+ in byte[] inMaskingKey,
+ in KeyParameter[] inUnwrappingParams,
+ in long inPasswordSid,
+ in long inBiometricSid,
+ out ByteArray outImportedKeyBlob,
+ out KeyCharacteristics outImportedKeyCharacteristics);
+
+ /**
+ * Upgrades an old key blob. Keys can become "old" in two ways: IKeyMintDevice can be
+ * upgraded to a new version with an incompatible key blob format, or the system can be updated
+ * to invalidate the OS version (OS_VERSION tag), system patch level (OS_PATCHLEVEL tag),
+ * vendor patch level (VENDOR_PATCH_LEVEL tag), boot patch level (BOOT_PATCH_LEVEL tag) or
+ * other, implementation-defined patch level (keyMint implementers are encouraged to extend
+ * this HAL with a minor version extension to define validatable patch levels for other
+ * images; tags must be defined in the implementer's namespace, starting at 10000). In either
+ * case, attempts to use an old key blob with begin() must result in IKeyMintDevice returning
+ * ErrorCode::KEY_REQUIRES_UPGRADE. The caller must use this method to upgrade the key blob.
+ *
+ * The upgradeKey method must examine each version or patch level associated with the key. If
+ * any one of them is higher than the corresponding current device value upgradeKey() must
+ * return ErrorCode::INVALID_ARGUMENT. There is one exception: it is always permissible to
+ * "downgrade" from any OS_VERSION number to OS_VERSION 0. For example, if the key has
+ * OS_VERSION 080001, it is permisible to upgrade the key if the current system version is
+ * 080100, because the new version is larger, or if the current system version is 0, because
+ * upgrades to 0 are always allowed. If the system version were 080000, however, keyMint must
+ * return ErrorCode::INVALID_ARGUMENT because that value is smaller than 080001. Values other
+ * than OS_VERSION must never be downgraded.
+ *
+ * Note that Keymaster versions 2 and 3 required that the system and boot images have the same
+ * patch level and OS version. This requirement is relaxed for 4.0::IKeymasterDevice and
+ * IKeyMintDevice, and the OS version in the boot image footer is no longer used.
+ *
+ * @param inKeyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+ *
+ * @param inUpgradeParams A parameter list containing any parameters needed to complete the
+ * upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
+ *
+ * @return A new key blob that references the same key as keyBlobToUpgrade, but is in the new
+ * format, or has the new version data.
+ */
+ byte[] upgradeKey(in byte[] inKeyBlobToUpgrade, in KeyParameter[] inUpgradeParams);
+
+ /**
+ * Deletes the key, or key pair, associated with the key blob. Calling this function on
+ * a key with Tag::ROLLBACK_RESISTANCE in its hardware-enforced authorization list must
+ * render the key permanently unusable. Keys without Tag::ROLLBACK_RESISTANCE may or
+ * may not be rendered unusable.
+ *
+ * @param inKeyBlob The opaque descriptor returned by generateKey() or importKey();
+ */
+ void deleteKey(in byte[] inKeyBlob);
+
+ /**
+ * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
+ * this function is called all keys with Tag::ROLLBACK_RESISTANCE in their hardware-enforced
+ * authorization lists must be rendered permanently unusable. Keys without
+ * Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
+ *
+ * @return error See the ErrorCode enum.
+ */
+ void deleteAllKeys();
+
+ /**
+ * Destroys knowledge of the device's ids. This prevents all device id attestation in the
+ * future. The destruction must be permanent so that not even a factory reset will restore the
+ * device ids.
+ *
+ * Device id attestation may be provided only if this method is fully implemented, allowing the
+ * user to permanently disable device id attestation. If this cannot be guaranteed, the device
+ * must never attest any device ids.
+ *
+ * This is a NOP if device id attestation is not supported.
+ */
+ void destroyAttestationIds();
+
+ /**
+ * Begins a cryptographic operation using the specified key. If all is well, begin() must
+ * return ErrorCode::OK and create an operation handle which must be passed to subsequent calls
+ * to update(), finish() or abort().
+ *
+ * It is critical that each call to begin() be paired with a subsequent call to finish() or
+ * abort(), to allow the IKeyMintDevice implementation to clean up any internal operation
+ * state. The caller's failure to do this may leak internal state space or other internal
+ * resources and may eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it
+ * runs out of space for operations. Any result other than ErrorCode::OK from begin(), update()
+ * or finish() implicitly aborts the operation, in which case abort() need not be called (and
+ * must return ErrorCode::INVALID_OPERATION_HANDLE if called). IKeyMintDevice implementations
+ * must support 32 concurrent operations.
+ *
+ * If Tag::APPLICATION_ID or Tag::APPLICATION_DATA were specified during key generation or
+ * import, calls to begin must include those tags with the originally-specified values in the
+ * inParams argument to this method. If not, begin() must return ErrorCode::INVALID_KEY_BLOB.
+ *
+ * == Authorization Enforcement ==
+ *
+ * The following key authorization parameters must be enforced by the IKeyMintDevice secure
+ * environment if the tags were returned in the "hardwareEnforced" list in the
+ * KeyCharacteristics. Public key operations, meaning KeyPurpose::ENCRYPT and
+ * KeyPurpose::VERIFY must be allowed to succeed even if authorization requirements are not met.
+ *
+ * -- All Key Types --
+ *
+ * The tags in this section apply to all key types. See below for additional key type-specific
+ * tags.
+ *
+ * o Tag::PURPOSE: The purpose specified in the begin() call must match one of the purposes in
+ * the key authorizations. If the specified purpose does not match, begin() must return
+ * ErrorCode::UNSUPPORTED_PURPOSE.
+ *
+ * o Tag::ACTIVE_DATETIME can only be enforced if a trusted UTC time source is available. If
+ * the current date and time is prior to the tag value, begin() must return
+ * ErrorCode::KEY_NOT_YET_VALID.
+ *
+ * o Tag::ORIGINATION_EXPIRE_DATETIME can only be enforced if a trusted UTC time source is
+ * available. If the current date and time is later than the tag value and the purpose is
+ * KeyPurpose::ENCRYPT or KeyPurpose::SIGN, begin() must return ErrorCode::KEY_EXPIRED.
+ *
+ * o Tag::USAGE_EXPIRE_DATETIME can only be enforced if a trusted UTC time source is
+ * available. If the current date and time is later than the tag value and the purpose is
+ * KeyPurpose::DECRYPT or KeyPurpose::VERIFY, begin() must return ErrorCode::KEY_EXPIRED.
+ *
+ * o Tag::MAX_USES_PER_BOOT must be compared against a secure counter that tracks the uses of
+ * the key since boot time. If the count of previous uses exceeds the tag value, begin() must
+ * return ErrorCode::KEY_MAX_OPS_EXCEEDED.
+ *
+ * o Tag::USER_SECURE_ID must be enforced by this method if and only if the key also has
+ * Tag::AUTH_TIMEOUT (if it does not have Tag::AUTH_TIMEOUT, the Tag::USER_SECURE_ID
+ * requirement must be enforced by update() and finish()). If the key has both, then this
+ * method must receive a non-empty HardwareAuthToken in the authToken argument. For the auth
+ * token to be valid, all of the following have to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
+ * the current secure timestamp (which is a monotonic timer counting milliseconds since
+ * boot.)
+ *
+ * If any of these conditions are not met, begin() must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * o Tag::CALLER_NONCE allows the caller to specify a nonce or initialization vector (IV). If
+ * the key doesn't have this tag, but the caller provided Tag::NONCE to this method,
+ * ErrorCode::CALLER_NONCE_PROHIBITED must be returned.
+ *
+ * o Tag::BOOTLOADER_ONLY specifies that only the bootloader may use the key. If this method is
+ * called with a bootloader-only key after the bootloader has finished executing, it must
+ * return ErrorCode::INVALID_KEY_BLOB. The mechanism for notifying the IKeyMintDevice that
+ * the bootloader has finished executing is implementation-defined.
+ *
+ * -- RSA Keys --
+ *
+ * All RSA key operations must specify exactly one padding mode in inParams. If unspecified or
+ * specified more than once, the begin() must return ErrorCode::UNSUPPORTED_PADDING_MODE.
+ *
+ * RSA signing and verification operations need a digest, as do RSA encryption and decryption
+ * operations with OAEP padding mode. For those cases, the caller must specify exactly one
+ * digest in inParams. If unspecified or specified more than once, begin() must return
+ * ErrorCode::UNSUPPORTED_DIGEST.
+ *
+ * Private key operations (KeyPurpose::DECRYPT and KeyPurpose::SIGN) need authorization of
+ * digest and padding, which means that the key authorizations need to contain the specified
+ * values. If not, begin() must return ErrorCode::INCOMPATIBLE_DIGEST or
+ * ErrorCode::INCOMPATIBLE_PADDING, as appropriate. Public key operations (KeyPurpose::ENCRYPT
+ * and KeyPurpose::VERIFY) are permitted with unauthorized digest or padding modes.
+ *
+ * With the exception of PaddingMode::NONE, all RSA padding modes are applicable only to certain
+ * purposes. Specifically, PaddingMode::RSA_PKCS1_1_5_SIGN and PaddingMode::RSA_PSS only
+ * support signing and verification, while PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
+ * PaddingMode::RSA_OAEP only support encryption and decryption. begin() must return
+ * ErrorCode::UNSUPPORTED_PADDING_MODE if the specified mode does not support the specified
+ * purpose.
+ *
+ * There are some important interactions between padding modes and digests:
+ *
+ * o PaddingMode::NONE indicates that a "raw" RSA operation is performed. If signing or
+ * verifying, Digest::NONE is specified for the digest. No digest is necessary for unpadded
+ * encryption or decryption.
+ *
+ * o PaddingMode::RSA_PKCS1_1_5_SIGN padding requires a digest. The digest may be Digest::NONE,
+ * in which case the KeyMint implementation cannot build a proper PKCS#1 v1.5 signature
+ * structure, because it cannot add the DigestInfo structure. Instead, the IKeyMintDevice
+ * must construct 0x00 || 0x01 || PS || 0x00 || M, where M is the provided message and PS is a
+ * random padding string at least eight bytes in length. The size of the RSA key has to be at
+ * least 11 bytes larger than the message, otherwise begin() must return
+ * ErrorCode::INVALID_INPUT_LENGTH.
+ *
+ * o PaddingMode::RSA_PKCS1_1_1_5_ENCRYPT padding does not require a digest.
+ *
+ * o PaddingMode::RSA_PSS padding requires a digest, which may not be Digest::NONE. If
+ * Digest::NONE is specified, the begin() must return ErrorCode::INCOMPATIBLE_DIGEST. In
+ * addition, the size of the RSA key must be at least 2 + D bytes larger than the output size
+ * of the digest, where D is the size of the digest, in bytes. Otherwise begin() must
+ * return ErrorCode::INCOMPATIBLE_DIGEST. The salt size must be D.
+ *
+ * o PaddingMode::RSA_OAEP padding requires a digest, which may not be Digest::NONE. If
+ * Digest::NONE is specified, begin() must return ErrorCode::INCOMPATIBLE_DIGEST. The OAEP
+ * mask generation function must be MGF1 and the MGF1 digest must be SHA1, regardless of the
+ * OAEP digest specified.
+ *
+ * -- EC Keys --
+ *
+ * EC key operations must specify exactly one padding mode in inParams. If unspecified or
+ * specified more than once, begin() must return ErrorCode::UNSUPPORTED_PADDING_MODE.
+ *
+ * Private key operations (KeyPurpose::SIGN) need authorization of digest and padding, which
+ * means that the key authorizations must contain the specified values. If not, begin() must
+ * return ErrorCode::INCOMPATIBLE_DIGEST. Public key operations (KeyPurpose::VERIFY) are
+ * permitted with unauthorized digest or padding.
+ *
+ * -- AES Keys --
+ *
+ * AES key operations must specify exactly one block mode (Tag::BLOCK_MODE) and one padding mode
+ * (Tag::PADDING) in inParams. If either value is unspecified or specified more than once,
+ * begin() must return ErrorCode::UNSUPPORTED_BLOCK_MODE or
+ * ErrorCode::UNSUPPORTED_PADDING_MODE. The specified modes must be authorized by the key,
+ * otherwise begin() must return ErrorCode::INCOMPATIBLE_BLOCK_MODE or
+ * ErrorCode::INCOMPATIBLE_PADDING_MODE.
+ *
+ * If the block mode is BlockMode::GCM, inParams must specify Tag::MAC_LENGTH, and the specified
+ * value must be a multiple of 8 that is not greater than 128 or less than the value of
+ * Tag::MIN_MAC_LENGTH in the key authorizations. For MAC lengths greater than 128 or
+ * non-multiples of 8, begin() must return ErrorCode::UNSUPPORTED_MAC_LENGTH. For values less
+ * than the key's minimum length, begin() must return ErrorCode::INVALID_MAC_LENGTH.
+ *
+ * If the block mode is BlockMode::GCM or BlockMode::CTR, the specified padding mode must be
+ * PaddingMode::NONE. For BlockMode::ECB or BlockMode::CBC, the mode may be PaddingMode::NONE
+ * or PaddingMode::PKCS7. If the padding mode doesn't meet these conditions, begin() must
+ * return ErrorCode::INCOMPATIBLE_PADDING_MODE.
+ *
+ * If the block mode is BlockMode::CBC, BlockMode::CTR, or BlockMode::GCM, an initialization
+ * vector or nonce is required. In most cases, callers shouldn't provide an IV or nonce and the
+ * IKeyMintDevice implementation must generate a random IV or nonce and return it via
+ * Tag::NONCE in outParams. CBC and CTR IVs are 16 bytes. GCM nonces are 12 bytes. If the key
+ * authorizations contain Tag::CALLER_NONCE, then the caller may provide an IV/nonce with
+ * Tag::NONCE in inParams. If a nonce is provided when Tag::CALLER_NONCE is not authorized,
+ * begin() must return ErrorCode::CALLER_NONCE_PROHIBITED. If a nonce is not provided when
+ * Tag::CALLER_NONCE is authorized, IKeyMintDevice msut generate a random IV/nonce.
+ *
+ * -- HMAC keys --
+ *
+ * HMAC key operations must specify Tag::MAC_LENGTH in inParams. The specified value must be a
+ * multiple of 8 that is not greater than the digest length or less than the value of
+ * Tag::MIN_MAC_LENGTH in the key authorizations. For MAC lengths greater than the digest
+ * length or non-multiples of 8, begin() must return ErrorCode::UNSUPPORTED_MAC_LENGTH. For
+ * values less than the key's minimum length, begin() must return ErrorCode::INVALID_MAC_LENGTH.
+ *
+ * @param inPurpose The purpose of the operation, one of KeyPurpose::ENCRYPT,
+ * KeyPurpose::DECRYPT, KeyPurpose::SIGN or KeyPurpose::VERIFY. Note that for AEAD
+ * modes, encryption and decryption imply signing and verification, respectively, but
+ * must be specified as KeyPurpose::ENCRYPT and KeyPurpose::DECRYPT.
+ *
+ * @param inKeyBlob The opaque key descriptor returned by generateKey() or importKey(). The key
+ * must have a purpose compatible with purpose and all of its usage requirements must be
+ * satisfied, or begin() must return an appropriate error code (see above).
+ *
+ * @param inParams Additional parameters for the operation. If Tag::APPLICATION_ID or
+ * Tag::APPLICATION_DATA were provided during generation, they must be provided here, or
+ * the operation must fail with ErrorCode::INVALID_KEY_BLOB. For operations that require
+ * a nonce or IV, on keys that were generated with Tag::CALLER_NONCE, inParams may
+ * contain a tag Tag::NONCE. If Tag::NONCE is provided for a key without
+ * Tag:CALLER_NONCE, ErrorCode::CALLER_NONCE_PROHIBITED must be returned.
+ *
+ * @param inAuthToken Authentication token. Callers that provide no token must set all numeric
+ * fields to zero and the MAC must be an empty vector. TODO: make this field nullable.
+ * b/173483024.
+ *
+ * @return BeginResult as output, which contains the challenge, KeyParameters which haves
+ * additional data from the operation initialization, notably to return the IV or nonce
+ * from operations that generate an IV or nonce, and IKeyMintOperation object pointer
+ * which is used to perform update(), finish() or abort() operations.
+ */
+ BeginResult begin(in KeyPurpose inPurpose,
+ in byte[] inKeyBlob,
+ in KeyParameter[] inParams,
+ in HardwareAuthToken inAuthToken);
+}
diff --git a/keymint/aidl/android/hardware/keymint/IKeyMintOperation.aidl b/keymint/aidl/android/hardware/keymint/IKeyMintOperation.aidl
new file mode 100644
index 0000000..1b79296
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/IKeyMintOperation.aidl
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.ByteArray;
+import android.hardware.keymint.HardwareAuthToken;
+import android.hardware.keymint.KeyParameter;
+import android.hardware.keymint.KeyParameterArray;
+import android.hardware.keymint.VerificationToken;
+
+@VintfStability
+interface IKeyMintOperation {
+ /**
+ * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
+ * with begin().
+ *
+ * If operation is in an invalid state (was aborted or had an error) update() must return
+ * ErrorCode::INVALID_OPERATION_HANDLE.
+ *
+ * To provide more flexibility for buffer handling, implementations of this method have the
+ * option of consuming less data than was provided. The caller is responsible for looping to
+ * feed the rest of the data in subsequent calls. The amount of input consumed must be returned
+ * in the inputConsumed parameter. Implementations must always consume at least one byte,
+ * unless the operation cannot accept any more; if more than zero bytes are provided and zero
+ * bytes are consumed, callers must consider this an error and abort the operation.
+ * TODO(seleneh) update the code to always consume alll the input data. b/168665179.
+ *
+ * Implementations may also choose how much data to return, as a result of the update. This is
+ * only relevant for encryption and decryption operations, because signing and verification
+ * return no data until finish. It is recommended to return data as early as possible, rather
+ * than buffer it.
+ *
+ * If this method returns an error code other than ErrorCode::OK, the operation is aborted and
+ * the operation handle must be invalidated. Any future use of the handle, with this method,
+ * finish, or abort, must return ErrorCode::INVALID_OPERATION_HANDLE.
+ *
+ * == Authorization Enforcement ==
+ *
+ * Key authorization enforcement is performed primarily in begin(). The one exception is the
+ * case where the key has:
+ *
+ * o One or more Tag::USER_SECURE_IDs, and
+ *
+ * o Does not have a Tag::AUTH_TIMEOUT
+ *
+ * In this case, the key requires an authorization per operation, and the update method must
+ * receive a non-empty and valid HardwareAuthToken. For the auth token to be valid, all of the
+ * following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The challenge field in the auth token must contain the operationHandle
+ *
+ * If any of these conditions are not met, update() must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * The caller must provide the auth token on every call to update() and finish().
+ *
+ * -- RSA keys --
+ *
+ * For signing and verification operations with Digest::NONE, this method must accept the entire
+ * block to be signed or verified in a single update. It may not consume only a portion of the
+ * block in these cases. However, the caller may choose to provide the data in multiple
+ * updates, and update() must accept the data this way as well. If the caller provides more
+ * data to sign than can be used (length of data exceeds RSA key size), update() must return
+ * ErrorCode::INVALID_INPUT_LENGTH.
+ *
+ * -- ECDSA keys --
+ *
+ * For signing and verification operations with Digest::NONE, this method must accept the entire
+ * block to be signed or verified in a single update. This method may not consume only a
+ * portion of the block. However, the caller may choose to provide the data in multiple updates
+ * and update() must accept the data this way as well. If the caller provides more data to sign
+ * than can be used, the data is silently truncated. (This differs from the handling of excess
+ * data provided in similar RSA operations. The reason for this is compatibility with legacy
+ * clients.)
+ *
+ * -- AES keys --
+ *
+ * AES GCM mode supports "associated authentication data," provided via the Tag::ASSOCIATED_DATA
+ * tag in the inParams argument. The associated data may be provided in repeated calls
+ * (important if the data is too large to send in a single block) but must always precede data
+ * to be encrypted or decrypted. An update call may receive both associated data and data to
+ * encrypt/decrypt, but subsequent updates must not include associated data. If the caller
+ * provides associated data to an update call after a call that includes data to
+ * encrypt/decrypt, update() must return ErrorCode::INVALID_TAG.
+ *
+ * For GCM encryption, the AEAD tag must be appended to the ciphertext by finish(). During
+ * decryption, the last Tag::MAC_LENGTH bytes of the data provided to the last update call must
+ * be the AEAD tag. Since a given invocation of update cannot know if it's the last invocation,
+ * it must process all but the tag length and buffer the possible tag data for processing during
+ * finish().
+ *
+ * TODO: update() needs to be refactored b/168665179.
+ *
+ * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+ * specify Tag::ADDITIONAL_DATA. Note that additional data may be provided in multiple
+ * calls to update(), but only until input data has been provided.
+ *
+ * @param input Data to be processed. Note that update() may or may not consume all of the data
+ * provided. See return value.
+ *
+ * @param verificationToken Verification token, used to prove that another IKeymasterDevice HAL
+ * has verified some parameters, and to deliver the other HAL's current timestamp, if
+ * needed. If not provided, all fields must be initialized to zero and vectors must be
+ * empty.
+ *
+ * @return error Returns ErrorCode encountered in keymint as service specific errors. See the
+ * ErrorCode enum in ErrorCode.aidl.
+ *
+ * @return int Amount of data that was consumed by update(). If this is less than the
+ * amount provided, the caller may provide the remainder in a subsequent call to
+ * update() or finish(). Every call to update must consume at least one byte, unless
+ * the input is empty, and implementations should consume as much data as reasonably
+ * possible for each call.
+ *
+ * @return outParams returns the updated key parameters from the blob, if needed.
+ * operation.
+ *
+ * @return out variable output The output data, if any.
+ */
+ int update(in @nullable KeyParameterArray inParams,
+ in @nullable byte[] input,
+ in @nullable HardwareAuthToken inAuthToken,
+ in @nullable VerificationToken inVerificationToken,
+ out @nullable KeyParameterArray outParams,
+ out @nullable ByteArray output);
+
+ /**
+ * Finalizes a cryptographic operation begun with begin() and invalidates operation.
+ *
+ * This method is the last one called in an operation, so all processed data must be returned.
+ *
+ * Whether it completes successfully or returns an error, this method finalizes the operation.
+ * Any future use of the operation, with finish(), update(), or abort(), must return
+ * ErrorCode::INVALID_OPERATION_HANDLE.
+ *
+ * Signing operations return the signature as the output. Verification operations accept the
+ * signature in the signature parameter, and return no output.
+ *
+ * == Authorization enforcement ==
+ *
+ * Key authorization enforcement is performed primarily in begin(). The exceptions are
+ * authorization per operation keys and confirmation-required keys.
+ *
+ * Authorization per operation keys are the case where the key has one or more
+ * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT. In this case, the key requires
+ * an authorization per operation, and the finish method must receive a non-empty and valid
+ * authToken. For the auth token to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The challenge field in the auth token must contain the operation challenge.
+ *
+ * If any of these conditions are not met, update() must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * The caller must provide the auth token on every call to update() and finish().
+ *
+ * Confirmation-required keys are keys that were generated with
+ * Tag::TRUSTED_CONFIRMATION_REQUIRED. For these keys, when doing a signing operation the
+ * caller must pass a KeyParameter Tag::CONFIRMATION_TOKEN to finish(). Implementations must
+ * check the confirmation token by computing the 32-byte HMAC-SHA256 over all of the
+ * to-be-signed data, prefixed with the 18-byte UTF-8 encoded string "confirmation token". If
+ * the computed value does not match the Tag::CONFIRMATION_TOKEN parameter, finish() must not
+ * produce a signature and must return ErrorCode::NO_USER_CONFIRMATION.
+ *
+ * -- RSA keys --
+ *
+ * Some additional requirements, depending on the padding mode:
+ *
+ * o PaddingMode::NONE. For unpadded signing and encryption operations, if the provided data is
+ * shorter than the key, the data must be zero-padded on the left before
+ * signing/encryption. If the data is the same length as the key, but numerically larger,
+ * finish() must return ErrorCode::INVALID_ARGUMENT. For verification and decryption
+ * operations, the data must be exactly as long as the key. Otherwise, return
+ * ErrorCode::INVALID_INPUT_LENGTH.
+ *
+ * o PaddingMode::RSA_PSS. For PSS-padded signature operations, the PSS salt length must match
+ * the size of the PSS digest selected. The digest specified with Tag::DIGEST in inputParams
+ * on begin() must be used as the PSS digest algorithm, MGF1 must be used as the mask
+ * generation function and SHA1 must be used as the MGF1 digest algorithm.
+ *
+ * o PaddingMode::RSA_OAEP. The digest specified with Tag::DIGEST in inputParams on begin is
+ * used as the OAEP digest algorithm, MGF1 must be used as the mask generation function and
+ * and SHA1 must be used as the MGF1 digest algorithm.
+ *
+ * -- ECDSA keys --
+ *
+ * If the data provided for unpadded signing or verification is too long, truncate it.
+ *
+ * -- AES keys --
+ *
+ * Some additional conditions, depending on block mode:
+ *
+ * o BlockMode::ECB or BlockMode::CBC. If padding is PaddingMode::NONE and the data length is
+ * not a multiple of the AES block size, finish() must return
+ * ErrorCode::INVALID_INPUT_LENGTH. If padding is PaddingMode::PKCS7, pad the data per the
+ * PKCS#7 specification, including adding an additional padding block if the data is a multiple
+ * of the block length.
+ *
+ * o BlockMode::GCM. During encryption, after processing all plaintext, compute the tag
+ * (Tag::MAC_LENGTH bytes) and append it to the returned ciphertext. During decryption,
+ * process the last Tag::MAC_LENGTH bytes as the tag. If tag verification fails, finish()
+ * must return ErrorCode::VERIFICATION_FAILED.
+ *
+ * TODO: update() will need to be refactored into 2 function. b/168665179.
+ *
+ * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+ * specify Tag::ADDITIONAL_DATA, but only if no input data was provided to update().
+ *
+ * @param input Data to be processed, per the parameters established in the call to begin().
+ * finish() must consume all provided data or return ErrorCode::INVALID_INPUT_LENGTH.
+ *
+ * @param signature The signature to be verified if the purpose specified in the begin() call
+ * was KeyPurpose::VERIFY.
+ *
+ * @param authToken Authentication token. Can be nullable if not provided.
+ *
+ * @param verificationToken Verification token, used to prove that another IKeyMintDevice HAL
+ * has verified some parameters, and to deliver the other HAL's current timestamp, if
+ * needed. Can be nullable if not needed.
+ *
+ * @return outParams Any output parameters generated by finish().
+ *
+ * @return The output data, if any.
+ */
+ byte[] finish(in @nullable KeyParameterArray inParams, in @nullable byte[] input,
+ in @nullable byte[] inSignature,
+ in @nullable HardwareAuthToken authToken,
+ in @nullable VerificationToken inVerificationToken,
+ out @nullable KeyParameterArray outParams);
+
+ /**
+ * Aborts a cryptographic operation begun with begin(), freeing all internal resources. If an
+ * operation was finalized, calling update, finish, or abort yields
+ * ErrorCode::INVALID_OPERATION_HANDLE. An operation is finalized if finish or abort was
+ * called on it, or if update returned an ErrorCode.
+ *
+ * @param operationHandle The operation handle returned by begin(). This handle must be
+ * invalid when abort() returns.
+ *
+ * @return error See the ErrorCode enum in ErrorCode.aidl.
+ */
+ void abort();
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyCharacteristics.aidl b/keymint/aidl/android/hardware/keymint/KeyCharacteristics.aidl
new file mode 100644
index 0000000..ac7c2b4
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyCharacteristics.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.KeyParameter;
+
+/**
+ * KeyCharacteristics defines the attributes of a key, including cryptographic parameters, and usage
+ * restrictions. It consits of two vectors of KeyParameters, one for "softwareEnforced" attributes
+ * and one for "hardwareEnforced" attributes.
+ *
+ * KeyCharacteristics objects are returned by generateKey, importKey, importWrappedKey and
+ * getKeyCharacteristics. The IKeyMintDevice secure environment is responsible for allocating the
+ * parameters, all of which are Tags with associated values, to the correct vector. The
+ * hardwareEnforced vector must contain only those attributes which are enforced by secure hardware.
+ * All others should be in the softwareEnforced vector. See the definitions of individual Tag enums
+ * for specification of which must be hardware-enforced, which may be software-enforced and which
+ * must never appear in KeyCharacteristics.
+ */
+@VintfStability
+parcelable KeyCharacteristics {
+ /* TODO(seleneh) get rid of the software enforced in keymint. replace hardware enforced with
+ * tee enforced and strongbox enforced.
+ */
+ KeyParameter[] softwareEnforced;
+ KeyParameter[] hardwareEnforced;
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyDerivationFunction.aidl b/keymint/aidl/android/hardware/keymint/KeyDerivationFunction.aidl
new file mode 100644
index 0000000..1eba446
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyDerivationFunction.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * Key derivation functions, mostly used in ECIES.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyDerivationFunction {
+ /** Do not apply a key derivation function; use the raw agreed key */
+ NONE = 0,
+ /** HKDF defined in RFC 5869 with SHA256 */
+ RFC5869_SHA256 = 1,
+ /** KDF1 defined in ISO 18033-2 with SHA1 */
+ ISO18033_2_KDF1_SHA1 = 2,
+ /** KDF1 defined in ISO 18033-2 with SHA256 */
+ ISO18033_2_KDF1_SHA256 = 3,
+ /** KDF2 defined in ISO 18033-2 with SHA1 */
+ ISO18033_2_KDF2_SHA1 = 4,
+ /** KDF2 defined in ISO 18033-2 with SHA256 */
+ ISO18033_2_KDF2_SHA256 = 5,
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyFormat.aidl b/keymint/aidl/android/hardware/keymint/KeyFormat.aidl
new file mode 100644
index 0000000..13044dc
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyFormat.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * Formats for key import and export.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyFormat {
+ /** X.509 certificate format, for public key export. */
+ X509 = 0,
+ /** PCKS#8 format, asymmetric key pair import. */
+ PKCS8 = 1,
+ /** Raw bytes, for symmetric key import. */
+ RAW = 3,
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyMintHardwareInfo.aidl b/keymint/aidl/android/hardware/keymint/KeyMintHardwareInfo.aidl
new file mode 100644
index 0000000..5815b10
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyMintHardwareInfo.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.SecurityLevel;
+
+
+/**
+ * KeyMintHardwareInfo is the hardware information returned by calling KeyMint getHardwareInfo()
+ */
+
+@VintfStability
+parcelable KeyMintHardwareInfo {
+ /**
+ * Implementation version of the keymint hardware. The version number is implementation
+ * defined, and not necessarily globally meaningful. The version is used to distinguish
+ * between different versions of a given implementation.
+ * TODO(seleneh) add the version related info to the code.
+ */
+ int versionNumber;
+
+ /* securityLevel is the security level of the IKeyMintDevice implementation accessed
+ * through this aidl package. */
+ SecurityLevel securityLevel;
+
+ /* keyMintName is the name of the IKeyMintDevice implementation. */
+ @utf8InCpp String keyMintName;
+
+ /* keyMintAuthorName is the name of the author of the IKeyMintDevice implementation
+ * (organization name, not individual). This name is implementation defined,
+ * so it can be used to distinguish between different implementations from the
+ * same author.
+ */
+ @utf8InCpp String keyMintAuthorName;
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyOrigin.aidl b/keymint/aidl/android/hardware/keymint/KeyOrigin.aidl
new file mode 100644
index 0000000..70320d3
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyOrigin.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * The origin of a key (or pair), i.e. where it was generated. Note that ORIGIN can be found in
+ * either the hardware-enforced or software-enforced list for a key, indicating whether the key is
+ * hardware or software-based. Specifically, a key with GENERATED in the hardware-enforced list
+ * must be guaranteed never to have existed outide the secure hardware.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyOrigin {
+ /** Generated in keyMint. Should not exist outside the TEE. */
+ GENERATED = 0,
+
+ /** Derived inside keyMint. Likely exists off-device. */
+ DERIVED = 1,
+
+ /** Imported into keyMint. Existed as cleartext in Android. */
+ IMPORTED = 2,
+
+ /** Previously used for another purpose that is now obsolete. */
+ RESERVED = 3,
+
+ /**
+ * Securely imported into KeyMint. Was created elsewhere, and passed securely through Android
+ * to secure hardware.
+ */
+ SECURELY_IMPORTED = 4,
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyParameter.aidl b/keymint/aidl/android/hardware/keymint/KeyParameter.aidl
new file mode 100644
index 0000000..d58e4aa
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyParameter.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+import android.hardware.keymint.Algorithm;
+import android.hardware.keymint.BlockMode;
+import android.hardware.keymint.Digest;
+import android.hardware.keymint.EcCurve;
+import android.hardware.keymint.HardwareAuthenticatorType;
+import android.hardware.keymint.KeyDerivationFunction;
+import android.hardware.keymint.KeyOrigin;
+import android.hardware.keymint.KeyPurpose;
+import android.hardware.keymint.PaddingMode;
+import android.hardware.keymint.SecurityLevel;
+import android.hardware.keymint.Tag;
+
+
+/**
+ * Identifies the key authorization parameters to be used with keyMint. This is usually
+ * provided as an array of KeyParameters to IKeyMintDevice or Operation.
+ *
+ * TODO(seleneh): Union was not supported in aidl when this cl is first drafted. So we just had
+ * the Tags, and bool, int, long, int[], and we will cast to the appropate types base on the
+ * Tag value. We need to update this defination to distingish Algorithm, BlockMode,
+ * PaddingMode, KeyOrigin...etc later, as union support is recently added to aidl.
+ * b/173253030
+ */
+@VintfStability
+parcelable KeyParameter {
+ /**
+ * Identify what type of key parameter this parcelable actually holds, and based on the type
+ * of tag is int, long, bool, or byte[], one of the fields below will be referenced.
+ */
+ Tag tag;
+
+ boolean boolValue;
+ int integer;
+ long longInteger;
+ // TODO: change this to nullable.
+ byte[] blob;
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyParameterArray.aidl b/keymint/aidl/android/hardware/keymint/KeyParameterArray.aidl
new file mode 100644
index 0000000..cc9e37a
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyParameterArray.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.KeyParameter;
+
+/**
+ * Identifies the key authorization parameters to be used with keyMint. This is usually
+ * provided as an array of KeyParameters to IKeyMintDevice or Operation.
+ */
+@VintfStability
+parcelable KeyParameterArray {
+ /**
+ * Identify list of key parameters corresponding to a particular key blob.
+ */
+ KeyParameter[] params;
+}
diff --git a/keymint/aidl/android/hardware/keymint/KeyPurpose.aidl b/keymint/aidl/android/hardware/keymint/KeyPurpose.aidl
new file mode 100644
index 0000000..bc029fd
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/KeyPurpose.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+
+/**
+ * Possible purposes of a key (or pair).
+ */
+@VintfStability
+@Backing(type = "int")
+enum KeyPurpose {
+ /* Usable with RSA, EC and AES keys. */
+ ENCRYPT = 0,
+
+ /* Usable with RSA, EC and AES keys. */
+ DECRYPT = 1,
+
+ /* Usable with RSA, EC and HMAC keys. */
+ SIGN = 2,
+
+ /* Usable with RSA, EC and HMAC keys. */
+ VERIFY = 3,
+
+ /* 4 is reserved */
+ /* Usable with wrapping keys. */
+ WRAP_KEY = 5,
+
+ /* TODO(seleneh) add AGREE_KEY and ATTEST_KEY and their corresponding codes and tests later*/
+}
diff --git a/keymint/aidl/android/hardware/keymint/PaddingMode.aidl b/keymint/aidl/android/hardware/keymint/PaddingMode.aidl
new file mode 100644
index 0000000..337ed91
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/PaddingMode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * TODO(seleneh) update the description.
+ *
+ * Padding modes that may be applied to plaintext for encryption operations. This list includes
+ * padding modes for both symmetric and asymmetric algorithms. Note that implementations should not
+ * provide all possible combinations of algorithm and padding, only the
+ * cryptographically-appropriate pairs.
+ */
+@VintfStability
+@Backing(type="int")
+enum PaddingMode {
+ NONE = 1, /* deprecated */
+ RSA_OAEP = 2,
+ RSA_PSS = 3,
+ RSA_PKCS1_1_5_ENCRYPT = 4,
+ RSA_PKCS1_1_5_SIGN = 5,
+ PKCS7 = 64,
+}
diff --git a/keymint/aidl/android/hardware/keymint/SecurityLevel.aidl b/keymint/aidl/android/hardware/keymint/SecurityLevel.aidl
new file mode 100644
index 0000000..d8de024
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/SecurityLevel.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * Device security levels.
+ */
+@VintfStability
+@Backing(type="int")
+enum SecurityLevel {
+ SOFTWARE = 0,
+ TRUSTED_ENVIRONMENT = 1,
+ /**
+ * STRONGBOX specifies that the secure hardware satisfies the requirements specified in CDD
+ * 9.11.2.
+ */
+ STRONGBOX = 2,
+}
diff --git a/keymint/aidl/android/hardware/keymint/Tag.aidl b/keymint/aidl/android/hardware/keymint/Tag.aidl
new file mode 100644
index 0000000..46da096
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/Tag.aidl
@@ -0,0 +1,892 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.TagType;
+
+// TODO(seleneh) : note aidl currently does not support double nested enum definitions such as
+// ROOT_OF_TRUST = TagType:BYTES | 704. So we are forced to write definations as
+// ROOT_OF_TRUST = (9 << 28) for now. Will need to flip this back later when aidl support is added.
+
+/**
+ * Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
+ * data are stored in KeyParameter.
+ */
+@VintfStability
+@Backing(type = "int")
+enum Tag {
+ /**
+ * Tag::INVALID should never be set. It means you hit an error.
+ */
+ INVALID = (0 << 28) | 0,
+
+ /**
+ * Tag::PURPOSE specifies the set of purposes for which the key may be used. Possible values
+ * are defined in the KeyPurpose enumeration.
+ *
+ * This tag is repeatable; keys may be generated with multiple values, although an operation has
+ * a single purpose. When begin() is called to start an operation, the purpose of the operation
+ * is specified. If the purpose specified for the operation is not authorized by the key (the
+ * key didn't have a corresponding Tag::PURPOSE provided during generation/import), the
+ * operation must fail with ErrorCode::INCOMPATIBLE_PURPOSE.
+ *
+ * Must be hardware-enforced.
+ */
+ PURPOSE = (2 << 28) | 1, /* TagType:ENUM_REP */
+
+ /**
+ * Tag::ALGORITHM specifies the cryptographic algorithm with which the key is used. This tag
+ * must be provided to generateKey and importKey, and must be specified in the wrapped key
+ * provided to importWrappedKey.
+ *
+ * Must be hardware-enforced.
+ */
+ ALGORITHM = (1 << 28) | 2, /* TagType:ENUM */
+
+ /**
+ * Tag::KEY_SIZE pecifies the size, in bits, of the key, measuring in the normal way for the
+ * key's algorithm. For example, for RSA keys, Tag::KEY_SIZE specifies the size of the public
+ * modulus. For AES keys it specifies the length of the secret key material. For 3DES keys it
+ * specifies the length of the key material, not counting parity bits (though parity bits must
+ * be provided for import, etc.). Since only three-key 3DES keys are supported, 3DES
+ * Tag::KEY_SIZE must be 168.
+ *
+ * Must be hardware-enforced.
+ */
+ KEY_SIZE = (3 << 28) | 3, /* TagType:UINT */
+
+ /**
+ * Tag::BLOCK_MODE specifies the block cipher mode(s) with which the key may be used. This tag
+ * is only relevant to AES and 3DES keys. Possible values are defined by the BlockMode enum.
+ *
+ * This tag is repeatable for key generation/import. For AES and 3DES operations the caller
+ * must specify a Tag::BLOCK_MODE in the additionalParams argument of begin(). If the mode is
+ * missing or the specified mode is not in the modes specified for the key during
+ * generation/import, the operation must fail with ErrorCode::INCOMPATIBLE_BLOCK_MODE.
+ *
+ * Must be hardware-enforced.
+ */
+ BLOCK_MODE = (2 << 28) | 4,
+ /* BlockMode. */ /* TagType:ENUM_REP */
+
+ /**
+ * Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
+ * and verification operations. This tag is relevant to RSA, ECDSA and HMAC keys. Possible
+ * values are defined by the Digest enum.
+ *
+ * This tag is repeatable for key generation/import. For signing and verification operations,
+ * the caller must specify a digest in the additionalParams argument of begin(). If the digest
+ * is missing or the specified digest is not in the digests associated with the key, the
+ * operation must fail with ErrorCode::INCOMPATIBLE_DIGEST.
+ *
+ * Must be hardware-enforced.
+ */
+ DIGEST = (2 << 28) | 5, /* TagType:ENUM_REP */
+
+ /**
+ * Tag::PADDING specifies the padding modes that may be used with the key. This tag is relevant
+ * to RSA, AES and 3DES keys. Possible values are defined by the PaddingMode enum.
+ *
+ * PaddingMode::RSA_OAEP and PaddingMode::RSA_PKCS1_1_5_ENCRYPT are used only for RSA
+ * encryption/decryption keys and specify RSA OAEP padding and RSA PKCS#1 v1.5 randomized
+ * padding, respectively. PaddingMode::RSA_PSS and PaddingMode::RSA_PKCS1_1_5_SIGN are used
+ * only for RSA signing/verification keys and specify RSA PSS padding and RSA PKCS#1 v1.5
+ * deterministic padding, respectively.
+ *
+ * PaddingMode::NONE may be used with either RSA, AES or 3DES keys. For AES or 3DES keys, if
+ * PaddingMode::NONE is used with block mode ECB or CBC and the data to be encrypted or
+ * decrypted is not a multiple of the AES block size in length, the call to finish() must fail
+ * with ErrorCode::INVALID_INPUT_LENGTH.
+ *
+ * PaddingMode::PKCS7 may only be used with AES and 3DES keys, and only with ECB and CBC modes.
+ *
+ * In any case, if the caller specifies a padding mode that is not usable with the key's
+ * algorithm, the generation or import method must return ErrorCode::INCOMPATIBLE_PADDING_MODE.
+ *
+ * This tag is repeatable. A padding mode must be specified in the call to begin(). If the
+ * specified mode is not authorized for the key, the operation must fail with
+ * ErrorCode::INCOMPATIBLE_BLOCK_MODE.
+ *
+ * Must be hardware-enforced.
+ */
+ PADDING = (2 << 28) | 6, /* TagType:ENUM_REP */
+
+ /**
+ * Tag::CALLER_NONCE specifies that the caller can provide a nonce for nonce-requiring
+ * operations. This tag is boolean, so the possible values are true (if the tag is present) and
+ * false (if the tag is not present).
+ *
+ * This tag is used only for AES and 3DES keys, and is only relevant for CBC, CTR and GCM block
+ * modes. If the tag is not present in a key's authorization list, implementations must reject
+ * any operation that provides Tag::NONCE to begin() with ErrorCode::CALLER_NONCE_PROHIBITED.
+ *
+ * Must be hardware-enforced.
+ */
+ CALLER_NONCE = (7 << 28) | 7, /* TagType:BOOL */
+
+ /**
+ * Tag::MIN_MAC_LENGTH specifies the minimum length of MAC that can be requested or verified
+ * with this key for HMAC keys and AES keys that support GCM mode.
+ *
+ * This value is the minimum MAC length, in bits. It must be a multiple of 8 bits. For HMAC
+ * keys, the value must be least 64 and no more than 512. For GCM keys, the value must be at
+ * least 96 and no more than 128. If the provided value violates these requirements,
+ * generateKey() or importKey() must return ErrorCode::UNSUPPORTED_KEY_SIZE.
+ *
+ * Must be hardware-enforced.
+ */
+ MIN_MAC_LENGTH = (3 << 28) | 8, /* TagType:UINT */
+
+ // Tag 9 reserved
+
+ /**
+ * Tag::EC_CURVE specifies the elliptic curve. EC key generation requests may have
+ * Tag:EC_CURVE, Tag::KEY_SIZE, or both. If both are provided and the size and curve do not
+ * match, IKeyMintDevice must return ErrorCode::INVALID_ARGUMENT.
+ *
+ * Must be hardware-enforced.
+ */
+ EC_CURVE = (1 << 28) | 10, /* TagType:ENUM */
+
+ /**
+ * Tag::RSA_PUBLIC_EXPONENT specifies the value of the public exponent for an RSA key pair.
+ * This tag is relevant only to RSA keys, and is required for all RSA keys.
+ *
+ * The value is a 64-bit unsigned integer that satisfies the requirements of an RSA public
+ * exponent. This value must be a prime number. IKeyMintDevice implementations must support
+ * the value 2^16+1 and may support other reasonable values. If no exponent is specified or if
+ * the specified exponent is not supported, key generation must fail with
+ * ErrorCode::INVALID_ARGUMENT.
+ *
+ * Must be hardware-enforced.
+ */
+ RSA_PUBLIC_EXPONENT = (5 << 28) | 200, /* TagType:ULONG */
+
+ // Tag 201 reserved
+
+ /**
+ * Tag::INCLUDE_UNIQUE_ID is specified during key generation to indicate that an attestation
+ * certificate for the generated key should contain an application-scoped and time-bounded
+ * device-unique ID. See Tag::UNIQUE_ID.
+ *
+ * Must be hardware-enforced.
+ */
+ INCLUDE_UNIQUE_ID = (7 << 28) | 202, /* TagType:BOOL */
+
+ /**
+ * TODO(seleneh) this tag needs to be deleted from all codes.
+ *
+ * Tag::BLOB_USAGE_REQUIREMENTS specifies the necessary system environment conditions for the
+ * generated key to be used. Possible values are defined by the KeyBlobUsageRequirements enum.
+ *
+ * This tag is specified by the caller during key generation or import to require that the key
+ * is usable in the specified condition. If the caller specifies Tag::BLOB_USAGE_REQUIREMENTS
+ * with value KeyBlobUsageRequirements::STANDALONE the IKeyMintDevice must return a key blob
+ * that can be used without file system support. This is critical for devices with encrypted
+ * disks, where the file system may not be available until after a KeyMint key is used to
+ * decrypt the disk.
+ *
+ * Must be hardware-enforced.
+ */
+ BLOB_USAGE_REQUIREMENTS = (1 << 28) | 301, /* TagType:ENUM */
+
+ /**
+ * Tag::BOOTLOADER_ONLY specifies only the bootloader can use the key.
+ *
+ * Any attempt to use a key with Tag::BOOTLOADER_ONLY from the Android system must fail with
+ * ErrorCode::INVALID_KEY_BLOB.
+ *
+ * Must be hardware-enforced.
+ */
+ BOOTLOADER_ONLY = (7 << 28) | 302, /* TagType:BOOL */
+
+ /**
+ * Tag::ROLLBACK_RESISTANCE specifies that the key has rollback resistance, meaning that when
+ * deleted with deleteKey() or deleteAllKeys(), the key is guaranteed to be permanently deleted
+ * and unusable. It's possible that keys without this tag could be deleted and then restored
+ * from backup.
+ *
+ * This tag is specified by the caller during key generation or import to require. If the
+ * IKeyMintDevice cannot guarantee rollback resistance for the specified key, it must return
+ * ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE. IKeyMintDevice implementations are not
+ * required to support rollback resistance.
+ *
+ * Must be hardwared-enforced.
+ */
+ ROLLBACK_RESISTANCE = (7 << 28) | 303, /* TagType:BOOL */
+
+ // Reserved for future use.
+ HARDWARE_TYPE = (1 << 28) | 304, /* TagType:ENUM */
+
+ /**
+ * Keys tagged with EARLY_BOOT_ONLY may only be used, or created, during early boot, until
+ * IKeyMintDevice::earlyBootEnded() is called.
+ */
+ EARLY_BOOT_ONLY = (7 << 28) | 305, /* TagType:BOOL */
+
+ /**
+ * Tag::ACTIVE_DATETIME specifies the date and time at which the key becomes active, in
+ * milliseconds since Jan 1, 1970. If a key with this tag is used prior to the specified date
+ * and time, IKeyMintDevice::begin() must return ErrorCode::KEY_NOT_YET_VALID;
+ *
+ * Need not be hardware-enforced.
+ */
+ ACTIVE_DATETIME = (6 << 28) | 400,
+ /* Start of validity. */ /* TagType:DATE */
+
+ /**
+ * Tag::ORIGINATION_EXPIRE_DATETIME specifies the date and time at which the key expires for
+ * signing and encryption purposes. After this time, any attempt to use a key with
+ * KeyPurpose::SIGN or KeyPurpose::ENCRYPT provided to begin() must fail with
+ * ErrorCode::KEY_EXPIRED.
+ *
+ * The value is a 64-bit integer representing milliseconds since January 1, 1970.
+ *
+ * Need not be hardware-enforced.
+ */
+ ORIGINATION_EXPIRE_DATETIME = (6 << 28) | 401, /* TagType:DATE */
+
+ /**
+ * Tag::USAGE_EXPIRE_DATETIME specifies the date and time at which the key expires for
+ * verification and decryption purposes. After this time, any attempt to use a key with
+ * KeyPurpose::VERIFY or KeyPurpose::DECRYPT provided to begin() must fail with
+ * ErrorCode::KEY_EXPIRED.
+ *
+ * The value is a 64-bit integer representing milliseconds since January 1, 1970.
+ *
+ * Need not be hardware-enforced.
+ */
+ USAGE_EXPIRE_DATETIME = (6 << 28) | 402, /* TagType:DATE */
+
+ /**
+ * TODO(seleneh) this tag need to be deleted.
+ *
+ * TODO(seleneh) this tag need to be deleted.
+ *
+ * Tag::MIN_SECONDS_BETWEEN_OPS specifies the minimum amount of time that elapses between
+ * allowed operations using a key. This can be used to rate-limit uses of keys in contexts
+ * where unlimited use may enable brute force attacks.
+ *
+ * The value is a 32-bit integer representing seconds between allowed operations.
+ *
+ * When a key with this tag is used in an operation, the IKeyMintDevice must start a timer
+ * during the finish() or abort() call. Any call to begin() that is received before the timer
+ * indicates that the interval specified by Tag::MIN_SECONDS_BETWEEN_OPS has elapsed must fail
+ * with ErrorCode::KEY_RATE_LIMIT_EXCEEDED. This implies that the IKeyMintDevice must keep a
+ * table of use counters for keys with this tag. Because memory is often limited, this table
+ * may have a fixed maximum size and KeyMint may fail operations that attempt to use keys with
+ * this tag when the table is full. The table must acommodate at least 8 in-use keys and
+ * aggressively reuse table slots when key minimum-usage intervals expire. If an operation
+ * fails because the table is full, KeyMint returns ErrorCode::TOO_MANY_OPERATIONS.
+ *
+ * Must be hardware-enforced.
+ */
+ MIN_SECONDS_BETWEEN_OPS = (3 << 28) | 403, /* TagType:UINT */
+
+ /**
+ * Tag::MAX_USES_PER_BOOT specifies the maximum number of times that a key may be used between
+ * system reboots. This is another mechanism to rate-limit key use.
+ *
+ * The value is a 32-bit integer representing uses per boot.
+ *
+ * When a key with this tag is used in an operation, a key-associated counter must be
+ * incremented during the begin() call. After the key counter has exceeded this value, all
+ * subsequent attempts to use the key must fail with ErrorCode::MAX_OPS_EXCEEDED, until the
+ * device is restarted. This implies that the IKeyMintDevice must keep a table of use
+ * counters for keys with this tag. Because KeyMint memory is often limited, this table can
+ * have a fixed maximum size and KeyMint can fail operations that attempt to use keys with
+ * this tag when the table is full. The table needs to acommodate at least 8 keys. If an
+ * operation fails because the table is full, IKeyMintDevice must
+ * ErrorCode::TOO_MANY_OPERATIONS.
+ *
+ * Must be hardware-enforced.
+ */
+ MAX_USES_PER_BOOT = (3 << 28) | 404, /* TagType:UINT */
+
+ /**
+ * Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
+ *
+ * Must not be hardware-enforced.
+ */
+ USER_ID = (3 << 28) | 501, /* TagType:UINT */
+
+ /**
+ * Tag::USER_SECURE_ID specifies that a key may only be used under a particular secure user
+ * authentication state. This tag is mutually exclusive with Tag::NO_AUTH_REQUIRED.
+ *
+ * The value is a 64-bit integer specifying the authentication policy state value which must be
+ * present in the userId or authenticatorId field of a HardwareAuthToken provided to begin(),
+ * update(), or finish(). If a key with Tag::USER_SECURE_ID is used without a HardwareAuthToken
+ * with the matching userId or authenticatorId, the IKeyMintDevice must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * Tag::USER_SECURE_ID interacts with Tag::AUTH_TIMEOUT in a very important way. If
+ * Tag::AUTH_TIMEOUT is present in the key's characteristics then the key is a "timeout-based"
+ * key, and may only be used if the difference between the current time when begin() is called
+ * and the timestamp in the HardwareAuthToken is less than the value in Tag::AUTH_TIMEOUT * 1000
+ * (the multiplier is because Tag::AUTH_TIMEOUT is in seconds, but the HardwareAuthToken
+ * timestamp is in milliseconds). Otherwise the IKeyMintDevice must returrn
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * If Tag::AUTH_TIMEOUT is not present, then the key is an "auth-per-operation" key. In this
+ * case, begin() must not require a HardwareAuthToken with appropriate contents. Instead,
+ * update() and finish() must receive a HardwareAuthToken with Tag::USER_SECURE_ID value in
+ * userId or authenticatorId fields, and the current operation's operation handle in the
+ * challenge field. Otherwise the IKeyMintDevice must returrn
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * This tag is repeatable. If repeated, and any one of the values matches the HardwareAuthToken
+ * as described above, the key is authorized for use. Otherwise the operation must fail with
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
+ * Must be hardware-enforced.
+ */
+ USER_SECURE_ID = (10 << 28) | 502, /* TagType:ULONG_REP */
+
+ /**
+ * Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key. This tag
+ * is mutually exclusive with Tag::USER_SECURE_ID.
+ *
+ * Must be hardware-enforced.
+ */
+ NO_AUTH_REQUIRED = (7 << 28) | 503, /* TagType:BOOL */
+
+ /**
+ * Tag::USER_AUTH_TYPE specifies the types of user authenticators that may be used to authorize
+ * this key.
+ *
+ * The value is one or more values from HardwareAuthenticatorType, ORed together.
+ *
+ * When IKeyMintDevice is requested to perform an operation with a key with this tag, it must
+ * receive a HardwareAuthToken and one or more bits must be set in both the HardwareAuthToken's
+ * authenticatorType field and the Tag::USER_AUTH_TYPE value. That is, it must be true that
+ *
+ * (token.authenticatorType & tag_user_auth_type) != 0
+ *
+ * where token.authenticatorType is the authenticatorType field of the HardwareAuthToken and
+ * tag_user_auth_type is the value of Tag:USER_AUTH_TYPE.
+ *
+ * Must be hardware-enforced.
+ */
+ USER_AUTH_TYPE = (1 << 28) | 504, /* TagType:ENUM */
+
+ /**
+ * Tag::AUTH_TIMEOUT specifies the time in seconds for which the key is authorized for use,
+ * after user authentication. If
+ * Tag::USER_SECURE_ID is present and this tag is not, then the key requies authentication for
+ * every usage (see begin() for the details of the authentication-per-operation flow).
+ *
+ * The value is a 32-bit integer specifying the time in seconds after a successful
+ * authentication of the user specified by Tag::USER_SECURE_ID with the authentication method
+ * specified by Tag::USER_AUTH_TYPE that the key can be used.
+ *
+ * Must be hardware-enforced.
+ */
+ AUTH_TIMEOUT = (3 << 28) | 505, /* TagType:UINT */
+
+ /**
+ * Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication timeout if
+ * device is still on-body (requires on-body sensor).
+ *
+ * Cannot be hardware-enforced.
+ */
+ ALLOW_WHILE_ON_BODY = (7 << 28) | 506, /* TagType:BOOL */
+
+ /**
+ * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
+ * unusable except when the user has provided proof of physical presence. Proof of physical
+ * presence must be a signal that cannot be triggered by an attacker who doesn't have one of:
+ *
+ * a) Physical control of the device or
+ *
+ * b) Control of the secure environment that holds the key.
+ *
+ * For instance, proof of user identity may be considered proof of presence if it meets the
+ * requirements. However, proof of identity established in one security domain (e.g. TEE) does
+ * not constitute proof of presence in another security domain (e.g. StrongBox), and no
+ * mechanism analogous to the authentication token is defined for communicating proof of
+ * presence across security domains.
+ *
+ * Some examples:
+ *
+ * A hardware button hardwired to a pin on a StrongBox device in such a way that nothing
+ * other than a button press can trigger the signal constitutes proof of physical presence
+ * for StrongBox keys.
+ *
+ * Fingerprint authentication provides proof of presence (and identity) for TEE keys if the
+ * TEE has exclusive control of the fingerprint scanner and performs fingerprint matching.
+ *
+ * Password authentication does not provide proof of presence to either TEE or StrongBox,
+ * even if TEE or StrongBox does the password matching, because password input is handled by
+ * the non-secure world, which means an attacker who has compromised Android can spoof
+ * password authentication.
+ *
+ * Note that no mechanism is defined for delivering proof of presence to an IKeyMintDevice,
+ * except perhaps as implied by an auth token. This means that KeyMint must be able to check
+ * proof of presence some other way. Further, the proof of presence must be performed between
+ * begin() and the first call to update() or finish(). If the first update() or the finish()
+ * call is made without proof of presence, the keyMint method must return
+ * ErrorCode::PROOF_OF_PRESENCE_REQUIRED and abort the operation. The caller must delay the
+ * update() or finish() call until proof of presence has been provided, which means the caller
+ * must also have some mechanism for verifying that the proof has been provided.
+ *
+ * Only one operation requiring TUP may be in flight at a time. If begin() has already been
+ * called on one key with TRUSTED_USER_PRESENCE_REQUIRED, and another begin() comes in for that
+ * key or another with TRUSTED_USER_PRESENCE_REQUIRED, KeyMint must return
+ * ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED.
+ *
+ * Must be hardware-enforced.
+ */
+ TRUSTED_USER_PRESENCE_REQUIRED = (7 << 28) | 507, /* TagType:BOOL */
+
+ /** Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
+ * specifies that this key must not be usable unless the user provides confirmation of the data
+ * to be signed. Confirmation is proven to keyMint via an approval token. See
+ * CONFIRMATION_TOKEN, as well as the ConfirmatinUI HAL.
+ *
+ * If an attempt to use a key with this tag does not have a cryptographically valid
+ * CONFIRMATION_TOKEN provided to finish() or if the data provided to update()/finish() does not
+ * match the data described in the token, keyMint must return NO_USER_CONFIRMATION.
+ *
+ * Must be hardware-enforced.
+ */
+ TRUSTED_CONFIRMATION_REQUIRED = (7 << 28) | 508, /* TagType:BOOL */
+
+ /**
+ * Tag::UNLOCKED_DEVICE_REQUIRED specifies that the key may only be used when the device is
+ * unlocked.
+ *
+ * Must be software-enforced.
+ */
+ UNLOCKED_DEVICE_REQUIRED = (7 << 28) | 509, /* TagType:BOOL */
+
+ /**
+ * Tag::APPLICATION_ID. When provided to generateKey or importKey, this tag specifies data
+ * that is necessary during all uses of the key. In particular, calls to exportKey() and
+ * getKeyCharacteristics() must provide the same value to the clientId parameter, and calls to
+ * begin must provide this tag and the same associated data as part of the inParams set. If
+ * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+ *
+ * The content of this tag must be bound to the key cryptographically, meaning it must not be
+ * possible for an adversary who has access to all of the secure world secrets but does not have
+ * access to the tag content to decrypt the key without brute-forcing the tag content, which
+ * applications can prevent by specifying sufficiently high-entropy content.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ APPLICATION_ID = (9 << 28) | 601, /* TagType:BYTES */
+
+ /*
+ * Semantically unenforceable tags, either because they have no specific meaning or because
+ * they're informational only.
+ */
+
+ /**
+ * Tag::APPLICATION_DATA. When provided to generateKey or importKey, this tag specifies data
+ * that is necessary during all uses of the key. In particular, calls to exportKey() and
+ * getKeyCharacteristics() must provide the same value to the appData parameter, and calls to
+ * begin must provide this tag and the same associated data as part of the inParams set. If
+ * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+ *
+ * The content of this tag msut be bound to the key cryptographically, meaning it must not be
+ * possible for an adversary who has access to all of the secure world secrets but does not have
+ * access to the tag content to decrypt the key without brute-forcing the tag content, which
+ * applications can prevent by specifying sufficiently high-entropy content.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ APPLICATION_DATA = (9 << 28) | 700, /* TagType:BYTES */
+
+ /**
+ * Tag::CREATION_DATETIME specifies the date and time the key was created, in milliseconds since
+ * January 1, 1970. This tag is optional and informational only.
+ *
+ * Tag::CREATED is informational only, and not enforced by anything. Must be in the
+ * software-enforced list, if provided.
+ */
+ CREATION_DATETIME = (6 << 28) | 701, /* TagType:DATE */
+
+ /**
+ * Tag::ORIGIN specifies where the key was created, if known. This tag must not be specified
+ * during key generation or import, and must be added to the key characteristics by the
+ * IKeyMintDevice. The possible values are defined in the KeyOrigin enum.
+ *
+ * Must be hardware-enforced.
+ */
+ ORIGIN = (1 << 28) | 702, /* TagType:ENUM */
+
+ // 703 is unused.
+
+ /**
+ * Tag::ROOT_OF_TRUST specifies the root of trust associated with the key used by verified boot
+ * to validate the system. It describes the boot key, verified boot state, boot hash, and
+ * whether device is locked. This tag is never provided to or returned from KeyMint in the
+ * key characteristics. It exists only to define the tag for use in the attestation record.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ROOT_OF_TRUST = (9 << 28) | 704, /* TagType:BYTES */
+
+ /**
+ * Tag::OS_VERSION specifies the system OS version with which the key may be used. This tag is
+ * never sent to the IKeyMintDevice, but is added to the hardware-enforced authorization list
+ * by the TA. Any attempt to use a key with a Tag::OS_VERSION value different from the
+ * currently-running OS version must cause begin(), getKeyCharacteristics() or exportKey() to
+ * return ErrorCode::KEY_REQUIRES_UPGRADE. See upgradeKey() for details.
+ *
+ * The value of the tag is an integer of the form MMmmss, where MM is the major version number,
+ * mm is the minor version number, and ss is the sub-minor version number. For example, for a
+ * key generated on Android version 4.0.3, the value would be 040003.
+ *
+ * The IKeyMintDevice HAL must read the current OS version from the system property
+ * ro.build.version.release and deliver it to the secure environment when the HAL is first
+ * loaded (mechanism is implementation-defined). The secure environment must not accept another
+ * version until after the next boot. If the content of ro.build.version.release has additional
+ * version information after the sub-minor version number, it must not be included in
+ * Tag::OS_VERSION. If the content is non-numeric, the secure environment must use 0 as the
+ * system version.
+ *
+ * Must be hardware-enforced.
+ */
+ OS_VERSION = (3 << 28) | 705, /* TagType:UINT */
+
+ /**
+ * Tag::OS_PATCHLEVEL specifies the system security patch level with which the key may be used.
+ * This tag is never sent to the keyMint TA, but is added to the hardware-enforced
+ * authorization list by the TA. Any attempt to use a key with a Tag::OS_PATCHLEVEL value
+ * different from the currently-running system patchlevel must cause begin(),
+ * getKeyCharacteristics() or exportKey() to return ErrorCode::KEY_REQUIRES_UPGRADE. See
+ * upgradeKey() for details.
+ *
+ * The value of the tag is an integer of the form YYYYMM, where YYYY is the four-digit year of
+ * the last update and MM is the two-digit month of the last update. For example, for a key
+ * generated on an Android device last updated in December 2015, the value would be 201512.
+ *
+ * The IKeyMintDevice HAL must read the current system patchlevel from the system property
+ * ro.build.version.security_patch and deliver it to the secure environment when the HAL is
+ * first loaded (mechanism is implementation-defined). The secure environment must not accept
+ * another patchlevel until after the next boot.
+ *
+ * Must be hardware-enforced.
+ */
+ OS_PATCHLEVEL = (3 << 28) | 706, /* TagType:UINT */
+
+ /**
+ * Tag::UNIQUE_ID specifies a unique, time-based identifier. This tag is never provided to or
+ * returned from KeyMint in the key characteristics. It exists only to define the tag for use
+ * in the attestation record.
+ *
+ * When a key with Tag::INCLUDE_UNIQUE_ID is attested, the unique ID is added to the attestation
+ * record. The value is a 128-bit hash that is unique per device and per calling application,
+ * and changes monthly and on most password resets. It is computed with:
+ *
+ * HMAC_SHA256(T || C || R, HBK)
+ *
+ * Where:
+ *
+ * T is the "temporal counter value", computed by dividing the value of
+ * Tag::CREATION_DATETIME by 2592000000, dropping any remainder. T changes every 30 days
+ * (2592000000 = 30 * 24 * 60 * 60 * 1000).
+ *
+ * C is the value of Tag::ATTESTATION_APPLICATION_ID that is provided to attestKey().
+ *
+ * R is 1 if Tag::RESET_SINCE_ID_ROTATION was provided to attestKey or 0 if the tag was not
+ * provided.
+ *
+ * HBK is a unique hardware-bound secret known to the secure environment and never revealed
+ * by it. The secret must contain at least 128 bits of entropy and be unique to the
+ * individual device (probabilistic uniqueness is acceptable).
+ *
+ * HMAC_SHA256 is the HMAC function, with SHA-2-256 as the hash.
+ *
+ * The output of the HMAC function must be truncated to 128 bits.
+ *
+ * Must be hardware-enforced.
+ */
+ UNIQUE_ID = (9 << 28) | 707, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attestKey() method,
+ * which must place the value in the KeyDescription SEQUENCE of the attestation extension. See
+ * attestKey().
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_CHALLENGE = (9 << 28) | 708, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_APPLICATION_ID identifies the set of applications which may use a key, used
+ * only with attestKey().
+ *
+ * The content of Tag::ATTESTATION_APPLICATION_ID is a DER-encoded ASN.1 structure, with the
+ * following schema:
+ *
+ * AttestationApplicationId ::= SEQUENCE {
+ * packageInfoRecords SET OF PackageInfoRecord,
+ * signatureDigests SET OF OCTET_STRING,
+ * }
+ *
+ * PackageInfoRecord ::= SEQUENCE {
+ * packageName OCTET_STRING,
+ * version INTEGER,
+ * }
+ *
+ * See system/security/keystore/keystore_attestation_id.cpp for details of construction.
+ * IKeyMintDevice implementers do not need to create or parse the ASN.1 structure, but only
+ * copy the tag value into the attestation record. The DER-encoded string must not exceed 1 KiB
+ * in length.
+ *
+ * Cannot be hardware-enforced.
+ */
+ ATTESTATION_APPLICATION_ID = (9 << 28) | 709, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_BRAND provides the device's brand name, as returned by Build.BRAND in
+ * Android, to attestKey(). This field must be set only when requesting attestation of the
+ * device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_BRAND = (9 << 28) | 710, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_DEVICE provides the device's device name, as returned by Build.DEVICE in
+ * Android, to attestKey(). This field must be set only when requesting attestation of the
+ * device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_DEVICE = (9 << 28) | 711, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_PRODUCT provides the device's product name, as returned by Build.PRODUCT
+ * in Android, to attestKey(). This field must be set only when requesting attestation of the
+ * device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_PRODUCT = (9 << 28) | 712, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_SERIAL the device's serial number. This field must be set only when
+ * requesting attestation of the device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_SERIAL = (9 << 28) | 713, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attestKey().
+ * This field must be set only when requesting attestation of the device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_IMEI = (9 << 28) | 714, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_MEID provides the MEIDs for all radios on the device to attestKey().
+ * This field must be set only when requesting attestation of the device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_MEID = (9 << 28) | 715, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_MANUFACTURER provides the device's manufacturer name, as returned by
+ * Build.MANUFACTURER in Android, to attstKey(). This field must be set only when requesting
+ * attestation of the device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_MANUFACTURER = (9 << 28) | 716, /* TagType:BYTES */
+
+ /**
+ * Tag::ATTESTATION_ID_MODEL provides the device's model name, as returned by Build.MODEL in
+ * Android, to attestKey(). This field must be set only when requesting attestation of the
+ * device's identifiers.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_MODEL = (9 << 28) | 717, /* TagType:BYTES */
+
+ /**
+ * Tag::VENDOR_PATCHLEVEL specifies the vendor image security patch level with which the key may
+ * be used. This tag is never sent to the keyMint TA, but is added to the hardware-enforced
+ * authorization list by the TA. Any attempt to use a key with a Tag::VENDOR_PATCHLEVEL value
+ * different from the currently-running system patchlevel must cause begin(),
+ * getKeyCharacteristics() or exportKey() to return ErrorCode::KEY_REQUIRES_UPGRADE. See
+ * upgradeKey() for details.
+ *
+ * The value of the tag is an integer of the form YYYYMMDD, where YYYY is the four-digit year of
+ * the last update, MM is the two-digit month and DD is the two-digit day of the last
+ * update. For example, for a key generated on an Android device last updated on June 5, 2018,
+ * the value would be 20180605.
+ *
+ * The IKeyMintDevice HAL must read the current vendor patchlevel from the system property
+ * ro.vendor.build.security_patch and deliver it to the secure environment when the HAL is first
+ * loaded (mechanism is implementation-defined). The secure environment must not accept another
+ * patchlevel until after the next boot.
+ *
+ * Must be hardware-enforced.
+ */
+ VENDOR_PATCHLEVEL = (3 << 28) | 718, /* TagType:UINT */
+
+ /**
+ * Tag::BOOT_PATCHLEVEL specifies the boot image (kernel) security patch level with which the
+ * key may be used. This tag is never sent to the keyMint TA, but is added to the
+ * hardware-enforced authorization list by the TA. Any attempt to use a key with a
+ * Tag::BOOT_PATCHLEVEL value different from the currently-running system patchlevel must
+ * cause begin(), getKeyCharacteristics() or exportKey() to return
+ * ErrorCode::KEY_REQUIRES_UPGRADE. See upgradeKey() for details.
+ *
+ * The value of the tag is an integer of the form YYYYMMDD, where YYYY is the four-digit year of
+ * the last update, MM is the two-digit month and DD is the two-digit day of the last
+ * update. For example, for a key generated on an Android device last updated on June 5, 2018,
+ * the value would be 20180605. If the day is not known, 00 may be substituted.
+ *
+ * During each boot, the bootloader must provide the patch level of the boot image to the secure
+ * envirionment (mechanism is implementation-defined).
+ *
+ * Must be hardware-enforced.
+ */
+ BOOT_PATCHLEVEL = (3 << 28) | 719, /* TagType:UINT */
+
+ /**
+ * DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attestKey(). It indicates that
+ * attestation using a device-unique key is requested, rather than a batch key. When a
+ * device-unique key is used, only the attestation certificate is returned; no additional
+ * chained certificates are provided. It's up to the caller to recognize the device-unique
+ * signing key. Only SecurityLevel::STRONGBOX IKeyMintDevices may support device-unique
+ * attestations. SecurityLevel::TRUSTED_ENVIRONMENT IKeyMintDevices must return
+ * ErrorCode::INVALID_ARGUMENT if they receive DEVICE_UNIQUE_ATTESTATION.
+ * SecurityLevel::STRONGBOX IKeyMintDevices need not support DEVICE_UNIQUE_ATTESTATION, and
+ * return ErrorCode::CANNOT_ATTEST_IDS if they do not support it.
+ *
+ * IKeyMintDevice implementations that support device-unique attestation MUST add the
+ * DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
+ */
+ DEVICE_UNIQUE_ATTESTATION = (7 << 28) | 720, /* TagType:BOOL */
+
+ /**
+ * IDENTITY_CREDENTIAL_KEY is never used by IKeyMintDevice, is not a valid argument to key
+ * generation or any operation, is never returned by any method and is never used in a key
+ * attestation. It is used in attestations produced by the IIdentityCredential HAL when that
+ * HAL attests to Credential Keys. IIdentityCredential produces KeyMint-style attestations.
+ */
+ IDENTITY_CREDENTIAL_KEY = (7 << 28) | 721, /* TagType:BOOL */
+
+ /**
+ * To prevent keys from being compromised if an attacker acquires read access to system / kernel
+ * memory, some inline encryption hardware supports protecting storage encryption keys in
+ * hardware without software having access to or the ability to set the plaintext keys.
+ * Instead, software only sees wrapped version of these keys.
+ *
+ * STORAGE_KEY is used to denote that a key generated or imported is a key used for storage
+ * encryption. Keys of this type can either be generated or imported or secure imported using
+ * keyMint. exportKey() can be used to re-wrap storage key with a per-boot ephemeral key
+ * wrapped key once the key characteristics are enforced.
+ *
+ * Keys with this tag cannot be used for any operation within keyMint.
+ * ErrorCode::INVALID_OPERATION is returned when a key with Tag::STORAGE_KEY is provided to
+ * begin().
+ */
+ STORAGE_KEY = (7 << 28) | 722, /* TagType:BOOL */
+
+ /**
+ * Tag::ASSOCIATED_DATA Provides "associated data" for AES-GCM encryption or decryption. This
+ * tag is provided to update and specifies data that is not encrypted/decrypted, but is used in
+ * computing the GCM tag.
+ *
+ * Must never appear KeyCharacteristics.
+ */
+ ASSOCIATED_DATA = (9 << 28) | 1000, /* TagType:BYTES */
+
+ /**
+ * Tag::NONCE is used to provide or return a nonce or Initialization Vector (IV) for AES-GCM,
+ * AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption. This tag is provided to begin during
+ * encryption and decryption operations. It is only provided to begin if the key has
+ * Tag::CALLER_NONCE. If not provided, an appropriate nonce or IV must be randomly generated by
+ * KeyMint and returned from begin.
+ *
+ * The value is a blob, an arbitrary-length array of bytes. Allowed lengths depend on the mode:
+ * GCM nonces are 12 bytes in length; AES-CBC and AES-CTR IVs are 16 bytes in length, 3DES-CBC
+ * IVs are 8 bytes in length.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ NONCE = (9 << 28) | 1001, /* TagType:BYTES */
+
+ /**
+ * Tag::MAC_LENGTH provides the requested length of a MAC or GCM authentication tag, in bits.
+ *
+ * The value is the MAC length in bits. It must be a multiple of 8 and at least as large as the
+ * value of Tag::MIN_MAC_LENGTH associated with the key. Otherwise, begin() must return
+ * ErrorCode::INVALID_MAC_LENGTH.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ MAC_LENGTH = (3 << 28) | 1003, /* TagType:UINT */
+
+ /**
+ * Tag::RESET_SINCE_ID_ROTATION specifies whether the device has been factory reset since the
+ * last unique ID rotation. Used for key attestation.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ RESET_SINCE_ID_ROTATION = (7 << 28) | 1004, /* TagType:BOOL */
+
+ /**
+ * Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user
+ * confirmed a signing request. The content is a full-length HMAC-SHA256 value. See the
+ * ConfirmationUI HAL for details of token computation.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ CONFIRMATION_TOKEN = (9 << 28) | 1005, /* TagType:BYTES */
+}
diff --git a/keymint/aidl/android/hardware/keymint/TagType.aidl b/keymint/aidl/android/hardware/keymint/TagType.aidl
new file mode 100644
index 0000000..fb50b10
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/TagType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * TagType classifies Tags in Tag.aidl into various groups of data.
+ */
+@VintfStability
+@Backing(type="int")
+enum TagType {
+ /** Invalid type, used to designate a tag as uninitialized. */
+ INVALID = 0 << 28,
+ /** Enumeration value. */
+ ENUM = 1 << 28,
+ /** Repeatable enumeration value. */
+ ENUM_REP = 2 << 28,
+ /** 32-bit unsigned integer. */
+ UINT = 3 << 28,
+ /** Repeatable 32-bit unsigned integer. */
+ UINT_REP = 4 << 28,
+ /** 64-bit unsigned integer. */
+ ULONG = 5 << 28,
+ /** 64-bit unsigned integer representing a date and time, in milliseconds since 1 Jan 1970. */
+ DATE = 6 << 28,
+ /** Boolean. If a tag with this type is present, the value is "true". If absent, "false". */
+ BOOL = 7 << 28,
+ /** Byte string containing an arbitrary-length integer, big-endian ordering. */
+ BIGNUM = 8 << 28,
+ /** Byte string */
+ BYTES = 9 << 28,
+ /** Repeatable 64-bit unsigned integer */
+ ULONG_REP = 10 << 28,
+}
diff --git a/keymint/aidl/android/hardware/keymint/Timestamp.aidl b/keymint/aidl/android/hardware/keymint/Timestamp.aidl
new file mode 100644
index 0000000..7c882c6
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/Timestamp.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+/**
+ * Time in milliseconds since some arbitrary point in time. Time must be monotonically increasing,
+ * and a secure environment's notion of "current time" must not repeat until the Android device
+ * reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
+ * by setting the clock to zero during each boot, and then counting time accurately).
+ */
+@VintfStability
+parcelable Timestamp {
+ long milliSeconds;
+}
diff --git a/keymint/aidl/android/hardware/keymint/VerificationToken.aidl b/keymint/aidl/android/hardware/keymint/VerificationToken.aidl
new file mode 100644
index 0000000..736c0e2
--- /dev/null
+++ b/keymint/aidl/android/hardware/keymint/VerificationToken.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymint;
+
+import android.hardware.keymint.SecurityLevel;
+import android.hardware.keymint.Timestamp;
+
+/**
+ * VerificationToken instances are used for secure environments to authenticate one another.
+ *
+ * This version of the parcelable currently don't use the parametersVerified field since it's not
+ * needed for time-based verification. This can be added in a later version, if needed.
+ */
+@VintfStability
+parcelable VerificationToken {
+ /**
+ * The operation handle, used to ensure freshness.
+ */
+ long challenge;
+
+ /**
+ * The current time of the secure environment that generates the VerificationToken. This can be
+ * checked against auth tokens generated by the same secure environment, which avoids needing to
+ * synchronize clocks.
+ */
+ Timestamp timestamp;
+
+ /**
+ * SecurityLevel of the secure environment that generated the token.
+ */
+ SecurityLevel securityLevel;
+
+ /**
+ * 32-byte HMAC-SHA256 of the above values, computed as:
+ *
+ * HMAC(H,
+ * "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified)
+ *
+ * where:
+ *
+ * ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeyMint).
+ *
+ * ``||'' represents concatenation
+ *
+ * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
+ * order. securityLevel is represented as a 32-bit unsigned integer in big-endian order.
+ *
+ * If parametersVerified is non-empty, the representation of parametersVerified is an ASN.1 DER
+ * encoded representation of the values. The ASN.1 schema used is the AuthorizationList schema
+ * from the Keystore attestation documentation. If parametersVerified is empty, it is simply
+ * omitted from the HMAC computation.
+ */
+ byte[] mac;
+}
diff --git a/keymint/aidl/default/Android.bp b/keymint/aidl/default/Android.bp
new file mode 100644
index 0000000..539ca47
--- /dev/null
+++ b/keymint/aidl/default/Android.bp
@@ -0,0 +1,26 @@
+cc_binary {
+ name: "android.hardware.keymint@1.0-service",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.keymint@1.0-service.rc"],
+ vintf_fragments: ["android.hardware.keymint@1.0-service.xml"],
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "android.hardware.keymint-ndk_platform",
+ "libbase",
+ "libbinder_ndk",
+ "libcppbor",
+ "libcrypto",
+ "liblog",
+ "libkeymaster_portable",
+ "libkeymint1",
+ "libpuresoftkeymasterdevice",
+ "libutils",
+ ],
+ srcs: [
+ "service.cpp",
+ ],
+}
diff --git a/keymint/aidl/default/android.hardware.keymint@1.0-service.rc b/keymint/aidl/default/android.hardware.keymint@1.0-service.rc
new file mode 100644
index 0000000..92dce88
--- /dev/null
+++ b/keymint/aidl/default/android.hardware.keymint@1.0-service.rc
@@ -0,0 +1,3 @@
+service vendor.keymint-default /vendor/bin/hw/android.hardware.keymint@1.0-service
+ class early_hal
+ user nobody
diff --git a/keymint/aidl/default/android.hardware.keymint@1.0-service.xml b/keymint/aidl/default/android.hardware.keymint@1.0-service.xml
new file mode 100644
index 0000000..3935b5a
--- /dev/null
+++ b/keymint/aidl/default/android.hardware.keymint@1.0-service.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.keymint</name>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+</manifest>
diff --git a/keymint/aidl/default/service.cpp b/keymint/aidl/default/service.cpp
new file mode 100644
index 0000000..ca5555e
--- /dev/null
+++ b/keymint/aidl/default/service.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.keymint1-service"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <AndroidKeyMint1Device.h>
+#include <keymaster/soft_keymaster_logger.h>
+
+using aidl::android::hardware::keymint::SecurityLevel;
+using aidl::android::hardware::keymint::V1_0::AndroidKeyMint1Device;
+
+int main() {
+ // Zero threads seems like a useless pool, but below we'll join this thread to it, increasing
+ // the pool size to 1.
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<AndroidKeyMint1Device> km5 =
+ ndk::SharedRefBase::make<AndroidKeyMint1Device>(SecurityLevel::SOFTWARE);
+
+ keymaster::SoftKeymasterLogger logger;
+ const auto instanceName = std::string(AndroidKeyMint1Device::descriptor) + "/default";
+ LOG(INFO) << "instance: " << instanceName;
+ binder_status_t status =
+ AServiceManager_addService(km5->asBinder().get(), instanceName.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/keymint/aidl/vts/functional/Android.bp b/keymint/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..9ee8239
--- /dev/null
+++ b/keymint/aidl/vts/functional/Android.bp
@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+ name: "VtsAidlKeyMintV1_0TargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "keyMint1Test.cpp",
+ "VerificationTokenTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ "libkeymint1",
+ "libkeymintSupport",
+ ],
+ static_libs: [
+ "android.hardware.keymint-cpp",
+ "libcppbor",
+ "libkeyMint1VtsTestUtil",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test_library {
+ name: "libkeyMint1VtsTestUtil",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "KeyMintAidlTestBase.cpp",
+ ],
+ export_include_dirs: [
+ ".",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ "libkeymint1",
+ "libkeymintSupport",
+ ],
+ static_libs: [
+ "android.hardware.keymint-cpp",
+ "libcppbor",
+ ],
+}
diff --git a/keymint/aidl/vts/functional/AndroidTest.xml b/keymint/aidl/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..43e7a8a
--- /dev/null
+++ b/keymint/aidl/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsAidlKeyMintV1_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsAidlKeyMintV1_0TargetTest->/data/local/tmp/VtsAidlKeyMintV1_0TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsAidlKeyMintV1_0TargetTest" />
+ <option name="native-test-timeout" value="900000"/>
+ </test>
+</configuration>
diff --git a/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
new file mode 100644
index 0000000..0546149
--- /dev/null
+++ b/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "KeyMintAidlTestBase.h"
+
+#include <chrono>
+#include <vector>
+
+#include <android-base/logging.h>
+
+#include <keymintSupport/key_param_output.h>
+#include <keymintSupport/keymint_utils.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using namespace std::literals::chrono_literals;
+using std::endl;
+using std::optional;
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
+ if (set.size() == 0)
+ os << "(Empty)" << ::std::endl;
+ else {
+ os << "\n";
+ for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+ }
+ return os;
+}
+
+namespace test {
+
+ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(Status result) {
+ if (result.isOk()) return ErrorCode::OK;
+
+ if (result.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
+ return static_cast<ErrorCode>(result.serviceSpecificErrorCode());
+ }
+
+ return ErrorCode::UNKNOWN_ERROR;
+}
+
+void KeyMintAidlTestBase::InitializeKeyMint(sp<IKeyMintDevice> keyMint) {
+ ASSERT_NE(keyMint, nullptr);
+ keymint_ = keyMint;
+
+ KeyMintHardwareInfo info;
+ ASSERT_TRUE(keymint_->getHardwareInfo(&info).isOk());
+
+ securityLevel_ = info.securityLevel;
+ name_.assign(info.keyMintName.begin(), info.keyMintName.end());
+ author_.assign(info.keyMintAuthorName.begin(), info.keyMintAuthorName.end());
+
+ os_version_ = getOsVersion();
+ os_patch_level_ = getOsPatchlevel();
+}
+
+void KeyMintAidlTestBase::SetUp() {
+ InitializeKeyMint(
+ android::waitForDeclaredService<IKeyMintDevice>(String16(GetParam().c_str())));
+}
+
+ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
+ vector<uint8_t>* keyBlob, KeyCharacteristics* keyChar) {
+ EXPECT_NE(keyBlob, nullptr) << "Key blob pointer must not be null. Test bug";
+ EXPECT_NE(keyChar, nullptr)
+ << "Previous characteristics not deleted before generating key. Test bug.";
+
+ // Aidl does not clear these output parameters if the function returns
+ // error. This is different from hal where output parameter is always
+ // cleared due to hal returning void. So now we need to do our own clearing
+ // of the output variables prior to calling keyMint aidl libraries.
+ keyBlob->clear();
+ keyChar->softwareEnforced.clear();
+ keyChar->hardwareEnforced.clear();
+ certChain_.clear();
+
+ Status result;
+ ByteArray blob;
+
+ result = keymint_->generateKey(key_desc.vector_data(), &blob, keyChar, &certChain_);
+
+ // On result, blob & characteristics should be empty.
+ if (result.isOk()) {
+ if (SecLevel() != SecurityLevel::SOFTWARE) {
+ EXPECT_GT(keyChar->hardwareEnforced.size(), 0);
+ }
+ EXPECT_GT(keyChar->softwareEnforced.size(), 0);
+ // TODO(seleneh) in a later version where we return @nullable
+ // single Certificate, check non-null single certificate is always
+ // non-empty.
+ *keyBlob = blob.data;
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc) {
+ return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+ const string& key_material, vector<uint8_t>* key_blob,
+ KeyCharacteristics* key_characteristics) {
+ Status result;
+
+ certChain_.clear();
+ key_characteristics->softwareEnforced.clear();
+ key_characteristics->hardwareEnforced.clear();
+ key_blob->clear();
+
+ ByteArray blob;
+ result = keymint_->importKey(key_desc.vector_data(), format,
+ vector<uint8_t>(key_material.begin(), key_material.end()), &blob,
+ key_characteristics, &certChain_);
+
+ if (result.isOk()) {
+ if (SecLevel() != SecurityLevel::SOFTWARE) {
+ EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
+ }
+ EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
+ *key_blob = blob.data;
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+ const string& key_material) {
+ return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapping_key,
+ const AuthorizationSet& wrapping_key_desc,
+ string masking_key,
+ const AuthorizationSet& unwrapping_params) {
+ Status result;
+ EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
+
+ ByteArray outBlob;
+ key_characteristics_.softwareEnforced.clear();
+ key_characteristics_.hardwareEnforced.clear();
+
+ result = keymint_->importWrappedKey(vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()),
+ key_blob_,
+ vector<uint8_t>(masking_key.begin(), masking_key.end()),
+ unwrapping_params.vector_data(), 0 /* passwordSid */,
+ 0 /* biometricSid */, &outBlob, &key_characteristics_);
+
+ if (result.isOk()) {
+ key_blob_ = outBlob.data;
+ if (SecLevel() != SecurityLevel::SOFTWARE) {
+ EXPECT_GT(key_characteristics_.hardwareEnforced.size(), 0);
+ }
+ EXPECT_GT(key_characteristics_.softwareEnforced.size(), 0);
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
+ Status result = keymint_->deleteKey(*key_blob);
+ if (!keep_key_blob) {
+ *key_blob = vector<uint8_t>();
+ }
+
+ EXPECT_TRUE(result.isOk()) << result.serviceSpecificErrorCode() << endl;
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::DeleteKey(bool keep_key_blob) {
+ return DeleteKey(&key_blob_, keep_key_blob);
+}
+
+ErrorCode KeyMintAidlTestBase::DeleteAllKeys() {
+ Status result = keymint_->deleteAllKeys();
+ EXPECT_TRUE(result.isOk()) << result.serviceSpecificErrorCode() << endl;
+ return GetReturnErrorCode(result);
+}
+
+void KeyMintAidlTestBase::CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
+ ErrorCode result = DeleteKey(key_blob, keep_key_blob);
+ EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
+}
+
+void KeyMintAidlTestBase::CheckedDeleteKey() {
+ CheckedDeleteKey(&key_blob_);
+}
+
+ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
+ const AuthorizationSet& in_params,
+ AuthorizationSet* out_params, sp<IKeyMintOperation>& op) {
+ SCOPED_TRACE("Begin");
+ Status result;
+ BeginResult out;
+ result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
+
+ if (result.isOk()) {
+ *out_params = out.params;
+ challenge_ = out.challenge;
+ op = out.operation;
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
+ const AuthorizationSet& in_params,
+ AuthorizationSet* out_params) {
+ SCOPED_TRACE("Begin");
+ Status result;
+ BeginResult out;
+
+ result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
+
+ if (result.isOk()) {
+ *out_params = out.params;
+ challenge_ = out.challenge;
+ op_ = out.operation;
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params) {
+ SCOPED_TRACE("Begin");
+ EXPECT_EQ(nullptr, op_);
+ return Begin(purpose, key_blob_, in_params, out_params);
+}
+
+ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
+ SCOPED_TRACE("Begin");
+ AuthorizationSet out_params;
+ ErrorCode result = Begin(purpose, in_params, &out_params);
+ EXPECT_TRUE(out_params.empty());
+ return result;
+}
+
+ErrorCode KeyMintAidlTestBase::Update(const AuthorizationSet& in_params, const string& input,
+ AuthorizationSet* out_params, string* output,
+ int32_t* input_consumed) {
+ SCOPED_TRACE("Update");
+
+ Status result;
+ EXPECT_NE(op_, nullptr);
+ if (!op_) {
+ return ErrorCode::UNEXPECTED_NULL_POINTER;
+ }
+
+ KeyParameterArray key_params;
+ key_params.params = in_params.vector_data();
+
+ KeyParameterArray in_keyParams;
+ in_keyParams.params = in_params.vector_data();
+
+ optional<KeyParameterArray> out_keyParams;
+ optional<ByteArray> o_put;
+ result = op_->update(in_keyParams, vector<uint8_t>(input.begin(), input.end()), {}, {},
+ &out_keyParams, &o_put, input_consumed);
+
+ if (result.isOk()) {
+ if (o_put) {
+ output->append(o_put->data.begin(), o_put->data.end());
+ }
+
+ if (out_keyParams) {
+ out_params->push_back(AuthorizationSet(out_keyParams->params));
+ }
+ }
+
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::Update(const string& input, string* out, int32_t* input_consumed) {
+ SCOPED_TRACE("Update");
+ AuthorizationSet out_params;
+ ErrorCode result =
+ Update(AuthorizationSet() /* in_params */, input, &out_params, out, input_consumed);
+ EXPECT_TRUE(out_params.empty());
+ return result;
+}
+
+ErrorCode KeyMintAidlTestBase::Finish(const AuthorizationSet& in_params, const string& input,
+ const string& signature, AuthorizationSet* out_params,
+ string* output) {
+ SCOPED_TRACE("Finish");
+ Status result;
+
+ EXPECT_NE(op_, nullptr);
+ if (!op_) {
+ return ErrorCode::UNEXPECTED_NULL_POINTER;
+ }
+
+ KeyParameterArray key_params;
+ key_params.params = in_params.vector_data();
+
+ KeyParameterArray in_keyParams;
+ in_keyParams.params = in_params.vector_data();
+
+ optional<KeyParameterArray> out_keyParams;
+ optional<vector<uint8_t>> o_put;
+
+ vector<uint8_t> oPut;
+ result = op_->finish(in_keyParams, vector<uint8_t>(input.begin(), input.end()),
+ vector<uint8_t>(signature.begin(), signature.end()), {}, {},
+ &out_keyParams, &oPut);
+
+ if (result.isOk()) {
+ if (out_keyParams) {
+ out_params->push_back(AuthorizationSet(out_keyParams->params));
+ }
+
+ output->append(oPut.begin(), oPut.end());
+ }
+
+ op_.clear(); // So dtor doesn't Abort().
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::Finish(const string& message, string* output) {
+ SCOPED_TRACE("Finish");
+ AuthorizationSet out_params;
+ string finish_output;
+ ErrorCode result = Finish(AuthorizationSet() /* in_params */, message, "" /* signature */,
+ &out_params, output);
+ if (result != ErrorCode::OK) {
+ return result;
+ }
+ EXPECT_EQ(0U, out_params.size());
+ return result;
+}
+
+ErrorCode KeyMintAidlTestBase::Finish(const string& message, const string& signature,
+ string* output) {
+ SCOPED_TRACE("Finish");
+ AuthorizationSet out_params;
+ ErrorCode result =
+ Finish(AuthorizationSet() /* in_params */, message, signature, &out_params, output);
+
+ if (result != ErrorCode::OK) {
+ return result;
+ }
+
+ EXPECT_EQ(0U, out_params.size());
+ return result;
+}
+
+ErrorCode KeyMintAidlTestBase::Abort(const sp<IKeyMintOperation>& op) {
+ SCOPED_TRACE("Abort");
+
+ EXPECT_NE(op, nullptr);
+ if (!op) {
+ return ErrorCode::UNEXPECTED_NULL_POINTER;
+ }
+
+ Status retval = op->abort();
+ EXPECT_TRUE(retval.isOk());
+ return static_cast<ErrorCode>(retval.serviceSpecificErrorCode());
+}
+
+ErrorCode KeyMintAidlTestBase::Abort() {
+ SCOPED_TRACE("Abort");
+
+ EXPECT_NE(op_, nullptr);
+ if (!op_) {
+ return ErrorCode::UNEXPECTED_NULL_POINTER;
+ }
+
+ Status retval = op_->abort();
+ return static_cast<ErrorCode>(retval.serviceSpecificErrorCode());
+}
+
+void KeyMintAidlTestBase::AbortIfNeeded() {
+ SCOPED_TRACE("AbortIfNeeded");
+ if (op_) {
+ EXPECT_EQ(ErrorCode::OK, Abort());
+ op_.clear();
+ }
+}
+
+string KeyMintAidlTestBase::ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
+ const string& message, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params) {
+ SCOPED_TRACE("ProcessMessage");
+ AuthorizationSet begin_out_params;
+ ErrorCode result = Begin(operation, key_blob, in_params, &begin_out_params);
+ EXPECT_EQ(ErrorCode::OK, result);
+ if (result != ErrorCode::OK) {
+ return "";
+ }
+
+ string output;
+ int32_t consumed = 0;
+ AuthorizationSet update_params;
+ AuthorizationSet update_out_params;
+ result = Update(update_params, message, &update_out_params, &output, &consumed);
+ EXPECT_EQ(ErrorCode::OK, result);
+ if (result != ErrorCode::OK) {
+ return "";
+ }
+
+ string unused;
+ AuthorizationSet finish_params;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(finish_params, message.substr(consumed), unused, &finish_out_params, &output));
+
+ out_params->push_back(begin_out_params);
+ out_params->push_back(finish_out_params);
+ return output;
+}
+
+string KeyMintAidlTestBase::SignMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& params) {
+ SCOPED_TRACE("SignMessage");
+ AuthorizationSet out_params;
+ string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
+ EXPECT_TRUE(out_params.empty());
+ return signature;
+}
+
+string KeyMintAidlTestBase::SignMessage(const string& message, const AuthorizationSet& params) {
+ SCOPED_TRACE("SignMessage");
+ return SignMessage(key_blob_, message, params);
+}
+
+string KeyMintAidlTestBase::MacMessage(const string& message, Digest digest, size_t mac_length) {
+ SCOPED_TRACE("MacMessage");
+ return SignMessage(
+ key_blob_, message,
+ AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
+}
+
+void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
+ Digest digest, const string& expected_mac) {
+ SCOPED_TRACE("CheckHmacTestVector");
+ ASSERT_EQ(ErrorCode::OK,
+ ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(key.size() * 8)
+ .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
+ .Digest(digest),
+ KeyFormat::RAW, key));
+ string signature = MacMessage(message, digest, expected_mac.size() * 8);
+ EXPECT_EQ(expected_mac, signature)
+ << "Test vector didn't match for key of size " << key.size() << " message of size "
+ << message.size() << " and digest " << digest;
+ CheckedDeleteKey();
+}
+
+void KeyMintAidlTestBase::CheckAesCtrTestVector(const string& key, const string& nonce,
+ const string& message,
+ const string& expected_ciphertext) {
+ SCOPED_TRACE("CheckAesCtrTestVector");
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(key.size() * 8)
+ .BlockMode(BlockMode::CTR)
+ .Authorization(TAG_CALLER_NONCE)
+ .Padding(PaddingMode::NONE),
+ KeyFormat::RAW, key));
+
+ auto params = AuthorizationSetBuilder()
+ .Authorization(TAG_NONCE, nonce.data(), nonce.size())
+ .BlockMode(BlockMode::CTR)
+ .Padding(PaddingMode::NONE);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
+ EXPECT_EQ(expected_ciphertext, ciphertext);
+}
+
+void KeyMintAidlTestBase::CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+ PaddingMode padding_mode, const string& key,
+ const string& iv, const string& input,
+ const string& expected_output) {
+ auto authset = AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(key.size() * 7)
+ .BlockMode(block_mode)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(padding_mode);
+ if (iv.size()) authset.Authorization(TAG_CALLER_NONCE);
+ ASSERT_EQ(ErrorCode::OK, ImportKey(authset, KeyFormat::RAW, key));
+ ASSERT_GT(key_blob_.size(), 0U);
+
+ auto begin_params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
+ if (iv.size()) begin_params.Authorization(TAG_NONCE, iv.data(), iv.size());
+ AuthorizationSet output_params;
+ string output = ProcessMessage(key_blob_, purpose, input, begin_params, &output_params);
+ EXPECT_EQ(expected_output, output);
+}
+
+void KeyMintAidlTestBase::VerifyMessage(const vector<uint8_t>& key_blob, const string& message,
+ const string& signature, const AuthorizationSet& params) {
+ SCOPED_TRACE("VerifyMessage");
+ AuthorizationSet begin_out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params));
+
+ string output;
+ AuthorizationSet update_params;
+ AuthorizationSet update_out_params;
+ int32_t consumed;
+ ASSERT_EQ(ErrorCode::OK,
+ Update(update_params, message, &update_out_params, &output, &consumed));
+ EXPECT_TRUE(output.empty());
+ EXPECT_GT(consumed, 0U);
+
+ string unused;
+ AuthorizationSet finish_params;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK, Finish(finish_params, message.substr(consumed), signature,
+ &finish_out_params, &output));
+ op_.clear();
+ EXPECT_TRUE(output.empty());
+}
+
+void KeyMintAidlTestBase::VerifyMessage(const string& message, const string& signature,
+ const AuthorizationSet& params) {
+ SCOPED_TRACE("VerifyMessage");
+ VerifyMessage(key_blob_, message, signature, params);
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& in_params,
+ AuthorizationSet* out_params) {
+ SCOPED_TRACE("EncryptMessage");
+ return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, const AuthorizationSet& params,
+ AuthorizationSet* out_params) {
+ SCOPED_TRACE("EncryptMessage");
+ return EncryptMessage(key_blob_, message, params, out_params);
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, const AuthorizationSet& params) {
+ SCOPED_TRACE("EncryptMessage");
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+ return ciphertext;
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+ return ciphertext;
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding, vector<uint8_t>* iv_out) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ EXPECT_EQ(1U, out_params.size());
+ auto ivVal = out_params.GetTagValue(TAG_NONCE);
+ EXPECT_TRUE(ivVal.isOk());
+ if (ivVal.isOk()) *iv_out = ivVal.value();
+ return ciphertext;
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding, const vector<uint8_t>& iv_in) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(padding)
+ .Authorization(TAG_NONCE, iv_in);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ return ciphertext;
+}
+
+string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding, uint8_t mac_length_bits,
+ const vector<uint8_t>& iv_in) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(padding)
+ .Authorization(TAG_MAC_LENGTH, mac_length_bits)
+ .Authorization(TAG_NONCE, iv_in);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ return ciphertext;
+}
+
+string KeyMintAidlTestBase::DecryptMessage(const vector<uint8_t>& key_blob,
+ const string& ciphertext,
+ const AuthorizationSet& params) {
+ SCOPED_TRACE("DecryptMessage");
+ AuthorizationSet out_params;
+ string plaintext =
+ ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
+ EXPECT_TRUE(out_params.empty());
+ return plaintext;
+}
+
+string KeyMintAidlTestBase::DecryptMessage(const string& ciphertext,
+ const AuthorizationSet& params) {
+ SCOPED_TRACE("DecryptMessage");
+ return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+string KeyMintAidlTestBase::DecryptMessage(const string& ciphertext, BlockMode block_mode,
+ PaddingMode padding_mode, const vector<uint8_t>& iv) {
+ SCOPED_TRACE("DecryptMessage");
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(padding_mode)
+ .Authorization(TAG_NONCE, iv);
+ return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+std::pair<ErrorCode, vector<uint8_t>> KeyMintAidlTestBase::UpgradeKey(
+ const vector<uint8_t>& key_blob) {
+ std::pair<ErrorCode, vector<uint8_t>> retval;
+ vector<uint8_t> outKeyBlob;
+ Status result = keymint_->upgradeKey(key_blob, vector<KeyParameter>(), &outKeyBlob);
+ ErrorCode errorcode = GetReturnErrorCode(result);
+ retval = std::tie(errorcode, outKeyBlob);
+
+ return retval;
+}
+vector<uint32_t> KeyMintAidlTestBase::ValidKeySizes(Algorithm algorithm) {
+ switch (algorithm) {
+ case Algorithm::RSA:
+ switch (SecLevel()) {
+ case SecurityLevel::SOFTWARE:
+ case SecurityLevel::TRUSTED_ENVIRONMENT:
+ return {2048, 3072, 4096};
+ case SecurityLevel::STRONGBOX:
+ return {2048};
+ default:
+ ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
+ break;
+ }
+ break;
+ case Algorithm::EC:
+ switch (SecLevel()) {
+ case SecurityLevel::SOFTWARE:
+ case SecurityLevel::TRUSTED_ENVIRONMENT:
+ return {224, 256, 384, 521};
+ case SecurityLevel::STRONGBOX:
+ return {256};
+ default:
+ ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
+ break;
+ }
+ break;
+ case Algorithm::AES:
+ return {128, 256};
+ case Algorithm::TRIPLE_DES:
+ return {168};
+ case Algorithm::HMAC: {
+ vector<uint32_t> retval((512 - 64) / 8 + 1);
+ uint32_t size = 64 - 8;
+ std::generate(retval.begin(), retval.end(), [&]() { return (size += 8); });
+ return retval;
+ }
+ default:
+ ADD_FAILURE() << "Invalid Algorithm: " << algorithm;
+ return {};
+ }
+ ADD_FAILURE() << "Should be impossible to get here";
+ return {};
+}
+
+vector<uint32_t> KeyMintAidlTestBase::InvalidKeySizes(Algorithm algorithm) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ switch (algorithm) {
+ case Algorithm::RSA:
+ return {3072, 4096};
+ case Algorithm::EC:
+ return {224, 384, 521};
+ case Algorithm::AES:
+ return {192};
+ default:
+ return {};
+ }
+ }
+ return {};
+}
+
+vector<EcCurve> KeyMintAidlTestBase::ValidCurves() {
+ if (securityLevel_ == SecurityLevel::STRONGBOX) {
+ return {EcCurve::P_256};
+ } else {
+ return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+ }
+}
+
+vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
+ if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
+ CHECK(SecLevel() == SecurityLevel::STRONGBOX);
+ return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+}
+
+vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
+ switch (SecLevel()) {
+ case SecurityLevel::SOFTWARE:
+ case SecurityLevel::TRUSTED_ENVIRONMENT:
+ if (withNone) {
+ if (withMD5)
+ return {Digest::NONE, Digest::MD5, Digest::SHA1,
+ Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
+ Digest::SHA_2_512};
+ else
+ return {Digest::NONE, Digest::SHA1, Digest::SHA_2_224,
+ Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
+ } else {
+ if (withMD5)
+ return {Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
+ Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
+ else
+ return {Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
+ Digest::SHA_2_512};
+ }
+ break;
+ case SecurityLevel::STRONGBOX:
+ if (withNone)
+ return {Digest::NONE, Digest::SHA_2_256};
+ else
+ return {Digest::SHA_2_256};
+ break;
+ default:
+ ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
+ break;
+ }
+ ADD_FAILURE() << "Should be impossible to get here";
+ return {};
+}
+
+} // namespace test
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
new file mode 100644
index 0000000..2948c41
--- /dev/null
+++ b/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VTS_KEYMINT_AIDL_TEST_UTILS_H
+#define VTS_KEYMINT_AIDL_TEST_UTILS_H
+
+#pragma once
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android/hardware/keymint/ErrorCode.h>
+#include <android/hardware/keymint/IKeyMintDevice.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+
+#include <keymintSupport/authorization_set.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+namespace test {
+
+using ::android::sp;
+using binder::Status;
+using ::std::shared_ptr;
+using ::std::string;
+using ::std::vector;
+
+constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
+
+class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
+ public:
+ void SetUp() override;
+ void TearDown() override {
+ if (key_blob_.size()) {
+ CheckedDeleteKey();
+ }
+ AbortIfNeeded();
+ }
+
+ void InitializeKeyMint(sp<IKeyMintDevice> keyMint);
+ IKeyMintDevice& keyMint() { return *keymint_; }
+ uint32_t os_version() { return os_version_; }
+ uint32_t os_patch_level() { return os_patch_level_; }
+
+ ErrorCode GetReturnErrorCode(Status result);
+ ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
+ KeyCharacteristics* key_characteristics);
+
+ ErrorCode GenerateKey(const AuthorizationSet& key_desc);
+
+ ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+ const string& key_material, vector<uint8_t>* key_blob,
+ KeyCharacteristics* key_characteristics);
+ ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+ const string& key_material);
+
+ ErrorCode ImportWrappedKey(string wrapped_key, string wrapping_key,
+ const AuthorizationSet& wrapping_key_desc, string masking_key,
+ const AuthorizationSet& unwrapping_params);
+
+ ErrorCode DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
+ ErrorCode DeleteKey(bool keep_key_blob = false);
+
+ ErrorCode DeleteAllKeys();
+
+ void CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
+ void CheckedDeleteKey();
+
+ ErrorCode Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params,
+ sp<IKeyMintOperation>& op);
+ ErrorCode Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params);
+ ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params);
+ ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params);
+
+ ErrorCode Update(const AuthorizationSet& in_params, const string& input,
+ AuthorizationSet* out_params, string* output, int32_t* input_consumed);
+ ErrorCode Update(const string& input, string* out, int32_t* input_consumed);
+
+ ErrorCode Finish(const AuthorizationSet& in_params, const string& input,
+ const string& signature, AuthorizationSet* out_params, string* output);
+ ErrorCode Finish(const string& message, string* output);
+ ErrorCode Finish(const string& message, const string& signature, string* output);
+ ErrorCode Finish(string* output) { return Finish(string(), output); }
+
+ ErrorCode Abort();
+ ErrorCode Abort(const sp<IKeyMintOperation>& op);
+ void AbortIfNeeded();
+
+ string ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
+ const string& message, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params);
+
+ string SignMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& params);
+ string SignMessage(const string& message, const AuthorizationSet& params);
+
+ string MacMessage(const string& message, Digest digest, size_t mac_length);
+
+ void CheckHmacTestVector(const string& key, const string& message, Digest digest,
+ const string& expected_mac);
+
+ void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
+ const string& expected_ciphertext);
+
+ void CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+ PaddingMode padding_mode, const string& key, const string& iv,
+ const string& input, const string& expected_output);
+
+ void VerifyMessage(const vector<uint8_t>& key_blob, const string& message,
+ const string& signature, const AuthorizationSet& params);
+ void VerifyMessage(const string& message, const string& signature,
+ const AuthorizationSet& params);
+
+ string EncryptMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params);
+ string EncryptMessage(const string& message, const AuthorizationSet& params,
+ AuthorizationSet* out_params);
+ string EncryptMessage(const string& message, const AuthorizationSet& params);
+ string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding);
+ string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+ vector<uint8_t>* iv_out);
+ string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+ const vector<uint8_t>& iv_in);
+ string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+ uint8_t mac_length_bits, const vector<uint8_t>& iv_in);
+
+ string DecryptMessage(const vector<uint8_t>& key_blob, const string& ciphertext,
+ const AuthorizationSet& params);
+ string DecryptMessage(const string& ciphertext, const AuthorizationSet& params);
+ string DecryptMessage(const string& ciphertext, BlockMode block_mode, PaddingMode padding_mode,
+ const vector<uint8_t>& iv);
+
+ std::pair<ErrorCode, vector<uint8_t>> UpgradeKey(const vector<uint8_t>& key_blob);
+
+ bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
+ SecurityLevel SecLevel() { return securityLevel_; }
+
+ vector<uint32_t> ValidKeySizes(Algorithm algorithm);
+ vector<uint32_t> InvalidKeySizes(Algorithm algorithm);
+
+ vector<EcCurve> ValidCurves();
+ vector<EcCurve> InvalidCurves();
+
+ vector<Digest> ValidDigests(bool withNone, bool withMD5);
+
+ static vector<string> build_params() {
+ auto params = android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+ return params;
+ }
+
+ sp<IKeyMintOperation> op_;
+ vector<Certificate> certChain_;
+ vector<uint8_t> key_blob_;
+ KeyCharacteristics key_characteristics_;
+
+ private:
+ sp<IKeyMintDevice> keymint_;
+ uint32_t os_version_;
+ uint32_t os_patch_level_;
+
+ SecurityLevel securityLevel_;
+ string name_;
+ string author_;
+ long challenge_;
+};
+
+#define INSTANTIATE_KEYMINT_AIDL_TEST(name) \
+ INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
+ testing::ValuesIn(KeyMintAidlTestBase::build_params()), \
+ android::PrintInstanceNameToString)
+
+} // namespace test
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+#endif // VTS_KEYMINT_AIDL_TEST_UTILS_H
diff --git a/keymint/aidl/vts/functional/VerificationTokenTest.cpp b/keymint/aidl/vts/functional/VerificationTokenTest.cpp
new file mode 100644
index 0000000..bd0942b
--- /dev/null
+++ b/keymint/aidl/vts/functional/VerificationTokenTest.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "KeyMintAidlTestBase.h"
+
+namespace android {
+namespace hardware {
+namespace keymint {
+namespace test {
+
+class VerificationTokenTest : public KeyMintAidlTestBase {
+ protected:
+ struct VerifyAuthorizationResult {
+ ErrorCode error;
+ VerificationToken token;
+ };
+
+ VerifyAuthorizationResult verifyAuthorization(uint64_t operationHandle,
+ const HardwareAuthToken& authToken) {
+ VerifyAuthorizationResult result;
+
+ Status err;
+ err = keyMint().verifyAuthorization(operationHandle, //
+ authToken, //
+ &result.token);
+
+ result.error = GetReturnErrorCode(err);
+ return result;
+ }
+
+ uint64_t getTime() {
+ struct timespec timespec;
+ EXPECT_EQ(0, clock_gettime(CLOCK_BOOTTIME, ×pec));
+ return timespec.tv_sec * 1000 + timespec.tv_nsec / 1000000;
+ }
+
+ int sleep_ms(uint32_t milliseconds) {
+ struct timespec sleep_time = {static_cast<time_t>(milliseconds / 1000),
+ static_cast<long>(milliseconds % 1000) * 1000000};
+ while (sleep_time.tv_sec || sleep_time.tv_nsec) {
+ if (nanosleep(&sleep_time /* to wait */,
+ &sleep_time /* remaining (on interrruption) */) == 0) {
+ sleep_time = {};
+ } else {
+ if (errno != EINTR) return errno;
+ }
+ }
+ return 0;
+ }
+};
+
+/*
+ * VerificationTokens exist to facilitate cross-KeyMint verification of requirements. As
+ * such, the precise capabilities required will vary depending on the specific vendor
+ * implementations. Essentially, VerificationTokens are a "hook" to enable vendor
+ * implementations to communicate, so the precise usage is defined by those vendors. The only
+ * thing we really can test is that tokens can be created by TEE keyMints, and that the
+ * timestamps increase as expected.
+ */
+TEST_P(VerificationTokenTest, TestCreation) {
+ auto result1 = verifyAuthorization(1 /* operation handle */, HardwareAuthToken());
+ auto result1_time = getTime();
+
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ // StrongBox should not implement verifyAuthorization.
+ EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
+ return;
+ }
+
+ ASSERT_EQ(ErrorCode::OK, result1.error);
+ EXPECT_EQ(1U, result1.token.challenge);
+ EXPECT_EQ(SecLevel(), result1.token.securityLevel);
+ EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+
+ constexpr uint32_t time_to_sleep = 200;
+ sleep_ms(time_to_sleep);
+
+ auto result2 = verifyAuthorization(2 /* operation handle */, HardwareAuthToken());
+
+ auto result2_time = getTime();
+ ASSERT_EQ(ErrorCode::OK, result2.error);
+ EXPECT_EQ(2U, result2.token.challenge);
+ EXPECT_EQ(SecLevel(), result2.token.securityLevel);
+
+ auto host_time_delta = result2_time - result1_time;
+
+ EXPECT_GE(host_time_delta, time_to_sleep)
+ << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
+ EXPECT_LE(host_time_delta, time_to_sleep + 20)
+ << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
+ << " ms? That's awful!";
+
+ auto km_time_delta =
+ result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
+
+ // If not too much else is going on on the system, the time delta should be quite close. Allow
+ // 2 ms of slop just to avoid test flakiness.
+ //
+ // TODO(swillden): see if we can output values so they can be gathered across many runs and
+ // report if times aren't nearly always <1ms apart.
+ EXPECT_LE(host_time_delta, km_time_delta + 2);
+ EXPECT_LE(km_time_delta, host_time_delta + 2);
+ ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
+ ASSERT_NE(0,
+ memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
+}
+
+/*
+ * Test that the mac changes when the time stamp changes. This is does not guarantee that the time
+ * stamp is included in the mac but on failure we know that it is not. Other than in the test
+ * case above we call verifyAuthorization with the exact same set of parameters.
+ */
+TEST_P(VerificationTokenTest, MacChangesOnChangingTimestamp) {
+ auto result1 = verifyAuthorization(0 /* operation handle */, HardwareAuthToken());
+ auto result1_time = getTime();
+
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ // StrongBox should not implement verifyAuthorization.
+ EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
+ return;
+ }
+
+ EXPECT_EQ(ErrorCode::OK, result1.error);
+ EXPECT_EQ(0U, result1.token.challenge);
+ EXPECT_EQ(SecLevel(), result1.token.securityLevel);
+ EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+
+ constexpr uint32_t time_to_sleep = 200;
+ sleep_ms(time_to_sleep);
+
+ auto result2 = verifyAuthorization(0 /* operation handle */, HardwareAuthToken());
+ // ASSERT_TRUE(result2.callSuccessful);
+ auto result2_time = getTime();
+ EXPECT_EQ(ErrorCode::OK, result2.error);
+ EXPECT_EQ(0U, result2.token.challenge);
+ EXPECT_EQ(SecLevel(), result2.token.securityLevel);
+
+ auto host_time_delta = result2_time - result1_time;
+
+ EXPECT_GE(host_time_delta, time_to_sleep)
+ << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
+ EXPECT_LE(host_time_delta, time_to_sleep + 20)
+ << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
+ << " ms? That's awful!";
+
+ auto km_time_delta =
+ result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
+
+ EXPECT_LE(host_time_delta, km_time_delta + 2);
+ EXPECT_LE(km_time_delta, host_time_delta + 2);
+ ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
+ ASSERT_NE(0,
+ memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(VerificationTokenTest);
+
+} // namespace test
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/aidl/vts/functional/keyMint1Test.cpp b/keymint/aidl/vts/functional/keyMint1Test.cpp
new file mode 100644
index 0000000..c2fa2f8
--- /dev/null
+++ b/keymint/aidl/vts/functional/keyMint1Test.cpp
@@ -0,0 +1,4069 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keymint_5_test"
+#include <cutils/log.h>
+
+#include <signal.h>
+#include <iostream>
+
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+#include <cutils/properties.h>
+
+#include <android/hardware/keymint/KeyFormat.h>
+
+#include <keymintSupport/attestation_record.h>
+#include <keymintSupport/key_param_output.h>
+#include <keymintSupport/openssl_utils.h>
+
+#include "KeyMintAidlTestBase.h"
+
+static bool arm_deleteAllKeys = false;
+static bool dump_Attestations = false;
+
+using android::hardware::keymint::AuthorizationSet;
+using android::hardware::keymint::KeyCharacteristics;
+using android::hardware::keymint::KeyFormat;
+
+namespace android {
+namespace hardware {
+
+namespace keymint {
+
+bool operator==(const keymint::AuthorizationSet& a, const keymint::AuthorizationSet& b) {
+ return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
+}
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+namespace std {
+
+using namespace android::hardware::keymint;
+
+template <>
+struct std::equal_to<KeyCharacteristics> {
+ bool operator()(const KeyCharacteristics& a, const KeyCharacteristics& b) const {
+ // This isn't very efficient. Oh, well.
+ AuthorizationSet a_sw(a.softwareEnforced);
+ AuthorizationSet b_sw(b.softwareEnforced);
+ AuthorizationSet a_tee(b.hardwareEnforced);
+ AuthorizationSet b_tee(b.hardwareEnforced);
+
+ a_sw.Sort();
+ b_sw.Sort();
+ a_tee.Sort();
+ b_tee.Sort();
+
+ return ((a_sw == b_sw) && (a_tee == b_tee));
+ }
+};
+
+} // namespace std
+
+namespace android {
+namespace hardware {
+namespace keymint {
+namespace test {
+namespace {
+
+template <TagType tag_type, Tag tag, typename ValueT>
+bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
+ auto it = std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
+ return param.tag == tag && accessTagValue(ttag, param) == expected_value;
+ });
+ return (it != set.end());
+}
+
+template <TagType tag_type, Tag tag>
+bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag>) {
+ auto it = std::find_if(set.begin(), set.end(),
+ [&](const KeyParameter& param) { return param.tag == tag; });
+ return (it != set.end());
+}
+
+constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+string hex2str(string a) {
+ string b;
+ size_t num = a.size() / 2;
+ b.resize(num);
+ for (size_t i = 0; i < num; i++) {
+ b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+ }
+ return b;
+}
+
+string rsa_key =
+ hex2str("30820275020100300d06092a864886f70d01010105000482025f3082025b"
+ "02010002818100c6095409047d8634812d5a218176e45c41d60a75b13901"
+ "f234226cffe776521c5a77b9e389417b71c0b6a44d13afe4e4a2805d46c9"
+ "da2935adb1ff0c1f24ea06e62b20d776430a4d435157233c6f916783c30e"
+ "310fcbd89b85c2d56771169785ac12bca244abda72bfb19fc44d27c81e1d"
+ "92de284f4061edfd99280745ea6d2502030100010281801be0f04d9cae37"
+ "18691f035338308e91564b55899ffb5084d2460e6630257e05b3ceab0297"
+ "2dfabcd6ce5f6ee2589eb67911ed0fac16e43a444b8c861e544a05933657"
+ "72f8baf6b22fc9e3c5f1024b063ac080a7b2234cf8aee8f6c47bbf4fd3ac"
+ "e7240290bef16c0b3f7f3cdd64ce3ab5912cf6e32f39ab188358afcccd80"
+ "81024100e4b49ef50f765d3b24dde01aceaaf130f2c76670a91a61ae08af"
+ "497b4a82be6dee8fcdd5e3f7ba1cfb1f0c926b88f88c92bfab137fba2285"
+ "227b83c342ff7c55024100ddabb5839c4c7f6bf3d4183231f005b31aa58a"
+ "ffdda5c79e4cce217f6bc930dbe563d480706c24e9ebfcab28a6cdefd324"
+ "b77e1bf7251b709092c24ff501fd91024023d4340eda3445d8cd26c14411"
+ "da6fdca63c1ccd4b80a98ad52b78cc8ad8beb2842c1d280405bc2f6c1bea"
+ "214a1d742ab996b35b63a82a5e470fa88dbf823cdd02401b7b57449ad30d"
+ "1518249a5f56bb98294d4b6ac12ffc86940497a5a5837a6cf946262b4945"
+ "26d328c11e1126380fde04c24f916dec250892db09a6d77cdba351024077"
+ "62cd8f4d050da56bd591adb515d24d7ccd32cca0d05f866d583514bd7324"
+ "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
+ "3492d6");
+
+string ec_256_key =
+ hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
+ "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
+ "99986481f3a4d859a14403420004bf85d7720d07c25461683bc648b4778a"
+ "9a14dd8a024e3bdd8c7ddd9ab2b528bbc7aa1b51f14ebbbb0bd0ce21bcc4"
+ "1c6eb00083cf3376d11fd44949e0b2183bfe");
+
+string ec_521_key =
+ hex2str("3081EE020100301006072A8648CE3D020106052B810400230481D63081D3"
+ "02010104420011458C586DB5DAA92AFAB03F4FE46AA9D9C3CE9A9B7A006A"
+ "8384BEC4C78E8E9D18D7D08B5BCFA0E53C75B064AD51C449BAE0258D54B9"
+ "4B1E885DED08ED4FB25CE9A1818903818600040149EC11C6DF0FA122C6A9"
+ "AFD9754A4FA9513A627CA329E349535A5629875A8ADFBE27DCB932C05198"
+ "6377108D054C28C6F39B6F2C9AF81802F9F326B842FF2E5F3C00AB7635CF"
+ "B36157FC0882D574A10D839C1A0C049DC5E0D775E2EE50671A208431BB45"
+ "E78E70BEFE930DB34818EE4D5C26259F5C6B8E28A652950F9F88D7B4B2C9"
+ "D9");
+
+string ec_256_key_rfc5915 =
+ hex2str("308193020100301306072a8648ce3d020106082a8648ce3d030107047930"
+ "770201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3"
+ "8e8d21c9fa750c1da00a06082a8648ce3d030107a14403420004e2cc561e"
+ "e701da0ad0ef0d176bb0c919d42e79c393fdc1bd6c4010d85cf2cf8e68c9"
+ "05464666f98dad4f01573ba81078b3428570a439ba3229fbc026c550682f");
+
+string ec_256_key_sec1 =
+ hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
+ "6b0201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3"
+ "8e8d21c9fa750c1da14403420004e2cc561ee701da0ad0ef0d176bb0c919"
+ "d42e79c393fdc1bd6c4010d85cf2cf8e68c905464666f98dad4f01573ba8"
+ "1078b3428570a439ba3229fbc026c550682f");
+
+struct RSA_Delete {
+ void operator()(RSA* p) { RSA_free(p); }
+};
+
+/* TODO(seleneh) add attestation verification codes like verify_chain() and
+ * attestation tests after we decided on the keymint 1 attestation changes.
+ */
+
+std::string make_string(const uint8_t* data, size_t length) {
+ return std::string(reinterpret_cast<const char*>(data), length);
+}
+
+template <size_t N>
+std::string make_string(const uint8_t (&a)[N]) {
+ return make_string(a, N);
+}
+
+class AidlBuf : public vector<uint8_t> {
+ typedef vector<uint8_t> super;
+
+ public:
+ AidlBuf() {}
+ AidlBuf(const super& other) : super(other) {}
+ AidlBuf(super&& other) : super(std::move(other)) {}
+ explicit AidlBuf(const std::string& other) : AidlBuf() { *this = other; }
+
+ AidlBuf& operator=(const super& other) {
+ super::operator=(other);
+ return *this;
+ }
+
+ AidlBuf& operator=(super&& other) {
+ super::operator=(std::move(other));
+ return *this;
+ }
+
+ AidlBuf& operator=(const string& other) {
+ resize(other.size());
+ for (size_t i = 0; i < other.size(); ++i) {
+ (*this)[i] = static_cast<uint8_t>(other[i]);
+ }
+ return *this;
+ }
+
+ string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+} // namespace
+
+class NewKeyGenerationTest : public KeyMintAidlTestBase {
+ protected:
+ void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
+ // TODO(swillden): Distinguish which params should be in which auth list.
+
+ AuthorizationSet auths(keyCharacteristics.hardwareEnforced);
+ auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced));
+
+ EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+ EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
+ EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY));
+
+ // Verify that App ID, App data and ROT are NOT included.
+ EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
+ EXPECT_FALSE(auths.Contains(TAG_APPLICATION_ID));
+ EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA));
+
+ // Check that some unexpected tags/values are NOT present.
+ EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::ENCRYPT));
+ EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT));
+ EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U));
+
+ // Now check that unspecified, defaulted tags are correct.
+ EXPECT_TRUE(auths.Contains(TAG_CREATION_DATETIME));
+
+ EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
+ << "OS version is " << os_version() << " key reported "
+ << auths.GetTagValue(TAG_OS_VERSION);
+ EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
+ << "OS patch level is " << os_patch_level() << " key reported "
+ << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ }
+};
+
+/*
+ * NewKeyGenerationTest.Rsa
+ *
+ * Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
+ * have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, Rsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ vector<uint8_t> key_blob;
+ KeyCharacteristics key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params;
+ if (IsSecure()) {
+ crypto_params = key_characteristics.hardwareEnforced;
+ } else {
+ crypto_params = key_characteristics.softwareEnforced;
+ }
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.NoInvalidRsaSizes
+ *
+ * Verifies that keymint cannot generate any RSA key sizes that are designated as invalid.
+ */
+TEST_P(NewKeyGenerationTest, NoInvalidRsaSizes) {
+ for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
+ vector<uint8_t> key_blob;
+ KeyCharacteristics key_characteristics;
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
+ &key_blob, &key_characteristics));
+ }
+}
+
+/*
+ * NewKeyGenerationTest.RsaNoDefaultSize
+ *
+ * Verifies that failing to specify a key size for RSA key generation returns
+ * UNSUPPORTED_KEY_SIZE.
+ */
+TEST_P(NewKeyGenerationTest, RsaNoDefaultSize) {
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_ALGORITHM, Algorithm::RSA)
+ .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3U)
+ .SigningKey()));
+}
+
+/*
+ * NewKeyGenerationTest.Ecdsa
+ *
+ * Verifies that keymint can generate all required EC key sizes, and that the resulting keys
+ * have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, Ecdsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ KeyCharacteristics key_characteristics;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(
+ AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
+ &key_blob, &key_characteristics));
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params;
+ if (IsSecure()) {
+ crypto_params = key_characteristics.hardwareEnforced;
+ } else {
+ crypto_params = key_characteristics.softwareEnforced;
+ }
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaDefaultSize
+ *
+ * Verifies that failing to specify a key size for EC key generation returns
+ * UNSUPPORTED_KEY_SIZE.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) {
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .SigningKey()
+ .Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaInvalidSize
+ *
+ * Verifies that specifying an invalid key size for EC key generation returns
+ * UNSUPPORTED_KEY_SIZE.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
+ for (auto key_size : InvalidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ KeyCharacteristics key_characteristics;
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(
+ AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
+ &key_blob, &key_characteristics));
+ }
+
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaMismatchKeySize
+ *
+ * Verifies that specifying mismatched key size and curve for EC key generation returns
+ * INVALID_ARGUMENT.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::INVALID_ARGUMENT,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(224)
+ .Authorization(TAG_EC_CURVE, EcCurve::P_256)
+ .Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAllValidSizes
+ *
+ * Verifies that keymint supports all required EC key sizes.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAllValidSizes) {
+ auto valid_sizes = ValidKeySizes(Algorithm::EC);
+ for (size_t size : valid_sizes) {
+ EXPECT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(size).Digest(Digest::NONE)))
+ << "Failed to generate size: " << size;
+ CheckedDeleteKey();
+ }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaInvalidCurves
+ *
+ * Verifies that keymint does not support any curve designated as unsupported.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAllValidCurves) {
+ Digest digest;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ digest = Digest::SHA_2_256;
+ } else {
+ digest = Digest::SHA_2_512;
+ }
+ for (auto curve : ValidCurves()) {
+ EXPECT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(curve).Digest(digest)))
+ << "Failed to generate key on curve: " << curve;
+ CheckedDeleteKey();
+ }
+}
+
+/*
+ * NewKeyGenerationTest.Hmac
+ *
+ * Verifies that keymint supports all required digests, and that the resulting keys have correct
+ * characteristics.
+ */
+TEST_P(NewKeyGenerationTest, Hmac) {
+ for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+ vector<uint8_t> key_blob;
+ KeyCharacteristics key_characteristics;
+ constexpr size_t key_size = 128;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(
+ AuthorizationSetBuilder().HmacKey(key_size).Digest(digest).Authorization(
+ TAG_MIN_MAC_LENGTH, 128),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet hardwareEnforced = key_characteristics.hardwareEnforced;
+ AuthorizationSet softwareEnforced = key_characteristics.softwareEnforced;
+ if (IsSecure()) {
+ EXPECT_TRUE(hardwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+ EXPECT_TRUE(hardwareEnforced.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ } else {
+ EXPECT_TRUE(softwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+ EXPECT_TRUE(softwareEnforced.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ }
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.HmacCheckKeySizes
+ *
+ * Verifies that keymint supports all key sizes, and rejects all invalid key sizes.
+ */
+TEST_P(NewKeyGenerationTest, HmacCheckKeySizes) {
+ for (size_t key_size = 0; key_size <= 512; ++key_size) {
+ if (key_size < 64 || key_size % 8 != 0) {
+ // To keep this test from being very slow, we only test a random fraction of
+ // non-byte key sizes. We test only ~10% of such cases. Since there are 392 of
+ // them, we expect to run ~40 of them in each run.
+ if (key_size % 8 == 0 || random() % 10 == 0) {
+ EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+ << "HMAC key size " << key_size << " invalid";
+ }
+ } else {
+ EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+ << "Failed to generate HMAC key of size " << key_size;
+ CheckedDeleteKey();
+ }
+ }
+}
+
+/*
+ * NewKeyGenerationTest.HmacCheckMinMacLengths
+ *
+ * Verifies that keymint supports all required MAC lengths and rejects all invalid lengths. This
+ * test is probabilistic in order to keep the runtime down, but any failure prints out the
+ * specific MAC length that failed, so reproducing a failed run will be easy.
+ */
+TEST_P(NewKeyGenerationTest, HmacCheckMinMacLengths) {
+ for (size_t min_mac_length = 0; min_mac_length <= 256; ++min_mac_length) {
+ if (min_mac_length < 64 || min_mac_length % 8 != 0) {
+ // To keep this test from being very long, we only test a random fraction of
+ // non-byte lengths. We test only ~10% of such cases. Since there are 172 of them,
+ // we expect to run ~17 of them in each run.
+ if (min_mac_length % 8 == 0 || random() % 10 == 0) {
+ EXPECT_EQ(ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length)))
+ << "HMAC min mac length " << min_mac_length << " invalid.";
+ }
+ } else {
+ EXPECT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length)))
+ << "Failed to generate HMAC key with min MAC length " << min_mac_length;
+ CheckedDeleteKey();
+ }
+ }
+}
+
+/*
+ * NewKeyGenerationTest.HmacMultipleDigests
+ *
+ * Verifies that keymint rejects HMAC key generation with multiple specified digest algorithms.
+ */
+TEST_P(NewKeyGenerationTest, HmacMultipleDigests) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Digest(Digest::SHA1)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+}
+
+/*
+ * NewKeyGenerationTest.HmacDigestNone
+ *
+ * Verifies that keymint rejects HMAC key generation with no digest or Digest::NONE
+ */
+TEST_P(NewKeyGenerationTest, HmacDigestNone) {
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+ GenerateKey(AuthorizationSetBuilder().HmacKey(128).Authorization(TAG_MIN_MAC_LENGTH,
+ 128)));
+
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(NewKeyGenerationTest);
+
+typedef KeyMintAidlTestBase SigningOperationsTest;
+
+/*
+ * SigningOperationsTest.RsaSuccess
+ *
+ * Verifies that raw RSA signature operations succeed.
+ */
+TEST_P(SigningOperationsTest, RsaSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)));
+ string message = "12345678901234567890123456789012";
+ string signature = SignMessage(
+ message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * SigningOperationsTest.RsaUseRequiresCorrectAppIdAppData
+ *
+ * Verifies that using an RSA key requires the correct app ID/data.
+ */
+TEST_P(SigningOperationsTest, RsaUseRequiresCorrectAppIdAppData) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_APPLICATION_ID, "clientid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata")));
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_APPLICATION_ID, "clientid")));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_APPLICATION_DATA, "appdata")));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_APPLICATION_DATA, "appdata")
+ .Authorization(TAG_APPLICATION_ID, "clientid")));
+ AbortIfNeeded();
+}
+
+/*
+ * SigningOperationsTest.RsaPssSha256Success
+ *
+ * Verifies that RSA-PSS signature operations succeed.
+ */
+TEST_P(SigningOperationsTest, RsaPssSha256Success) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PSS)
+ .Authorization(TAG_NO_AUTH_REQUIRED)));
+ // Use large message, which won't work without digesting.
+ string message(1024, 'a');
+ string signature = SignMessage(
+ message,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS));
+}
+
+/*
+ * SigningOperationsTest.RsaPaddingNoneDoesNotAllowOther
+ *
+ * Verifies that keymint rejects signature operations that specify a padding mode when the key
+ * supports only unpadded operations.
+ */
+TEST_P(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+ string message = "12345678901234567890123456789012";
+ string signature;
+
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+}
+
+/*
+ * SigningOperationsTest.NoUserConfirmation
+ *
+ * Verifies that keymint rejects signing operations for keys with
+ * TRUSTED_CONFIRMATION_REQUIRED and no valid confirmation token
+ * presented.
+ */
+TEST_P(SigningOperationsTest, NoUserConfirmation) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(1024, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)));
+
+ const string message = "12345678901234567890123456789012";
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+ string signature;
+ EXPECT_EQ(ErrorCode::NO_USER_CONFIRMATION, Finish(message, &signature));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1Sha256Success
+ *
+ * Verifies that digested RSA-PKCS1 signature operations succeed.
+ */
+TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ string message(1024, 'a');
+ string signature = SignMessage(message, AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1NoDigestSuccess
+ *
+ * Verifies that undigested RSA-PKCS1 signature operations succeed.
+ */
+TEST_P(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ string message(53, 'a');
+ string signature = SignMessage(message, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1NoDigestTooLarge
+ *
+ * Verifies that undigested RSA-PKCS1 signature operations fail with the correct error code when
+ * given a too-long message.
+ */
+TEST_P(SigningOperationsTest, RsaPkcs1NoDigestTooLong) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ string message(257, 'a');
+
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ string signature;
+ EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &signature));
+}
+
+/*
+ * SigningOperationsTest.RsaPssSha512TooSmallKey
+ *
+ * Verifies that undigested RSA-PSS signature operations fail with the correct error code when
+ * used with a key that is too small for the message.
+ *
+ * A PSS-padded message is of length salt_size + digest_size + 16 (sizes in bits), and the
+ * keymint specification requires that salt_size == digest_size, so the message will be
+ * digest_size * 2 +
+ * 16. Such a message can only be signed by a given key if the key is at least that size. This
+ * test uses SHA512, which has a digest_size == 512, so the message size is 1040 bits, too large
+ * for a 1024-bit key.
+ */
+TEST_P(SigningOperationsTest, RsaPssSha512TooSmallKey) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(1024, 65537)
+ .Digest(Digest::SHA_2_512)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::RSA_PSS)));
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_DIGEST,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_512)
+ .Padding(PaddingMode::RSA_PSS)));
+}
+
+/*
+ * SigningOperationsTest.RsaNoPaddingTooLong
+ *
+ * Verifies that raw RSA signature operations fail with the correct error code when
+ * given a too-long message.
+ */
+TEST_P(SigningOperationsTest, RsaNoPaddingTooLong) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ // One byte too long
+ string message(2048 / 8 + 1, 'a');
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ string result;
+ ErrorCode finish_error_code = Finish(message, &result);
+ EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+ finish_error_code == ErrorCode::INVALID_ARGUMENT);
+
+ // Very large message that should exceed the transfer buffer size of any reasonable TEE.
+ message = string(128 * 1024, 'a');
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+ finish_error_code = Finish(message, &result);
+ EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+ finish_error_code == ErrorCode::INVALID_ARGUMENT);
+}
+
+/*
+ * SigningOperationsTest.RsaAbort
+ *
+ * Verifies that operations can be aborted correctly. Uses an RSA signing operation for the
+ * test, but the behavior should be algorithm and purpose-independent.
+ */
+TEST_P(SigningOperationsTest, RsaAbort) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+ EXPECT_EQ(ErrorCode::OK, Abort());
+
+ // Another abort should fail
+ EXPECT_EQ(ErrorCode::INVALID_OPERATION_HANDLE, Abort());
+
+ // Set to sentinel, so TearDown() doesn't try to abort again.
+ op_.clear();
+}
+
+/*
+ * SigningOperationsTest.RsaUnsupportedPadding
+ *
+ * Verifies that RSA operations fail with the correct error (but key gen succeeds) when used
+ * with a padding mode inappropriate for RSA.
+ */
+TEST_P(SigningOperationsTest, RsaUnsupportedPadding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Digest(Digest::SHA_2_256 /* supported digest */)
+ .Padding(PaddingMode::PKCS7)));
+ ASSERT_EQ(
+ ErrorCode::UNSUPPORTED_PADDING_MODE,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::PKCS7)));
+}
+
+/*
+ * SigningOperationsTest.RsaPssNoDigest
+ *
+ * Verifies that RSA PSS operations fail when no digest is used. PSS requires a digest.
+ */
+TEST_P(SigningOperationsTest, RsaNoDigest) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::RSA_PSS)));
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_DIGEST,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::RSA_PSS)));
+
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Padding(PaddingMode::RSA_PSS)));
+}
+
+/*
+ * SigningOperationsTest.RsaPssNoDigest
+ *
+ * Verifies that RSA operations fail when no padding mode is specified. PaddingMode::NONE is
+ * supported in some cases (as validated in other tests), but a mode must be specified.
+ */
+TEST_P(SigningOperationsTest, RsaNoPadding) {
+ // Padding must be specified
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SigningKey()
+ .Digest(Digest::NONE)));
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_PADDING_MODE,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE)));
+}
+
+/*
+ * SigningOperationsTest.RsaShortMessage
+ *
+ * Verifies that raw RSA signatures succeed with a message shorter than the key size.
+ */
+TEST_P(SigningOperationsTest, RsaTooShortMessage) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)));
+
+ // Barely shorter
+ string message(2048 / 8 - 1, 'a');
+ SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+
+ // Much shorter
+ message = "a";
+ SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * SigningOperationsTest.RsaSignWithEncryptionKey
+ *
+ * Verifies that RSA encryption keys cannot be used to sign.
+ */
+TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)));
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+}
+
+/*
+ * SigningOperationsTest.RsaSignTooLargeMessage
+ *
+ * Verifies that attempting a raw signature of a message which is the same length as the key,
+ * but numerically larger than the public modulus, fails with the correct error.
+ */
+TEST_P(SigningOperationsTest, RsaSignTooLargeMessage) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)));
+
+ // Largest possible message will always be larger than the public modulus.
+ string message(2048 / 8, static_cast<char>(0xff));
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)));
+ string signature;
+ ASSERT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &signature));
+}
+
+/*
+ * SigningOperationsTest.EcdsaAllSizesAndHashes
+ *
+ * Verifies that ECDSA operations succeed with all possible key sizes and hashes.
+ */
+TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) {
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(key_size)
+ .Digest(digest));
+ EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with size " << key_size
+ << " and digest " << digest;
+ if (error != ErrorCode::OK) continue;
+
+ string message(1024, 'a');
+ if (digest == Digest::NONE) message.resize(key_size / 8);
+ SignMessage(message, AuthorizationSetBuilder().Digest(digest));
+ CheckedDeleteKey();
+ }
+ }
+}
+
+/*
+ * SigningOperationsTest.EcdsaAllCurves
+ *
+ * Verifies that ECDSA operations succeed with all possible curves.
+ */
+TEST_P(SigningOperationsTest, EcdsaAllCurves) {
+ for (auto curve : ValidCurves()) {
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::SHA_2_256));
+ EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+ if (error != ErrorCode::OK) continue;
+
+ string message(1024, 'a');
+ SignMessage(message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+ CheckedDeleteKey();
+ }
+}
+
+/*
+ * SigningOperationsTest.EcdsaNoDigestHugeData
+ *
+ * Verifies that ECDSA operations support very large messages, even without digesting. This
+ * should work because ECDSA actually only signs the leftmost L_n bits of the message, however
+ * large it may be. Not using digesting is a bad idea, but in some cases digesting is done by
+ * the framework.
+ */
+TEST_P(SigningOperationsTest, EcdsaNoDigestHugeData) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::NONE)));
+ string message(1 * 1024, 'a');
+ SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE));
+}
+
+/*
+ * SigningOperationsTest.EcUseRequiresCorrectAppIdAppData
+ *
+ * Verifies that using an EC key requires the correct app ID/data.
+ */
+TEST_P(SigningOperationsTest, EcUseRequiresCorrectAppIdAppData) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_APPLICATION_ID, "clientid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata")));
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE)));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Authorization(TAG_APPLICATION_ID, "clientid")));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Authorization(TAG_APPLICATION_DATA, "appdata")));
+ AbortIfNeeded();
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+ .Digest(Digest::NONE)
+ .Authorization(TAG_APPLICATION_DATA, "appdata")
+ .Authorization(TAG_APPLICATION_ID, "clientid")));
+ AbortIfNeeded();
+}
+
+/*
+ * SigningOperationsTest.AesEcbSign
+ *
+ * Verifies that attempts to use AES keys to sign fail in the correct way.
+ */
+TEST_P(SigningOperationsTest, AesEcbSign) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SigningKey()
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)));
+
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE,
+ Begin(KeyPurpose::SIGN, AuthorizationSet() /* in_params */, &out_params));
+ EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE,
+ Begin(KeyPurpose::VERIFY, AuthorizationSet() /* in_params */, &out_params));
+}
+
+/*
+ * SigningOperationsTest.HmacAllDigests
+ *
+ * Verifies that HMAC works with all digests.
+ */
+TEST_P(SigningOperationsTest, HmacAllDigests) {
+ for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(128)
+ .Digest(digest)
+ .Authorization(TAG_MIN_MAC_LENGTH, 160)))
+ << "Failed to create HMAC key with digest " << digest;
+ string message = "12345678901234567890123456789012";
+ string signature = MacMessage(message, digest, 160);
+ EXPECT_EQ(160U / 8U, signature.size())
+ << "Failed to sign with HMAC key with digest " << digest;
+ CheckedDeleteKey();
+ }
+}
+
+/*
+ * SigningOperationsTest.HmacSha256TooLargeMacLength
+ *
+ * Verifies that HMAC fails in the correct way when asked to generate a MAC larger than the
+ * digest size.
+ */
+TEST_P(SigningOperationsTest, HmacSha256TooLargeMacLength) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(128)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256)));
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::UNSUPPORTED_MAC_LENGTH, Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MAC_LENGTH, 264),
+ &output_params));
+}
+
+/*
+ * SigningOperationsTest.HmacSha256TooSmallMacLength
+ *
+ * Verifies that HMAC fails in the correct way when asked to generate a MAC smaller than the
+ * specified minimum MAC length.
+ */
+TEST_P(SigningOperationsTest, HmacSha256TooSmallMacLength) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(128)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MAC_LENGTH, 120),
+ &output_params));
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase3
+ *
+ * Validates against the test vectors from RFC 4231 test case 3.
+ */
+TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
+ string key(20, 0xaa);
+ string message(50, 0xdd);
+ uint8_t sha_224_expected[] = {
+ 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a,
+ 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea,
+ };
+ uint8_t sha_256_expected[] = {
+ 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8,
+ 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8,
+ 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
+ };
+ uint8_t sha_384_expected[] = {
+ 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0,
+ 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
+ 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d,
+ 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27,
+ };
+ uint8_t sha_512_expected[] = {
+ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c,
+ 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8,
+ 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22,
+ 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37,
+ 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
+ };
+
+ CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+ }
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase5
+ *
+ * Validates against the test vectors from RFC 4231 test case 5.
+ */
+TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) {
+ string key(20, 0x0c);
+ string message = "Test With Truncation";
+
+ uint8_t sha_224_expected[] = {
+ 0x0e, 0x2a, 0xea, 0x68, 0xa9, 0x0c, 0x8d, 0x37,
+ 0xc9, 0x88, 0xbc, 0xdb, 0x9f, 0xca, 0x6f, 0xa8,
+ };
+ uint8_t sha_256_expected[] = {
+ 0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0,
+ 0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b,
+ };
+ uint8_t sha_384_expected[] = {
+ 0x3a, 0xbf, 0x34, 0xc3, 0x50, 0x3b, 0x2a, 0x23,
+ 0xa4, 0x6e, 0xfc, 0x61, 0x9b, 0xae, 0xf8, 0x97,
+ };
+ uint8_t sha_512_expected[] = {
+ 0x41, 0x5f, 0xad, 0x62, 0x71, 0x58, 0x0a, 0x53,
+ 0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
+ };
+
+ CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(SigningOperationsTest);
+
+typedef KeyMintAidlTestBase VerificationOperationsTest;
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies that a simple RSA signature/verification sequence succeeds.
+ */
+TEST_P(VerificationOperationsTest, RsaSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)));
+ string message = "12345678901234567890123456789012";
+ string signature = SignMessage(
+ message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+ VerifyMessage(message, signature,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies RSA signature/verification for all padding modes and digests.
+ */
+TEST_P(VerificationOperationsTest, RsaAllPaddingsAndDigests) {
+ auto authorizations = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(ValidDigests(true /* withNone */, true /* withMD5 */))
+ .Padding(PaddingMode::NONE)
+ .Padding(PaddingMode::RSA_PSS)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(authorizations));
+
+ string message(128, 'a');
+ string corrupt_message(message);
+ ++corrupt_message[corrupt_message.size() / 2];
+
+ for (auto padding :
+ {PaddingMode::NONE, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN}) {
+ for (auto digest : ValidDigests(true /* withNone */, true /* withMD5 */)) {
+ if (padding == PaddingMode::NONE && digest != Digest::NONE) {
+ // Digesting only makes sense with padding.
+ continue;
+ }
+
+ if (padding == PaddingMode::RSA_PSS && digest == Digest::NONE) {
+ // PSS requires digesting.
+ continue;
+ }
+
+ string signature =
+ SignMessage(message, AuthorizationSetBuilder().Digest(digest).Padding(padding));
+ VerifyMessage(message, signature,
+ AuthorizationSetBuilder().Digest(digest).Padding(padding));
+
+ /* TODO(seleneh) add exportkey tests back later when we have decided on
+ * the new api.
+ if (digest != Digest::NONE) {
+ // Verify with OpenSSL.
+ vector<uint8_t> pubkey;
+ ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey));
+
+ const uint8_t* p = pubkey.data();
+ EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr, &p, pubkey.size()));
+ ASSERT_TRUE(pkey.get());
+
+ EVP_MD_CTX digest_ctx;
+ EVP_MD_CTX_init(&digest_ctx);
+ EVP_PKEY_CTX* pkey_ctx;
+ const EVP_MD* md = openssl_digest(digest);
+ ASSERT_NE(md, nullptr);
+ EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md,
+ nullptr, pkey.get()));
+
+ switch (padding) {
+ case PaddingMode::RSA_PSS:
+ EXPECT_GT(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx,
+ RSA_PKCS1_PSS_PADDING), 0); EXPECT_GT(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx,
+ EVP_MD_size(md)), 0); break; case PaddingMode::RSA_PKCS1_1_5_SIGN:
+ // PKCS1 is the default; don't need to set anything.
+ break;
+ default:
+ FAIL();
+ break;
+ }
+
+ EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(),
+ message.size())); EXPECT_EQ(1, EVP_DigestVerifyFinal(&digest_ctx,
+ reinterpret_cast<const
+ uint8_t*>(signature.data()), signature.size())); EVP_MD_CTX_cleanup(&digest_ctx);
+ }
+ */
+
+ // Corrupt signature shouldn't verify.
+ string corrupt_signature(signature);
+ ++corrupt_signature[corrupt_signature.size() / 2];
+
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY,
+ AuthorizationSetBuilder().Digest(digest).Padding(padding)));
+ string result;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result));
+
+ // Corrupt message shouldn't verify
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY,
+ AuthorizationSetBuilder().Digest(digest).Padding(padding)));
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result));
+ }
+ }
+}
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies ECDSA signature/verification for all digests and curves.
+ */
+TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndCurves) {
+ auto digests = ValidDigests(true /* withNone */, false /* withMD5 */);
+
+ string message = "1234567890";
+ string corrupt_message = "2234567890";
+ for (auto curve : ValidCurves()) {
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(digests));
+ EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate key for EC curve " << curve;
+ if (error != ErrorCode::OK) {
+ continue;
+ }
+
+ for (auto digest : digests) {
+ string signature = SignMessage(message, AuthorizationSetBuilder().Digest(digest));
+ VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(digest));
+
+ /* TODO(seleneh) add exportkey tests back later when we have decided on
+ * the new api.
+
+ // Verify with OpenSSL
+ if (digest != Digest::NONE) {
+ vector<uint8_t> pubkey;
+ ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey))
+ << curve << ' ' << digest;
+
+ const uint8_t* p = pubkey.data();
+ EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr, &p, pubkey.size()));
+ ASSERT_TRUE(pkey.get());
+
+ EVP_MD_CTX digest_ctx;
+ EVP_MD_CTX_init(&digest_ctx);
+ EVP_PKEY_CTX* pkey_ctx;
+ const EVP_MD* md = openssl_digest(digest);
+
+ EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md,
+ nullptr, pkey.get()))
+ << curve << ' ' << digest;
+
+ EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(),
+ message.size()))
+ << curve << ' ' << digest;
+
+ EXPECT_EQ(1,
+ EVP_DigestVerifyFinal(&digest_ctx,
+ reinterpret_cast<const
+ uint8_t*>(signature.data()), signature.size()))
+ << curve << ' ' << digest;
+
+ EVP_MD_CTX_cleanup(&digest_ctx);
+ }
+ */
+ // Corrupt signature shouldn't verify.
+ string corrupt_signature(signature);
+ ++corrupt_signature[corrupt_signature.size() / 2];
+
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest)))
+ << curve << ' ' << digest;
+
+ string result;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result))
+ << curve << ' ' << digest;
+
+ // Corrupt message shouldn't verify
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest)))
+ << curve << ' ' << digest;
+
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result))
+ << curve << ' ' << digest;
+ }
+
+ auto rc = DeleteKey();
+ ASSERT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+ }
+}
+
+/*
+ * VerificationOperationsTest.HmacSigningKeyCannotVerify
+ *
+ * Verifies HMAC signing and verification, but that a signing key cannot be used to verify.
+ */
+TEST_P(VerificationOperationsTest, HmacSigningKeyCannotVerify) {
+ string key_material = "HelloThisIsAKey";
+
+ vector<uint8_t> signing_key, verification_key;
+ KeyCharacteristics signing_key_chars, verification_key_chars;
+ EXPECT_EQ(ErrorCode::OK,
+ ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+ .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 160),
+ KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+ EXPECT_EQ(ErrorCode::OK,
+ ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+ .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 160),
+ KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+
+ string message = "This is a message.";
+ string signature = SignMessage(
+ signing_key, message,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 160));
+
+ // Signing key should not work.
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ Begin(KeyPurpose::VERIFY, signing_key,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &out_params));
+
+ // Verification key should work.
+ VerifyMessage(verification_key, message, signature,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+
+ CheckedDeleteKey(&signing_key);
+ CheckedDeleteKey(&verification_key);
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
+
+typedef KeyMintAidlTestBase ExportKeyTest;
+
+/*
+ * ExportKeyTest.RsaUnsupportedKeyFormat
+ *
+ * Verifies that attempting to export RSA keys in PKCS#8 format fails with the correct error.
+ */
+// TODO(seleneh) add ExportKey to GenerateKey
+// check result
+
+class ImportKeyTest : public KeyMintAidlTestBase {
+ public:
+ template <TagType tag_type, Tag tag, typename ValueT>
+ void CheckCryptoParam(TypedTag<tag_type, tag> ttag, ValueT expected) {
+ SCOPED_TRACE("CheckCryptoParam");
+ if (IsSecure()) {
+ EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, ttag, expected))
+ << "Tag " << tag << " with value " << expected << " not found";
+ EXPECT_FALSE(contains(key_characteristics_.softwareEnforced, ttag))
+ << "Tag " << tag << " found";
+ } else {
+ EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, ttag, expected))
+ << "Tag " << tag << " with value " << expected << " not found";
+ EXPECT_FALSE(contains(key_characteristics_.hardwareEnforced, ttag))
+ << "Tag " << tag << " found";
+ }
+ }
+
+ void CheckOrigin() {
+ SCOPED_TRACE("CheckOrigin");
+ if (IsSecure()) {
+ EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, TAG_ORIGIN,
+ KeyOrigin::IMPORTED));
+ } else {
+ EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, TAG_ORIGIN,
+ KeyOrigin::IMPORTED));
+ }
+ }
+};
+
+/*
+ * ImportKeyTest.RsaSuccess
+ *
+ * Verifies that importing and using an RSA key pair works correctly.
+ */
+TEST_P(ImportKeyTest, RsaSuccess) {
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PSS),
+ KeyFormat::PKCS8, rsa_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+ CheckCryptoParam(TAG_KEY_SIZE, 1024U);
+ CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_PSS);
+ CheckOrigin();
+
+ string message(1024 / 8, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS);
+ string signature = SignMessage(message, params);
+ VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.RsaKeySizeMismatch
+ *
+ * Verifies that importing an RSA key pair with a size that doesn't match the key fails in the
+ * correct way.
+ */
+TEST_P(ImportKeyTest, RsaKeySizeMismatch) {
+ ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+ ImportKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048 /* Doesn't match key */, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
+ KeyFormat::PKCS8, rsa_key));
+}
+
+/*
+ * ImportKeyTest.RsaPublicExponentMismatch
+ *
+ * Verifies that importing an RSA key pair with a public exponent that doesn't match the key
+ * fails in the correct way.
+ */
+TEST_P(ImportKeyTest, RsaPublicExponentMismatch) {
+ ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+ ImportKey(AuthorizationSetBuilder()
+ .RsaSigningKey(1024, 3 /* Doesn't match key */)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
+ KeyFormat::PKCS8, rsa_key));
+}
+
+/*
+ * ImportKeyTest.EcdsaSuccess
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair works correctly.
+ */
+TEST_P(ImportKeyTest, EcdsaSuccess) {
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256),
+ KeyFormat::PKCS8, ec_256_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_KEY_SIZE, 256U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
+
+ CheckOrigin();
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ string signature = SignMessage(message, params);
+ VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.EcdsaP256RFC5915Success
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair encoded using RFC5915 works
+ * correctly.
+ */
+TEST_P(ImportKeyTest, EcdsaP256RFC5915Success) {
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256),
+ KeyFormat::PKCS8, ec_256_key_rfc5915));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_KEY_SIZE, 256U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
+
+ CheckOrigin();
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ string signature = SignMessage(message, params);
+ VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.EcdsaP256SEC1Success
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair encoded using SEC1 works correctly.
+ */
+TEST_P(ImportKeyTest, EcdsaP256SEC1Success) {
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256),
+ KeyFormat::PKCS8, ec_256_key_sec1));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_KEY_SIZE, 256U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
+
+ CheckOrigin();
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ string signature = SignMessage(message, params);
+ VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ecdsa521Success
+ *
+ * Verifies that importing and using an ECDSA P-521 key pair works correctly.
+ */
+TEST_P(ImportKeyTest, Ecdsa521Success) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(521)
+ .Digest(Digest::SHA_2_256),
+ KeyFormat::PKCS8, ec_521_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_KEY_SIZE, 521U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_521);
+ CheckOrigin();
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+ string signature = SignMessage(message, params);
+ VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.EcdsaSizeMismatch
+ *
+ * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the
+ * correct way.
+ */
+TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
+ ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+ ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(224 /* Doesn't match key */)
+ .Digest(Digest::NONE),
+ KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.EcdsaCurveMismatch
+ *
+ * Verifies that importing an ECDSA key pair with a curve that doesn't match the key fails in
+ * the correct way.
+ */
+TEST_P(ImportKeyTest, EcdsaCurveMismatch) {
+ ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+ ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */)
+ .Digest(Digest::NONE),
+ KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.AesSuccess
+ *
+ * Verifies that importing and using an AES key works.
+ */
+TEST_P(ImportKeyTest, AesSuccess) {
+ string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(key.size() * 8)
+ .EcbMode()
+ .Padding(PaddingMode::PKCS7),
+ KeyFormat::RAW, key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::AES);
+ CheckCryptoParam(TAG_KEY_SIZE, 128U);
+ CheckCryptoParam(TAG_PADDING, PaddingMode::PKCS7);
+ CheckCryptoParam(TAG_BLOCK_MODE, BlockMode::ECB);
+ CheckOrigin();
+
+ string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ string ciphertext = EncryptMessage(message, params);
+ string plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * ImportKeyTest.AesSuccess
+ *
+ * Verifies that importing and using an HMAC key works.
+ */
+TEST_P(ImportKeyTest, HmacKeySuccess) {
+ string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(key.size() * 8)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256),
+ KeyFormat::RAW, key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::HMAC);
+ CheckCryptoParam(TAG_KEY_SIZE, 128U);
+ CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+ CheckOrigin();
+
+ string message = "Hello World!";
+ string signature = MacMessage(message, Digest::SHA_2_256, 256);
+ VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
+
+auto wrapped_key = hex2str(
+ "3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac8"
+ "4b59b30b455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e0"
+ "97474febc981195b1d13a69086c0863f66a7b7fdb48792227b1ac5e2489febdf087ab5486483033a6f001c"
+ "a5d1ec1e27f5c30f4cec2642074a39ae68aee552e196627a8e3d867e67a8c01b11e75f13cca0a97ab668b5"
+ "0cda07a8ecb7cd8e3dd7009c9636534f6f239cffe1fc8daa466f78b676c7119efb96bce4e69ca2a25d0b34"
+ "ed9c3ff999b801597d5220e307eaa5bee507fb94d1fa69f9e519b2de315bac92c36f2ea1fa1df4478c0dde"
+ "deae8c70e0233cd098040cd796b02c370f1fa4cc0124f1302e0201033029a1083106020100020101a20302"
+ "0120a30402020100a4053103020101a6053103020140bf83770205000420ccd540855f833a5e1480bfd2d3"
+ "6faf3aeee15df5beabe2691bc82dde2a7aa910041064c9f689c60ff6223ab6e6999e0eb6e5");
+
+auto wrapped_key_masked = hex2str(
+ "3082017902010004820100aad93ed5924f283b4bb5526fbe7a1412f9d9749ec30db9062b29e574a8546f33"
+ "c88732452f5b8e6a391ee76c39ed1712c61d8df6213dec1cffbc17a8c6d04c7b30893d8daa9b2015213e21"
+ "946821553207f8f9931c4caba23ed3bee28b36947e47f10e0a5c3dc51c988a628daad3e5e1f4005e79c2d5"
+ "a96c284b4b8d7e4948f331e5b85dd5a236f85579f3ea1d1b848487470bdb0ab4f81a12bee42c99fe0df4be"
+ "e3759453e69ad1d68a809ce06b949f7694a990429b2fe81e066ff43e56a21602db70757922a4bcc23ab89f"
+ "1e35da77586775f423e519c2ea394caf48a28d0c8020f1dcf6b3a68ec246f615ae96dae9a079b1f6eb9590"
+ "33c1af5c125fd94168040c6d9721d08589581ab49204a3302e0201033029a1083106020100020101a20302"
+ "0120a30402020100a4053103020101a6053103020140bf83770205000420a61c6e247e25b3e6e69aa78eb0"
+ "3c2d4ac20d1f99a9a024a76f35c8e2cab9b68d04102560c70109ae67c030f00b98b512a670");
+
+auto wrapping_key = hex2str(
+ "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d"
+ "8900ce56b0067f7d70e1fc653f3f34d194c1fed50018fb43db937b06e673a837313d56b1c725150a3fef86"
+ "acbddc41bb759c2854eae32d35841efb5c18d82bc90a1cb5c1d55adf245b02911f0b7cda88c421ff0ebafe"
+ "7c0d23be312d7bd5921ffaea1347c157406fef718f682643e4e5d33c6703d61c0cf7ac0bf4645c11f5c137"
+ "4c3886427411c449796792e0bef75dec858a2123c36753e02a95a96d7c454b504de385a642e0dfc3e60ac3"
+ "a7ee4991d0d48b0172a95f9536f02ba13cecccb92b727db5c27e5b2f5cec09600b286af5cf14c42024c61d"
+ "dfe71c2a8d7458f185234cb00e01d282f10f8fc6721d2aed3f4833cca2bd8fa62821dd5502030100010282"
+ "0100431447b6251908112b1ee76f99f3711a52b6630960046c2de70de188d833f8b8b91e4d785caeeeaf4f"
+ "0f74414e2cda40641f7fe24f14c67a88959bdb27766df9e710b630a03adc683b5d2c43080e52bee71e9eae"
+ "b6de297a5fea1072070d181c822bccff087d63c940ba8a45f670feb29fb4484d1c95e6d2579ba02aae0a00"
+ "900c3ebf490e3d2cd7ee8d0e20c536e4dc5a5097272888cddd7e91f228b1c4d7474c55b8fcd618c4a957bb"
+ "ddd5ad7407cc312d8d98a5caf7e08f4a0d6b45bb41c652659d5a5ba05b663737a8696281865ba20fbdd7f8"
+ "51e6c56e8cbe0ddbbf24dc03b2d2cb4c3d540fb0af52e034a2d06698b128e5f101e3b51a34f8d8b4f86181"
+ "02818100de392e18d682c829266cc3454e1d6166242f32d9a1d10577753e904ea7d08bff841be5bac82a16"
+ "4c5970007047b8c517db8f8f84e37bd5988561bdf503d4dc2bdb38f885434ae42c355f725c9a60f91f0788"
+ "e1f1a97223b524b5357fdf72e2f696bab7d78e32bf92ba8e1864eab1229e91346130748a6e3c124f9149d7"
+ "1c743502818100c95387c0f9d35f137b57d0d65c397c5e21cc251e47008ed62a542409c8b6b6ac7f8967b3"
+ "863ca645fcce49582a9aa17349db6c4a95affdae0dae612e1afac99ed39a2d934c880440aed8832f984316"
+ "3a47f27f392199dc1202f9a0f9bd08308007cb1e4e7f58309366a7de25f7c3c9b880677c068e1be936e812"
+ "88815252a8a102818057ff8ca1895080b2cae486ef0adfd791fb0235c0b8b36cd6c136e52e4085f4ea5a06"
+ "3212a4f105a3764743e53281988aba073f6e0027298e1c4378556e0efca0e14ece1af76ad0b030f27af6f0"
+ "ab35fb73a060d8b1a0e142fa2647e93b32e36d8282ae0a4de50ab7afe85500a16f43a64719d6e2b9439823"
+ "719cd08bcd03178102818100ba73b0bb28e3f81e9bd1c568713b101241acc607976c4ddccc90e65b6556ca"
+ "31516058f92b6e09f3b160ff0e374ec40d78ae4d4979fde6ac06a1a400c61dd31254186af30b22c10582a8"
+ "a43e34fe949c5f3b9755bae7baa7b7b7a6bd03b38cef55c86885fc6c1978b9cee7ef33da507c9df6b9277c"
+ "ff1e6aaa5d57aca528466102818100c931617c77829dfb1270502be9195c8f2830885f57dba869536811e6"
+ "864236d0c4736a0008a145af36b8357a7c3d139966d04c4e00934ea1aede3bb6b8ec841dc95e3f579751e2"
+ "bfdfe27ae778983f959356210723287b0affcc9f727044d48c373f1babde0724fa17a4fd4da0902c7c9b9b"
+ "f27ba61be6ad02dfddda8f4e6822");
+
+string zero_masking_key =
+ hex2str("0000000000000000000000000000000000000000000000000000000000000000");
+string masking_key = hex2str("D796B02C370F1FA4CC0124F14EC8CBEBE987E825246265050F399A51FD477DFC");
+
+class ImportWrappedKeyTest : public KeyMintAidlTestBase {};
+
+TEST_P(ImportWrappedKeyTest, Success) {
+ auto wrapping_key_desc = AuthorizationSetBuilder()
+ .RsaEncryptionKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+ ASSERT_EQ(ErrorCode::OK,
+ ImportWrappedKey(wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)));
+
+ string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ string ciphertext = EncryptMessage(message, params);
+ string plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+}
+
+TEST_P(ImportWrappedKeyTest, SuccessMasked) {
+ auto wrapping_key_desc = AuthorizationSetBuilder()
+ .RsaEncryptionKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+ ASSERT_EQ(ErrorCode::OK,
+ ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, masking_key,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)));
+}
+
+TEST_P(ImportWrappedKeyTest, WrongMask) {
+ auto wrapping_key_desc = AuthorizationSetBuilder()
+ .RsaEncryptionKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+ ASSERT_EQ(
+ ErrorCode::VERIFICATION_FAILED,
+ ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)));
+}
+
+TEST_P(ImportWrappedKeyTest, WrongPurpose) {
+ auto wrapping_key_desc = AuthorizationSetBuilder()
+ .RsaEncryptionKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP);
+
+ ASSERT_EQ(
+ ErrorCode::INCOMPATIBLE_PURPOSE,
+ ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
+ AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(ImportWrappedKeyTest);
+
+typedef KeyMintAidlTestBase EncryptionOperationsTest;
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingSuccess
+ *
+ * Verifies that raw RSA encryption works.
+ */
+TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ string message = string(2048 / 8, 'a');
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+ string ciphertext1 = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext2.size());
+
+ // Unpadded RSA is deterministic
+ EXPECT_EQ(ciphertext1, ciphertext2);
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingShortMessage
+ *
+ * Verifies that raw RSA encryption of short messages works.
+ */
+TEST_P(EncryptionOperationsTest, RsaNoPaddingShortMessage) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ string message = "1";
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+
+ string ciphertext = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext.size());
+
+ string expected_plaintext = string(2048U / 8 - 1, 0) + message;
+ string plaintext = DecryptMessage(ciphertext, params);
+
+ EXPECT_EQ(expected_plaintext, plaintext);
+
+ // Degenerate case, encrypting a numeric 1 yields 0x00..01 as the ciphertext.
+ message = static_cast<char>(1);
+ ciphertext = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext.size());
+ EXPECT_EQ(ciphertext, string(2048U / 8 - 1, 0) + message);
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingTooLong
+ *
+ * Verifies that raw RSA encryption of too-long messages fails in the expected way.
+ */
+TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ string message(2048 / 8 + 1, 'a');
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+
+ string result;
+ EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &result));
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingTooLarge
+ *
+ * Verifies that raw RSA encryption of too-large (numerically) messages fails in the expected
+ * way.
+ */
+// TODO(seleneh) add RsaNoPaddingTooLarge test back after decided and implemented new
+// version of ExportKey inside generateKey
+
+/*
+ * EncryptionOperationsTest.RsaOaepSuccess
+ *
+ * Verifies that RSA-OAEP encryption operations work, with all digests.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
+ auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+
+ size_t key_size = 2048; // Need largish key for SHA-512 test.
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(digests)));
+
+ string message = "Hello";
+
+ for (auto digest : digests) {
+ auto params = AuthorizationSetBuilder().Digest(digest).Padding(PaddingMode::RSA_OAEP);
+ string ciphertext1 = EncryptMessage(message, params);
+ if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+ EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(message, params);
+ EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+ // OAEP randomizes padding so every result should be different (with astronomically high
+ // probability).
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ string plaintext1 = DecryptMessage(ciphertext1, params);
+ EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
+ string plaintext2 = DecryptMessage(ciphertext2, params);
+ EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;
+
+ // Decrypting corrupted ciphertext should fail.
+ size_t offset_to_corrupt = random() % ciphertext1.size();
+ char corrupt_byte;
+ do {
+ corrupt_byte = static_cast<char>(random() % 256);
+ } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
+ ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string result;
+ EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+ EXPECT_EQ(0U, result.size());
+ }
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepInvalidDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
+ * without a digest.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepInvalidDigest) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::NONE)));
+ string message = "Hello World!";
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::NONE);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepInvalidDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to decrypt
+ * with a different digest than was used to encrypt.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(1024, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_224, Digest::SHA_2_256)));
+ string message = "Hello World!";
+ string ciphertext = EncryptMessage(
+ message,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_224).Padding(PaddingMode::RSA_OAEP));
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_OAEP)));
+ string result;
+ EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext, &result));
+ EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepTooLarge
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to encrypt a
+ * too-large message.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)));
+ constexpr size_t digest_size = 256 /* SHA_2_256 */ / 8;
+ constexpr size_t oaep_overhead = 2 * digest_size + 2;
+ string message(2048 / 8 - oaep_overhead + 1, 'a');
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, AuthorizationSetBuilder()
+ .Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)));
+ string result;
+ ErrorCode error = Finish(message, &result);
+ EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT);
+ EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaPkcs1Success
+ *
+ * Verifies that RSA PKCS encryption/decrypts works.
+ */
+TEST_P(EncryptionOperationsTest, RsaPkcs1Success) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
+
+ string message = "Hello World!";
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+ string ciphertext1 = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(message, params);
+ EXPECT_EQ(2048U / 8, ciphertext2.size());
+
+ // PKCS1 v1.5 randomizes padding so every result should be different.
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ string plaintext = DecryptMessage(ciphertext1, params);
+ EXPECT_EQ(message, plaintext);
+
+ // Decrypting corrupted ciphertext should fail.
+ size_t offset_to_corrupt = random() % ciphertext1.size();
+ char corrupt_byte;
+ do {
+ corrupt_byte = static_cast<char>(random() % 256);
+ } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
+ ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string result;
+ EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+ EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaPkcs1TooLarge
+ *
+ * Verifies that RSA PKCS encryption fails in the correct way when the mssage is too large.
+ */
+TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
+ string message(2048 / 8 - 10, 'a');
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+ string result;
+ ErrorCode error = Finish(message, &result);
+ EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT);
+ EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.EcdsaEncrypt
+ *
+ * Verifies that attempting to use ECDSA keys to encrypt fails in the correct way.
+ */
+TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::NONE)));
+ auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params));
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.HmacEncrypt
+ *
+ * Verifies that attempting to use HMAC keys to encrypt fails in the correct way.
+ */
+TEST_P(EncryptionOperationsTest, HmacEncrypt) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .HmacKey(128)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+ auto params = AuthorizationSetBuilder()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params));
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbRoundTripSuccess
+ *
+ * Verifies that AES ECB mode works.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbRoundTripSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+ .Padding(PaddingMode::NONE)));
+
+ ASSERT_GT(key_blob_.size(), 0U);
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+
+ // Two-block message.
+ string message = "12345678901234567890123456789012";
+ string ciphertext1 = EncryptMessage(message, params);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(string(message), params);
+ EXPECT_EQ(message.size(), ciphertext2.size());
+
+ // ECB is deterministic.
+ EXPECT_EQ(ciphertext1, ciphertext2);
+
+ string plaintext = DecryptMessage(ciphertext1, params);
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbRoundTripSuccess
+ *
+ * Verifies that AES encryption fails in the correct way when an unauthorized mode is specified.
+ */
+TEST_P(EncryptionOperationsTest, AesWrongMode) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+ .Padding(PaddingMode::NONE)));
+
+ ASSERT_GT(key_blob_.size(), 0U);
+
+ // Two-block message.
+ string message = "12345678901234567890123456789012";
+ EXPECT_EQ(
+ ErrorCode::INCOMPATIBLE_BLOCK_MODE,
+ Begin(KeyPurpose::ENCRYPT,
+ AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE)));
+}
+
+/*
+ * EncryptionOperationsTest.AesWrongPurpose
+ *
+ * Verifies that AES encryption fails in the correct way when an unauthorized purpose is
+ * specified.
+ */
+TEST_P(EncryptionOperationsTest, AesWrongPurpose) {
+ auto err = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesKey(128)
+ .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Padding(PaddingMode::NONE));
+ ASSERT_EQ(ErrorCode::OK, err) << "Got " << err;
+ ASSERT_GT(key_blob_.size(), 0U);
+
+ err = Begin(KeyPurpose::DECRYPT, AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128));
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+
+ CheckedDeleteKey();
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesKey(128)
+ .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Padding(PaddingMode::NONE)));
+
+ err = Begin(KeyPurpose::ENCRYPT, AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128));
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize
+ *
+ * Verifies that AES encryption fails in the correct way when provided an input that is not a
+ * multiple of the block size and no padding is specified.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+ .Padding(PaddingMode::NONE)));
+ // Message is slightly shorter than two blocks.
+ string message(16 * 2 - 1, 'a');
+
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &ciphertext));
+ EXPECT_EQ(0U, ciphertext.size());
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbPkcs7Padding
+ *
+ * Verifies that AES PKCS7 padding works for any message length.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbPkcs7Padding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)));
+
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+ // Try various message lengths; all should work.
+ for (size_t i = 0; i < 32; ++i) {
+ string message(i, 'a');
+ string ciphertext = EncryptMessage(message, params);
+ EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
+ string plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+ }
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbWrongPadding
+ *
+ * Verifies that AES enryption fails in the correct way when an unauthorized padding mode is
+ * specified.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbWrongPadding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+ // Try various message lengths; all should fail
+ for (size_t i = 0; i < 32; ++i) {
+ string message(i, 'a');
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
+ }
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbPkcs7PaddingCorrupted
+ *
+ * Verifies that AES decryption fails in the correct way when the padding is corrupted.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)));
+
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+ string message = "a";
+ string ciphertext = EncryptMessage(message, params);
+ EXPECT_EQ(16U, ciphertext.size());
+ EXPECT_NE(ciphertext, message);
+ ++ciphertext[ciphertext.size() / 2];
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext));
+}
+
+vector<uint8_t> CopyIv(const AuthorizationSet& set) {
+ auto iv = set.GetTagValue(TAG_NONCE);
+ EXPECT_TRUE(iv.isOk());
+ return iv.value();
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrRoundTripSuccess
+ *
+ * Verifies that AES CTR mode works.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE);
+
+ string message = "123";
+ AuthorizationSet out_params;
+ string ciphertext1 = EncryptMessage(message, params, &out_params);
+ vector<uint8_t> iv1 = CopyIv(out_params);
+ EXPECT_EQ(16U, iv1.size());
+
+ EXPECT_EQ(message.size(), ciphertext1.size());
+
+ out_params.Clear();
+ string ciphertext2 = EncryptMessage(message, params, &out_params);
+ vector<uint8_t> iv2 = CopyIv(out_params);
+ EXPECT_EQ(16U, iv2.size());
+
+ // IVs should be random, so ciphertexts should differ.
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ auto params_iv1 =
+ AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv1);
+ auto params_iv2 =
+ AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv2);
+
+ string plaintext = DecryptMessage(ciphertext1, params_iv1);
+ EXPECT_EQ(message, plaintext);
+ plaintext = DecryptMessage(ciphertext2, params_iv2);
+ EXPECT_EQ(message, plaintext);
+
+ // Using the wrong IV will result in a "valid" decryption, but the data will be garbage.
+ plaintext = DecryptMessage(ciphertext1, params_iv2);
+ EXPECT_NE(message, plaintext);
+ plaintext = DecryptMessage(ciphertext2, params_iv1);
+ EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesIncremental
+ *
+ * Verifies that AES works, all modes, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesIncremental) {
+ auto block_modes = {
+ BlockMode::ECB,
+ BlockMode::CBC,
+ BlockMode::CTR,
+ BlockMode::GCM,
+ };
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(block_modes)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ for (int increment = 1; increment <= 240; ++increment) {
+ for (auto block_mode : block_modes) {
+ string message(240, 'a');
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+ string ciphertext;
+ int32_t input_consumed;
+ string to_send;
+ for (size_t i = 0; i < message.size(); i += increment) {
+ to_send.append(message.substr(i, increment));
+ EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
+ EXPECT_EQ(to_send.length(), input_consumed);
+ to_send = to_send.substr(input_consumed);
+ EXPECT_EQ(0U, to_send.length());
+
+ switch (block_mode) {
+ case BlockMode::ECB:
+ case BlockMode::CBC:
+ // Implementations must take as many blocks as possible, leaving less
+ // than a block.
+ EXPECT_LE(to_send.length(), 16U);
+ break;
+ case BlockMode::GCM:
+ case BlockMode::CTR:
+ // Implementations must always take all the data.
+ EXPECT_EQ(0U, to_send.length());
+ break;
+ }
+ }
+ EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
+
+ switch (block_mode) {
+ case BlockMode::GCM:
+ EXPECT_EQ(message.size() + 16, ciphertext.size());
+ break;
+ case BlockMode::CTR:
+ EXPECT_EQ(message.size(), ciphertext.size());
+ break;
+ case BlockMode::CBC:
+ case BlockMode::ECB:
+ EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+ break;
+ }
+
+ auto iv = output_params.GetTagValue(TAG_NONCE);
+ switch (block_mode) {
+ case BlockMode::CBC:
+ case BlockMode::GCM:
+ case BlockMode::CTR:
+ ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
+ EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
+ params.push_back(TAG_NONCE, iv.value());
+ break;
+
+ case BlockMode::ECB:
+ EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+ break;
+ }
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+ << "Decrypt begin() failed for block mode " << block_mode;
+
+ string plaintext;
+ for (size_t i = 0; i < ciphertext.size(); i += increment) {
+ to_send.append(ciphertext.substr(i, increment));
+ EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
+ to_send = to_send.substr(input_consumed);
+ }
+ ErrorCode error = Finish(to_send, &plaintext);
+ ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+ << " and increment " << increment;
+ if (error == ErrorCode::OK) {
+ ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
+ << block_mode << " and increment " << increment;
+ }
+ }
+ }
+}
+
+struct AesCtrSp80038aTestVector {
+ const char* key;
+ const char* nonce;
+ const char* plaintext;
+ const char* ciphertext;
+};
+
+// These test vectors are taken from
+// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section F.5.
+static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = {
+ // AES-128
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"
+ "5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee",
+ },
+ // AES-192
+ {
+ "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94"
+ "1e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050",
+ },
+ // AES-256
+ {
+ "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5"
+ "2b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6",
+ },
+};
+
+/*
+ * EncryptionOperationsTest.AesCtrSp80038aTestVector
+ *
+ * Verifies AES CTR implementation against SP800-38A test vectors.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrSp80038aTestVector) {
+ std::vector<uint32_t> InvalidSizes = InvalidKeySizes(Algorithm::AES);
+ for (size_t i = 0; i < 3; i++) {
+ const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]);
+ const string key = hex2str(test.key);
+ if (std::find(InvalidSizes.begin(), InvalidSizes.end(), (key.size() * 8)) !=
+ InvalidSizes.end())
+ continue;
+ const string nonce = hex2str(test.nonce);
+ const string plaintext = hex2str(test.plaintext);
+ const string ciphertext = hex2str(test.ciphertext);
+ CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
+ }
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrIncompatiblePaddingMode
+ *
+ * Verifies that keymint rejects use of CTR mode with PKCS7 padding in the correct way.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncompatiblePaddingMode) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+ .Padding(PaddingMode::PKCS7)));
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrInvalidCallerNonce
+ *
+ * Verifies that keymint fails correctly when the user supplies an incorrect-size nonce.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+ .Authorization(TAG_CALLER_NONCE)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CTR)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf(string(1, 'a')));
+ EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+
+ params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CTR)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf(string(15, 'a')));
+ EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+
+ params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CTR)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf(string(17, 'a')));
+ EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrInvalidCallerNonce
+ *
+ * Verifies that keymint fails correctly when the user supplies an incorrect-size nonce.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+ .Padding(PaddingMode::NONE)));
+ // Two-block message.
+ string message = "12345678901234567890123456789012";
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ AuthorizationSet out_params;
+ string ciphertext1 = EncryptMessage(message, params, &out_params);
+ vector<uint8_t> iv1 = CopyIv(out_params);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+
+ out_params.Clear();
+
+ string ciphertext2 = EncryptMessage(message, params, &out_params);
+ vector<uint8_t> iv2 = CopyIv(out_params);
+ EXPECT_EQ(message.size(), ciphertext2.size());
+
+ // IVs should be random, so ciphertexts should differ.
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ params.push_back(TAG_NONCE, iv1);
+ string plaintext = DecryptMessage(ciphertext1, params);
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesCallerNonce
+ *
+ * Verifies that AES caller-provided nonces work correctly.
+ */
+TEST_P(EncryptionOperationsTest, AesCallerNonce) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+ .Authorization(TAG_CALLER_NONCE)
+ .Padding(PaddingMode::NONE)));
+
+ string message = "12345678901234567890123456789012";
+
+ // Don't specify nonce, should get a random one.
+ AuthorizationSetBuilder params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ EXPECT_EQ(message.size(), ciphertext.size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ string plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+
+ // Now specify a nonce, should also work.
+ params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CBC)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf("abcdefghijklmnop"));
+ out_params.Clear();
+ ciphertext = EncryptMessage(message, params, &out_params);
+
+ // Decrypt with correct nonce.
+ plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+
+ // Try with wrong nonce.
+ params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CBC)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf("aaaaaaaaaaaaaaaa"));
+ plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesCallerNonceProhibited
+ *
+ * Verifies that caller-provided nonces are not permitted when not specified in the key
+ * authorizations.
+ */
+TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+ .Padding(PaddingMode::NONE)));
+
+ string message = "12345678901234567890123456789012";
+
+ // Don't specify nonce, should get a random one.
+ AuthorizationSetBuilder params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ EXPECT_EQ(message.size(), ciphertext.size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ string plaintext = DecryptMessage(ciphertext, params);
+ EXPECT_EQ(message, plaintext);
+
+ // Now specify a nonce, should fail
+ params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CBC)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NONCE, AidlBuf("abcdefghijklmnop"));
+ out_params.Clear();
+ EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED, Begin(KeyPurpose::ENCRYPT, params, &out_params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmRoundTripSuccess
+ *
+ * Verifies that AES GCM mode works.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params))
+ << "Begin encrypt";
+ string ciphertext;
+ AuthorizationSet update_out_params;
+ ASSERT_EQ(ErrorCode::OK, Finish(update_params, message, "", &update_out_params, &ciphertext));
+
+ ASSERT_EQ(ciphertext.length(), message.length() + 16);
+
+ // Grab nonce
+ begin_params.push_back(begin_out_params);
+
+ // Decrypt.
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt";
+ string plaintext;
+ int32_t input_consumed;
+ ASSERT_EQ(ErrorCode::OK,
+ Update(update_params, ciphertext, &update_out_params, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
+ EXPECT_EQ(message.length(), plaintext.length());
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmRoundTripWithDelaySuccess
+ *
+ * Verifies that AES GCM mode works, even when there's a long delay
+ * between operations.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmRoundTripWithDelaySuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params))
+ << "Begin encrypt";
+ string ciphertext;
+ AuthorizationSet update_out_params;
+ sleep(5);
+ ASSERT_EQ(ErrorCode::OK, Finish(update_params, message, "", &update_out_params, &ciphertext));
+
+ ASSERT_EQ(ciphertext.length(), message.length() + 16);
+
+ // Grab nonce
+ begin_params.push_back(begin_out_params);
+
+ // Decrypt.
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt";
+ string plaintext;
+ int32_t input_consumed;
+ sleep(5);
+ ASSERT_EQ(ErrorCode::OK,
+ Update(update_params, ciphertext, &update_out_params, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ sleep(5);
+ EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
+ EXPECT_EQ(message.length(), plaintext.length());
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmDifferentNonces
+ *
+ * Verifies that encrypting the same data with different nonces produces different outputs.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmDifferentNonces) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_CALLER_NONCE)));
+
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+ string nonce1 = "000000000000";
+ string nonce2 = "111111111111";
+ string nonce3 = "222222222222";
+
+ string ciphertext1 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, AidlBuf(nonce1));
+ string ciphertext2 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, AidlBuf(nonce2));
+ string ciphertext3 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, AidlBuf(nonce3));
+
+ ASSERT_NE(ciphertext1, ciphertext2);
+ ASSERT_NE(ciphertext1, ciphertext3);
+ ASSERT_NE(ciphertext2, ciphertext3);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmTooShortTag
+ *
+ * Verifies that AES GCM mode fails correctly when a too-short tag length is specified.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmTooShortTag) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+ string message = "123456789012345678901234567890123456";
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 96);
+
+ EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmTooShortTagOnDecrypt
+ *
+ * Verifies that AES GCM mode fails correctly when a too-short tag is provided to decryption.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto finish_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+ EXPECT_EQ(1U, begin_out_params.size());
+ ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk());
+
+ AuthorizationSet finish_out_params;
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext));
+
+ params = AuthorizationSetBuilder()
+ .Authorizations(begin_out_params)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 96);
+
+ // Decrypt.
+ EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmCorruptKey
+ *
+ * Verifies that AES GCM mode fails correctly when the decryption key is incorrect.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmCorruptKey) {
+ const uint8_t nonce_bytes[] = {
+ 0xb7, 0x94, 0x37, 0xae, 0x08, 0xff, 0x35, 0x5d, 0x7d, 0x8a, 0x4d, 0x0f,
+ };
+ string nonce = make_string(nonce_bytes);
+ const uint8_t ciphertext_bytes[] = {
+ 0xb3, 0xf6, 0x79, 0x9e, 0x8f, 0x93, 0x26, 0xf2, 0xdf, 0x1e, 0x80, 0xfc,
+ 0xd2, 0xcb, 0x16, 0xd7, 0x8c, 0x9d, 0xc7, 0xcc, 0x14, 0xbb, 0x67, 0x78,
+ 0x62, 0xdc, 0x6c, 0x63, 0x9b, 0x3a, 0x63, 0x38, 0xd2, 0x4b, 0x31, 0x2d,
+ 0x39, 0x89, 0xe5, 0x92, 0x0b, 0x5d, 0xbf, 0xc9, 0x76, 0x76, 0x5e, 0xfb,
+ 0xfe, 0x57, 0xbb, 0x38, 0x59, 0x40, 0xa7, 0xa4, 0x3b, 0xdf, 0x05, 0xbd,
+ 0xda, 0xe3, 0xc9, 0xd6, 0xa2, 0xfb, 0xbd, 0xfc, 0xc0, 0xcb, 0xa0,
+ };
+ string ciphertext = make_string(ciphertext_bytes);
+
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128)
+ .Authorization(TAG_NONCE, nonce.data(), nonce.size());
+
+ auto import_params = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_CALLER_NONCE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128);
+
+ // Import correct key and decrypt
+ const uint8_t key_bytes[] = {
+ 0xba, 0x76, 0x35, 0x4f, 0x0a, 0xed, 0x6e, 0x8d,
+ 0x91, 0xf4, 0x5c, 0x4f, 0xf5, 0xa0, 0x62, 0xdb,
+ };
+ string key = make_string(key_bytes);
+ ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key));
+ string plaintext = DecryptMessage(ciphertext, params);
+ CheckedDeleteKey();
+
+ // Corrupt key and attempt to decrypt
+ key[0] = 0;
+ ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext));
+ CheckedDeleteKey();
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmAadNoData
+ *
+ * Verifies that AES GCM mode works when provided additional authenticated data, but no data to
+ * encrypt.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmAadNoData) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string aad = "1234567890123456";
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto finish_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+ string ciphertext;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK, Finish(finish_params, "" /* input */, "" /* signature */,
+ &finish_out_params, &ciphertext));
+ EXPECT_TRUE(finish_out_params.empty());
+
+ // Grab nonce
+ params.push_back(begin_out_params);
+
+ // Decrypt.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::OK, Finish(finish_params, ciphertext, "" /* signature */,
+ &finish_out_params, &plaintext));
+
+ EXPECT_TRUE(finish_out_params.empty());
+
+ EXPECT_EQ("", plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmMultiPartAad
+ *
+ * Verifies that AES GCM mode works when provided additional authenticated data in multiple
+ * chunks.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmMultiPartAad) {
+ const size_t tag_bits = 128;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string message = "123456789012345678901234567890123456";
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, tag_bits);
+ AuthorizationSet begin_out_params;
+
+ auto update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3);
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+
+ // No data, AAD only.
+ string ciphertext;
+ int32_t input_consumed;
+ AuthorizationSet update_out_params;
+ EXPECT_EQ(ErrorCode::OK, Update(update_params, "" /* input */, &update_out_params, &ciphertext,
+ &input_consumed));
+ EXPECT_EQ(0U, input_consumed);
+ EXPECT_EQ(0U, ciphertext.size());
+ EXPECT_TRUE(update_out_params.empty());
+
+ // AAD and data.
+ EXPECT_EQ(ErrorCode::OK,
+ Update(update_params, message, &update_out_params, &ciphertext, &input_consumed));
+ EXPECT_EQ(message.size(), input_consumed);
+ EXPECT_TRUE(update_out_params.empty());
+
+ EXPECT_EQ(ErrorCode::OK, Finish("" /* input */, &ciphertext));
+ // Expect 128-bit (16-byte) tag appended to ciphertext.
+ EXPECT_EQ(message.size() + (tag_bits >> 3), ciphertext.size());
+
+ // Grab nonce.
+ begin_params.push_back(begin_out_params);
+
+ // Decrypt
+ update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foofoo", (size_t)6);
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::OK, Finish(update_params, ciphertext, "" /* signature */,
+ &update_out_params, &plaintext));
+ EXPECT_TRUE(update_out_params.empty());
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmAadOutOfOrder
+ *
+ * Verifies that AES GCM mode fails correctly when given AAD after data to encipher.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmAadOutOfOrder) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string message = "123456789012345678901234567890123456";
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+ AuthorizationSet begin_out_params;
+
+ auto update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3);
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+
+ // No data, AAD only.
+ string ciphertext;
+ int32_t input_consumed;
+ AuthorizationSet update_out_params;
+ EXPECT_EQ(ErrorCode::OK, Update(update_params, "" /* input */, &update_out_params, &ciphertext,
+ &input_consumed));
+ EXPECT_EQ(0U, input_consumed);
+ EXPECT_EQ(0U, ciphertext.size());
+ EXPECT_TRUE(update_out_params.empty());
+
+ // AAD and data.
+ EXPECT_EQ(ErrorCode::OK,
+ Update(update_params, message, &update_out_params, &ciphertext, &input_consumed));
+ EXPECT_EQ(message.size(), input_consumed);
+ EXPECT_TRUE(update_out_params.empty());
+
+ // More AAD
+ EXPECT_EQ(ErrorCode::INVALID_TAG,
+ Update(update_params, "", &update_out_params, &ciphertext, &input_consumed));
+
+ op_.clear();
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmBadAad
+ *
+ * Verifies that AES GCM decryption fails correctly when additional authenticated date is wrong.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmBadAad) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string message = "12345678901234567890123456789012";
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto finish_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6);
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+ string ciphertext;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext));
+
+ // Grab nonce
+ begin_params.push_back(begin_out_params);
+
+ finish_params = AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA,
+ "barfoo" /* Wrong AAD */, (size_t)6);
+
+ // Decrypt.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */,
+ &finish_out_params, &plaintext));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmWrongNonce
+ *
+ * Verifies that AES GCM decryption fails correctly when the nonce is incorrect.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmWrongNonce) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string message = "12345678901234567890123456789012";
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto finish_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6);
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+ string ciphertext;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext));
+
+ // Wrong nonce
+ begin_params.push_back(TAG_NONCE, AidlBuf("123456789012"));
+
+ // Decrypt.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */,
+ &finish_out_params, &plaintext));
+
+ // With wrong nonce, should have gotten garbage plaintext (or none).
+ EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmCorruptTag
+ *
+ * Verifies that AES GCM decryption fails correctly when the tag is wrong.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmCorruptTag) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string aad = "1234567890123456";
+ string message = "123456789012345678901234567890123456";
+
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto finish_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+ string ciphertext;
+ AuthorizationSet finish_out_params;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext));
+ EXPECT_TRUE(finish_out_params.empty());
+
+ // Corrupt tag
+ ++(*ciphertext.rbegin());
+
+ // Grab nonce
+ params.push_back(begin_out_params);
+
+ // Decrypt.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+ string plaintext;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */,
+ &finish_out_params, &plaintext));
+ EXPECT_TRUE(finish_out_params.empty());
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbRoundTripSuccess
+ *
+ * Verifies that 3DES is basically functional.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesEcbRoundTripSuccess) {
+ auto auths = AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE);
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(auths));
+ // Two-block message.
+ string message = "1234567890123456";
+ auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+ string ciphertext1 = EncryptMessage(message, inParams);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(string(message), inParams);
+ EXPECT_EQ(message.size(), ciphertext2.size());
+
+ // ECB is deterministic.
+ EXPECT_EQ(ciphertext1, ciphertext2);
+
+ string plaintext = DecryptMessage(ciphertext1, inParams);
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbNotAuthorized
+ *
+ * Verifies that CBC keys reject ECB usage.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesEcbNotAuthorized) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, inParams));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbPkcs7Padding
+ *
+ * Tests ECB mode with PKCS#7 padding, various message sizes.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesEcbPkcs7Padding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::PKCS7)));
+
+ for (size_t i = 0; i < 32; ++i) {
+ string message(i, 'a');
+ auto inParams =
+ AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ string ciphertext = EncryptMessage(message, inParams);
+ EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
+ string plaintext = DecryptMessage(ciphertext, inParams);
+ EXPECT_EQ(message, plaintext);
+ }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbNoPaddingKeyWithPkcs7Padding
+ *
+ * Verifies that keys configured for no padding reject PKCS7 padding
+ */
+TEST_P(EncryptionOperationsTest, TripleDesEcbNoPaddingKeyWithPkcs7Padding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+ for (size_t i = 0; i < 32; ++i) {
+ auto inParams =
+ AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, inParams));
+ }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesEcbPkcs7PaddingCorrupted
+ *
+ * Verifies that corrupted padding is detected.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesEcbPkcs7PaddingCorrupted) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::PKCS7)));
+
+ string message = "a";
+ string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7);
+ EXPECT_EQ(8U, ciphertext.size());
+ EXPECT_NE(ciphertext, message);
+ ++ciphertext[ciphertext.size() / 2];
+
+ AuthorizationSetBuilder begin_params;
+ begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB);
+ begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+ string plaintext;
+ int32_t input_consumed;
+ EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+}
+
+struct TripleDesTestVector {
+ const char* name;
+ const KeyPurpose purpose;
+ const BlockMode block_mode;
+ const PaddingMode padding_mode;
+ const char* key;
+ const char* iv;
+ const char* input;
+ const char* output;
+};
+
+// These test vectors are from NIST CAVP, plus a few custom variants to test padding, since all
+// of the NIST vectors are multiples of the block size.
+static const TripleDesTestVector kTripleDesTestVectors[] = {
+ {
+ "TECBMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+ "a2b5bc67da13dc92cd9d344aa238544a0e1fa79ef76810cd", // key
+ "", // IV
+ "329d86bdf1bc5af4", // input
+ "d946c2756d78633f", // output
+ },
+ {
+ "TECBMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE,
+ "49e692290d2a5e46bace79b9648a4c5d491004c262dc9d49", // key
+ "", // IV
+ "6b1540781b01ce1997adae102dbf3c5b", // input
+ "4d0dc182d6e481ac4a3dc6ab6976ccae", // output
+ },
+ {
+ "TECBMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+ "52daec2ac7dc1958377392682f37860b2cc1ea2304bab0e9", // key
+ "", // IV
+ "6daad94ce08acfe7", // input
+ "660e7d32dcc90e79", // output
+ },
+ {
+ "TECBMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE,
+ "7f8fe3d3f4a48394fb682c2919926d6ddfce8932529229ce", // key
+ "", // IV
+ "e9653a0a1f05d31b9acd12d73aa9879d", // input
+ "9b2ae9d998efe62f1b592e7e1df8ff38", // output
+ },
+ {
+ "TCBCMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+ "b5cb1504802326c73df186e3e352a20de643b0d63ee30e37", // key
+ "43f791134c5647ba", // IV
+ "dcc153cef81d6f24", // input
+ "92538bd8af18d3ba", // output
+ },
+ {
+ "TCBCMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE,
+ "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key
+ "c2e999cb6249023c", // IV
+ "c689aee38a301bb316da75db36f110b5", // input
+ "e9afaba5ec75ea1bbe65506655bb4ecb", // output
+ },
+ {
+ "TCBCMMT3 Encrypt 1 PKCS7 variant", KeyPurpose::ENCRYPT, BlockMode::CBC,
+ PaddingMode::PKCS7,
+ "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key
+ "c2e999cb6249023c", // IV
+ "c689aee38a301bb316da75db36f110b500", // input
+ "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156", // output
+ },
+ {
+ "TCBCMMT3 Encrypt 1 PKCS7 decrypted", KeyPurpose::DECRYPT, BlockMode::CBC,
+ PaddingMode::PKCS7,
+ "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key
+ "c2e999cb6249023c", // IV
+ "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156", // input
+ "c689aee38a301bb316da75db36f110b500", // output
+ },
+ {
+ "TCBCMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+ "5eb6040d46082c7aa7d06dfd08dfeac8c18364c1548c3ba1", // key
+ "41746c7e442d3681", // IV
+ "c53a7b0ec40600fe", // input
+ "d4f00eb455de1034", // output
+ },
+ {
+ "TCBCMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE,
+ "5b1cce7c0dc1ec49130dfb4af45785ab9179e567f2c7d549", // key
+ "3982bc02c3727d45", // IV
+ "6006f10adef52991fcc777a1238bbb65", // input
+ "edae09288e9e3bc05746d872b48e3b29", // output
+ },
+};
+
+/*
+ * EncryptionOperationsTest.TripleDesTestVector
+ *
+ * Verifies that NIST (plus a few extra) test vectors produce the correct results.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesTestVector) {
+ constexpr size_t num_tests = sizeof(kTripleDesTestVectors) / sizeof(TripleDesTestVector);
+ for (auto* test = kTripleDesTestVectors; test < kTripleDesTestVectors + num_tests; ++test) {
+ SCOPED_TRACE(test->name);
+ CheckTripleDesTestVector(test->purpose, test->block_mode, test->padding_mode,
+ hex2str(test->key), hex2str(test->iv), hex2str(test->input),
+ hex2str(test->output));
+ }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcRoundTripSuccess
+ *
+ * Validates CBC mode functionality.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcRoundTripSuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ ASSERT_GT(key_blob_.size(), 0U);
+
+ // Two-block message.
+ string message = "1234567890123456";
+ vector<uint8_t> iv1;
+ string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv1);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+
+ vector<uint8_t> iv2;
+ string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv2);
+ EXPECT_EQ(message.size(), ciphertext2.size());
+
+ // IVs should be random, so ciphertexts should differ.
+ EXPECT_NE(iv1, iv2);
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv1);
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCallerIv
+ *
+ * Validates that 3DES keys can allow caller-specified IVs, and use them correctly.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCallerIv) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CALLER_NONCE)
+ .Padding(PaddingMode::NONE)));
+ string message = "1234567890123456";
+ vector<uint8_t> iv;
+ // Don't specify IV, should get a random one.
+ string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+ EXPECT_EQ(8U, iv.size());
+
+ string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv);
+ EXPECT_EQ(message, plaintext);
+
+ // Now specify an IV, should also work.
+ iv = AidlBuf("abcdefgh");
+ string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, iv);
+
+ // Decrypt with correct IV.
+ plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, iv);
+ EXPECT_EQ(message, plaintext);
+
+ // Now try with wrong IV.
+ plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, AidlBuf("aaaaaaaa"));
+ EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCallerNonceProhibited.
+ *
+ * Verifies that 3DES keys without TAG_CALLER_NONCE do not allow caller-specified IVS.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCallerNonceProhibited) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ string message = "12345678901234567890123456789012";
+ vector<uint8_t> iv;
+ // Don't specify nonce, should get a random one.
+ string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv);
+ EXPECT_EQ(message.size(), ciphertext1.size());
+ EXPECT_EQ(8U, iv.size());
+
+ string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv);
+ EXPECT_EQ(message, plaintext);
+
+ // Now specify a nonce, should fail.
+ auto input_params = AuthorizationSetBuilder()
+ .Authorization(TAG_NONCE, AidlBuf("abcdefgh"))
+ .BlockMode(BlockMode::CBC)
+ .Padding(PaddingMode::NONE);
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED,
+ Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNotAuthorized
+ *
+ * Verifies that 3DES ECB-only keys do not allow CBC usage.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcNotAuthorized) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+ // Two-block message.
+ string message = "1234567890123456";
+ auto begin_params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNoPaddingWrongInputSize
+ *
+ * Verifies that unpadded CBC operations reject inputs that are not a multiple of block size.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcNoPaddingWrongInputSize) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+ // Message is slightly shorter than two blocks.
+ string message = "123456789012345";
+
+ auto begin_params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &output_params));
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, "", &ciphertext));
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCbcPkcs7Padding.
+ *
+ * Verifies that PKCS7 padding works correctly in CBC mode.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcPkcs7Padding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::PKCS7)));
+
+ // Try various message lengths; all should work.
+ for (size_t i = 0; i < 32; ++i) {
+ string message(i, 'a');
+ vector<uint8_t> iv;
+ string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
+ EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
+ string plaintext = DecryptMessage(ciphertext, BlockMode::CBC, PaddingMode::PKCS7, iv);
+ EXPECT_EQ(message, plaintext);
+ }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcNoPaddingKeyWithPkcs7Padding
+ *
+ * Verifies that a key that requires PKCS7 padding cannot be used in unpadded mode.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcNoPaddingKeyWithPkcs7Padding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ // Try various message lengths; all should fail.
+ for (size_t i = 0; i < 32; ++i) {
+ auto begin_params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
+ }
+}
+
+/*
+ * EncryptionOperationsTest.TripleDesCbcPkcs7PaddingCorrupted
+ *
+ * Verifies that corrupted PKCS7 padding is rejected during decryption.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcPkcs7PaddingCorrupted) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::PKCS7)));
+
+ string message = "a";
+ vector<uint8_t> iv;
+ string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
+ EXPECT_EQ(8U, ciphertext.size());
+ EXPECT_NE(ciphertext, message);
+ ++ciphertext[ciphertext.size() / 2];
+
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::CBC)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_NONCE, iv);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+ string plaintext;
+ int32_t input_consumed;
+ EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+}
+
+/*
+ * EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding.
+ *
+ * Verifies that 3DES CBC works with many different input sizes.
+ */
+TEST_P(EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Padding(PaddingMode::NONE)));
+
+ int increment = 7;
+ string message(240, 'a');
+ AuthorizationSet input_params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
+
+ string ciphertext;
+ int32_t input_consumed;
+ for (size_t i = 0; i < message.size(); i += increment)
+ EXPECT_EQ(ErrorCode::OK,
+ Update(message.substr(i, increment), &ciphertext, &input_consumed));
+ EXPECT_EQ(ErrorCode::OK, Finish(&ciphertext));
+ EXPECT_EQ(message.size(), ciphertext.size());
+
+ // Move TAG_NONCE into input_params
+ input_params = output_params;
+ input_params.push_back(TAG_BLOCK_MODE, BlockMode::CBC);
+ input_params.push_back(TAG_PADDING, PaddingMode::NONE);
+ output_params.Clear();
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, input_params, &output_params));
+ string plaintext;
+ for (size_t i = 0; i < ciphertext.size(); i += increment)
+ EXPECT_EQ(ErrorCode::OK,
+ Update(ciphertext.substr(i, increment), &plaintext, &input_consumed));
+ EXPECT_EQ(ErrorCode::OK, Finish(&plaintext));
+ EXPECT_EQ(ciphertext.size(), plaintext.size());
+ EXPECT_EQ(message, plaintext);
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(EncryptionOperationsTest);
+
+typedef KeyMintAidlTestBase MaxOperationsTest;
+
+/*
+ * MaxOperationsTest.TestLimitAes
+ *
+ * Verifies that the max uses per boot tag works correctly with AES keys.
+ */
+TEST_P(MaxOperationsTest, TestLimitAes) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .EcbMode()
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+ string message = "1234567890123456";
+
+ auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
+
+ EncryptMessage(message, params);
+ EncryptMessage(message, params);
+ EncryptMessage(message, params);
+
+ // Fourth time should fail.
+ EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * MaxOperationsTest.TestLimitAes
+ *
+ * Verifies that the max uses per boot tag works correctly with RSA keys.
+ */
+TEST_P(MaxOperationsTest, TestLimitRsa) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .NoDigestOrPadding()
+ .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+ string message = "1234567890123456";
+
+ auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+ SignMessage(message, params);
+ SignMessage(message, params);
+ SignMessage(message, params);
+
+ // Fourth time should fail.
+ EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::SIGN, params));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(MaxOperationsTest);
+
+typedef KeyMintAidlTestBase AddEntropyTest;
+
+/*
+ * AddEntropyTest.AddEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up. There's no way to test that entropy
+ * is actually added.
+ */
+TEST_P(AddEntropyTest, AddEntropy) {
+ string data = "foo";
+ EXPECT_TRUE(keyMint().addRngEntropy(vector<uint8_t>(data.begin(), data.end())).isOk());
+}
+
+/*
+ * AddEntropyTest.AddEmptyEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up when given an empty buffer.
+ */
+TEST_P(AddEntropyTest, AddEmptyEntropy) {
+ EXPECT_TRUE(keyMint().addRngEntropy(AidlBuf()).isOk());
+}
+
+/*
+ * AddEntropyTest.AddLargeEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up when given a largish amount of data.
+ */
+TEST_P(AddEntropyTest, AddLargeEntropy) {
+ EXPECT_TRUE(keyMint().addRngEntropy(AidlBuf(string(2 * 1024, 'a'))).isOk());
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(AddEntropyTest);
+
+typedef KeyMintAidlTestBase AttestationTest;
+
+/*
+ * AttestationTest.RsaAttestation
+ *
+ * Verifies that attesting to RSA keys works and generates the expected output.
+ */
+// TODO(seleneh) add attestation tests back after decided on the new attestation
+// behavior under generateKey and importKey
+
+typedef KeyMintAidlTestBase KeyDeletionTest;
+
+/**
+ * KeyDeletionTest.DeleteKey
+ *
+ * This test checks that if rollback protection is implemented, DeleteKey invalidates a formerly
+ * valid key blob.
+ */
+TEST_P(KeyDeletionTest, DeleteKey) {
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+
+ // Delete must work if rollback protection is implemented
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+
+ ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
+
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+ &begin_out_params));
+ AbortIfNeeded();
+ key_blob_ = AidlBuf();
+ }
+}
+
+/**
+ * KeyDeletionTest.DeleteInvalidKey
+ *
+ * This test checks that the HAL excepts invalid key blobs..
+ */
+TEST_P(KeyDeletionTest, DeleteInvalidKey) {
+ // Generate key just to check if rollback protection is implemented
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+
+ // Delete must work if rollback protection is implemented
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+
+ // Delete the key we don't care about the result at this point.
+ DeleteKey();
+
+ // Now create an invalid key blob and delete it.
+ key_blob_ = AidlBuf("just some garbage data which is not a valid key blob");
+
+ ASSERT_EQ(ErrorCode::OK, DeleteKey());
+ }
+}
+
+/**
+ * KeyDeletionTest.DeleteAllKeys
+ *
+ * This test is disarmed by default. To arm it use --arm_deleteAllKeys.
+ *
+ * BEWARE: This test has serious side effects. All user keys will be lost! This includes
+ * FBE/FDE encryption keys, which means that the device will not even boot until after the
+ * device has been wiped manually (e.g., fastboot flashall -w), and new FBE/FDE keys have
+ * been provisioned. Use this test only on dedicated testing devices that have no valuable
+ * credentials stored in Keystore/Keymint.
+ */
+TEST_P(KeyDeletionTest, DeleteAllKeys) {
+ if (!arm_deleteAllKeys) return;
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+
+ // Delete must work if rollback protection is implemented
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+
+ ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
+
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+ &begin_out_params));
+ AbortIfNeeded();
+ key_blob_ = AidlBuf();
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(KeyDeletionTest);
+
+using UpgradeKeyTest = KeyMintAidlTestBase;
+
+/*
+ * UpgradeKeyTest.UpgradeKey
+ *
+ * Verifies that calling upgrade key on an up-to-date key works (i.e. does nothing).
+ */
+TEST_P(UpgradeKeyTest, UpgradeKey) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .AesEncryptionKey(128)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)));
+
+ auto result = UpgradeKey(key_blob_);
+
+ // Key doesn't need upgrading. Should get okay, but no new key blob.
+ EXPECT_EQ(result, std::make_pair(ErrorCode::OK, vector<uint8_t>()));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(UpgradeKeyTest);
+
+using ClearOperationsTest = KeyMintAidlTestBase;
+
+/*
+ * ClearSlotsTest.TooManyOperations
+ *
+ * Verifies that TOO_MANY_OPERATIONS is returned after the max number of
+ * operations are started without being finished or aborted. Also verifies
+ * that aborting the operations clears the operations.
+ *
+ */
+TEST_P(ClearOperationsTest, TooManyOperations) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+ constexpr size_t max_operations = 100; // set to arbituary large number
+ sp<IKeyMintOperation> op_handles[max_operations];
+ AuthorizationSet out_params;
+ ErrorCode result;
+ size_t i;
+
+ for (i = 0; i < max_operations; i++) {
+ result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+ if (ErrorCode::OK != result) {
+ break;
+ }
+ }
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
+ // Try again just in case there's a weird overflow bug
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ for (size_t j = 0; j < i; j++) {
+ EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
+ << "Aboort failed for i = " << j << std::endl;
+ }
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ AbortIfNeeded();
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(ClearOperationsTest);
+
+typedef KeyMintAidlTestBase TransportLimitTest;
+
+/*
+ * TransportLimitTest.FinishInput
+ *
+ * Verifies that passing input data to finish succeeds as expected.
+ */
+TEST_P(TransportLimitTest, LargeFinishInput) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::NONE)));
+
+ for (int msg_size = 8 /* 256 bytes */; msg_size <= 11 /* 2 KiB */; msg_size++) {
+ auto cipher_params =
+ AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+
+ AuthorizationSet out_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, cipher_params, &out_params));
+
+ string plain_message = std::string(1 << msg_size, 'x');
+ string encrypted_message;
+ auto rc = Finish(plain_message, &encrypted_message);
+
+ EXPECT_EQ(ErrorCode::OK, rc);
+ EXPECT_EQ(plain_message.size(), encrypted_message.size())
+ << "Encrypt finish returned OK, but did not consume all of the given input";
+ cipher_params.push_back(out_params);
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
+
+ string decrypted_message;
+ rc = Finish(encrypted_message, &decrypted_message);
+ EXPECT_EQ(ErrorCode::OK, rc);
+ EXPECT_EQ(plain_message.size(), decrypted_message.size())
+ << "Decrypt finish returned OK, did not consume all of the given input";
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(TransportLimitTest);
+
+} // namespace test
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] == '-') {
+ if (std::string(argv[i]) == "--arm_deleteAllKeys") {
+ arm_deleteAllKeys = true;
+ }
+ if (std::string(argv[i]) == "--dump_attestations") {
+ dump_Attestations = true;
+ }
+ }
+ }
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
+}
diff --git a/keymint/support/Android.bp b/keymint/support/Android.bp
new file mode 100644
index 0000000..432416e
--- /dev/null
+++ b/keymint/support/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library {
+ name: "libkeymintSupport",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "attestation_record.cpp",
+ "authorization_set.cpp",
+ "keymint_utils.cpp",
+ "key_param_output.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ shared_libs: [
+ "android.hardware.keymint-cpp",
+ "libbase",
+ "libcrypto",
+ "libutils",
+ ],
+}
diff --git a/keymint/support/OWNERS b/keymint/support/OWNERS
new file mode 100644
index 0000000..a93b171
--- /dev/null
+++ b/keymint/support/OWNERS
@@ -0,0 +1,4 @@
+jbires@google.com
+jdanis@google.com
+seleneh@google.com
+swillden@google.com
diff --git a/keymint/support/attestation_record.cpp b/keymint/support/attestation_record.cpp
new file mode 100644
index 0000000..e565974
--- /dev/null
+++ b/keymint/support/attestation_record.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <keymintSupport/attestation_record.h>
+
+#include <android/hardware/keymint/Tag.h>
+#include <android/hardware/keymint/TagType.h>
+
+#include <android-base/logging.h>
+#include <assert.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <keymintSupport/authorization_set.h>
+#include <keymintSupport/openssl_utils.h>
+
+#define AT __FILE__ ":" << __LINE__
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+struct stack_st_ASN1_TYPE_Delete {
+ void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
+};
+
+struct ASN1_STRING_Delete {
+ void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
+};
+
+struct ASN1_TYPE_Delete {
+ void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
+};
+
+#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
+
+typedef struct km_root_of_trust {
+ ASN1_OCTET_STRING* verified_boot_key;
+ ASN1_BOOLEAN device_locked;
+ ASN1_ENUMERATED* verified_boot_state;
+ ASN1_OCTET_STRING* verified_boot_hash;
+} KM_ROOT_OF_TRUST;
+
+ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_hash, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+
+typedef struct km_auth_list {
+ ASN1_INTEGER_SET* purpose;
+ ASN1_INTEGER* algorithm;
+ ASN1_INTEGER* key_size;
+ ASN1_INTEGER_SET* digest;
+ ASN1_INTEGER_SET* padding;
+ ASN1_INTEGER* ec_curve;
+ ASN1_INTEGER* rsa_public_exponent;
+ ASN1_INTEGER* active_date_time;
+ ASN1_INTEGER* origination_expire_date_time;
+ ASN1_INTEGER* usage_expire_date_time;
+ ASN1_NULL* no_auth_required;
+ ASN1_INTEGER* user_auth_type;
+ ASN1_INTEGER* auth_timeout;
+ ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* all_applications;
+ ASN1_OCTET_STRING* application_id;
+ ASN1_INTEGER* creation_date_time;
+ ASN1_INTEGER* origin;
+ ASN1_NULL* rollback_resistance;
+ KM_ROOT_OF_TRUST* root_of_trust;
+ ASN1_INTEGER* os_version;
+ ASN1_INTEGER* os_patchlevel;
+ ASN1_OCTET_STRING* attestation_application_id;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
+ ASN1_INTEGER* vendor_patchlevel;
+ ASN1_INTEGER* boot_patchlevel;
+ ASN1_NULL* early_boot_only;
+ ASN1_NULL* device_unique_attestation;
+ ASN1_NULL* storage_key;
+ ASN1_NULL* identity_credential;
+} KM_AUTH_LIST;
+
+ASN1_SEQUENCE(KM_AUTH_LIST) = {
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+ TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+ TAG_ROLLBACK_RESISTANCE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+ TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+ TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+ TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+ TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+ TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+ TAG_CREATION_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
+ TAG_VENDOR_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
+ TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, storage_key, ASN1_NULL, TAG_STORAGE_KEY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
+ TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
+
+} ASN1_SEQUENCE_END(KM_AUTH_LIST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
+
+typedef struct km_key_description {
+ ASN1_INTEGER* attestation_version;
+ ASN1_ENUMERATED* attestation_security_level;
+ ASN1_INTEGER* keymint_version;
+ ASN1_ENUMERATED* keymint_security_level;
+ ASN1_OCTET_STRING* attestation_challenge;
+ KM_AUTH_LIST* software_enforced;
+ KM_AUTH_LIST* tee_enforced;
+ ASN1_INTEGER* unique_id;
+} KM_KEY_DESCRIPTION;
+
+ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymint_version, ASN1_INTEGER),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymint_security_level, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
+} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
+IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
+
+template <Tag tag>
+void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag<TagType::ENUM_REP, tag> ttag,
+ AuthorizationSet* auth_list) {
+ typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
+ for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
+ auth_list->push_back(
+ ttag, static_cast<ValueT>(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i))));
+ }
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ENUM, tag> ttag,
+ AuthorizationSet* auth_list) {
+ typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
+ if (!asn1_int) return;
+ auth_list->push_back(ttag, static_cast<ValueT>(ASN1_INTEGER_get(asn1_int)));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::UINT, tag> ttag,
+ AuthorizationSet* auth_list) {
+ if (!asn1_int) return;
+ auth_list->push_back(ttag, ASN1_INTEGER_get(asn1_int));
+}
+
+BIGNUM* construct_uint_max() {
+ BIGNUM* value = BN_new();
+ BIGNUM_Ptr one(BN_new());
+ BN_one(one.get());
+ BN_lshift(value, one.get(), 32);
+ return value;
+}
+
+uint64_t BignumToUint64(BIGNUM* num) {
+ static_assert((sizeof(BN_ULONG) == sizeof(uint32_t)) || (sizeof(BN_ULONG) == sizeof(uint64_t)),
+ "This implementation only supports 32 and 64-bit BN_ULONG");
+ if (sizeof(BN_ULONG) == sizeof(uint32_t)) {
+ BIGNUM_Ptr uint_max(construct_uint_max());
+ BIGNUM_Ptr hi(BN_new()), lo(BN_new());
+ BN_CTX_Ptr ctx(BN_CTX_new());
+ BN_div(hi.get(), lo.get(), num, uint_max.get(), ctx.get());
+ return static_cast<uint64_t>(BN_get_word(hi.get())) << 32 | BN_get_word(lo.get());
+ } else if (sizeof(BN_ULONG) == sizeof(uint64_t)) {
+ return BN_get_word(num);
+ } else {
+ return 0;
+ }
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ULONG, tag> ttag,
+ AuthorizationSet* auth_list) {
+ if (!asn1_int) return;
+ BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+ auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::DATE, tag> ttag,
+ AuthorizationSet* auth_list) {
+ if (!asn1_int) return;
+ BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+ auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag<TagType::BOOL, tag> ttag,
+ AuthorizationSet* auth_list) {
+ if (!asn1_null) return;
+ auth_list->push_back(ttag);
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag<TagType::BYTES, tag> ttag,
+ AuthorizationSet* auth_list) {
+ if (!asn1_string) return;
+ vector<uint8_t> buf(asn1_string->data, asn1_string->data + asn1_string->length);
+ auth_list->push_back(ttag, buf);
+}
+
+// Extract the values from the specified ASN.1 record and place them in auth_list.
+static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
+ if (!record) return ErrorCode::OK;
+
+ copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+ copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+ copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
+ copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+ copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+ copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+ copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
+ copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+ copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
+ copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+ copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
+ copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
+ copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+ copyAuthTag(record->padding, TAG_PADDING, auth_list);
+ copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
+ copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+ copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+ copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+ copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
+ copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
+ copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
+ copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
+ auth_list);
+ copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
+ auth_list);
+ copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
+ copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+ copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
+ copyAuthTag(record->storage_key, TAG_STORAGE_KEY, auth_list);
+ copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
+
+ return ErrorCode::OK;
+}
+
+MAKE_OPENSSL_PTR_TYPE(KM_KEY_DESCRIPTION)
+
+// Parse the DER-encoded attestation record, placing the results in keymint_version,
+// attestation_challenge, software_enforced, tee_enforced and unique_id.
+ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ uint32_t* attestation_version, //
+ SecurityLevel* attestation_security_level,
+ uint32_t* keymint_version, SecurityLevel* keymint_security_level,
+ vector<uint8_t>* attestation_challenge,
+ AuthorizationSet* software_enforced,
+ AuthorizationSet* tee_enforced, //
+ vector<uint8_t>* unique_id) {
+ const uint8_t* p = asn1_key_desc;
+ KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
+ if (!record.get()) return ErrorCode::UNKNOWN_ERROR;
+
+ *attestation_version = ASN1_INTEGER_get(record->attestation_version);
+ *attestation_security_level =
+ static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->attestation_security_level));
+ *keymint_version = ASN1_INTEGER_get(record->keymint_version);
+ *keymint_security_level =
+ static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->keymint_security_level));
+
+ auto& chall = record->attestation_challenge;
+ attestation_challenge->resize(chall->length);
+ memcpy(attestation_challenge->data(), chall->data, chall->length);
+ auto& uid = record->unique_id;
+ unique_id->resize(uid->length);
+ memcpy(unique_id->data(), uid->data, uid->length);
+
+ ErrorCode error = extract_auth_list(record->software_enforced, software_enforced);
+ if (error != ErrorCode::OK) return error;
+
+ return extract_auth_list(record->tee_enforced, tee_enforced);
+}
+
+ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ vector<uint8_t>* verified_boot_key,
+ keymint_verified_boot_t* verified_boot_state, bool* device_locked,
+ vector<uint8_t>* verified_boot_hash) {
+ if (!verified_boot_key || !verified_boot_state || !device_locked || !verified_boot_hash) {
+ LOG(ERROR) << AT << "null pointer input(s)";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+ const uint8_t* p = asn1_key_desc;
+ KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
+ if (!record.get()) {
+ LOG(ERROR) << AT << "Failed record parsing";
+ return ErrorCode::UNKNOWN_ERROR;
+ }
+
+ KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+ if (record->tee_enforced && record->tee_enforced->root_of_trust) {
+ root_of_trust = record->tee_enforced->root_of_trust;
+ } else if (record->software_enforced && record->software_enforced->root_of_trust) {
+ root_of_trust = record->software_enforced->root_of_trust;
+ } else {
+ LOG(ERROR) << AT << " Failed root of trust parsing";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+ if (!root_of_trust->verified_boot_key) {
+ LOG(ERROR) << AT << " Failed verified boot key parsing";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+
+ auto& vb_key = root_of_trust->verified_boot_key;
+ verified_boot_key->resize(vb_key->length);
+ memcpy(verified_boot_key->data(), vb_key->data, vb_key->length);
+
+ *verified_boot_state = static_cast<keymint_verified_boot_t>(
+ ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
+ if (!verified_boot_state) {
+ LOG(ERROR) << AT << " Failed verified boot state parsing";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+
+ *device_locked = root_of_trust->device_locked;
+ if (!device_locked) {
+ LOG(ERROR) << AT << " Failed device locked parsing";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+
+ auto& vb_hash = root_of_trust->verified_boot_hash;
+ if (!vb_hash) {
+ LOG(ERROR) << AT << " Failed verified boot hash parsing";
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+ verified_boot_hash->resize(vb_hash->length);
+ memcpy(verified_boot_hash->data(), vb_hash->data, vb_hash->length);
+ return ErrorCode::OK; // KM_ERROR_OK;
+}
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/support/authorization_set.cpp b/keymint/support/authorization_set.cpp
new file mode 100644
index 0000000..9fc4e13
--- /dev/null
+++ b/keymint/support/authorization_set.cpp
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <keymintSupport/authorization_set.h>
+
+#include <assert.h>
+
+#include <android-base/logging.h>
+#include <sstream>
+
+#include <android/hardware/keymint/Algorithm.h>
+#include <android/hardware/keymint/BlockMode.h>
+#include <android/hardware/keymint/Digest.h>
+#include <android/hardware/keymint/KeyParameter.h>
+#include <android/hardware/keymint/KeyPurpose.h>
+#include <android/hardware/keymint/TagType.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+void AuthorizationSet::Sort() {
+ std::sort(data_.begin(), data_.end());
+}
+
+void AuthorizationSet::Deduplicate() {
+ if (data_.empty()) return;
+
+ Sort();
+ std::vector<KeyParameter> result;
+
+ auto curr = data_.begin();
+ auto prev = curr++;
+ for (; curr != data_.end(); ++prev, ++curr) {
+ if (prev->tag == Tag::INVALID) continue;
+
+ if (*prev != *curr) {
+ result.push_back(std::move(*prev));
+ }
+ }
+ result.push_back(std::move(*prev));
+
+ std::swap(data_, result);
+}
+
+void AuthorizationSet::Union(const AuthorizationSet& other) {
+ data_.insert(data_.end(), other.data_.begin(), other.data_.end());
+ Deduplicate();
+}
+
+void AuthorizationSet::Subtract(const AuthorizationSet& other) {
+ Deduplicate();
+
+ auto i = other.begin();
+ while (i != other.end()) {
+ int pos = -1;
+ do {
+ pos = find(i->tag, pos);
+ if (pos != -1 && (*i == data_[pos])) {
+ data_.erase(data_.begin() + pos);
+ break;
+ }
+ } while (pos != -1);
+ ++i;
+ }
+}
+
+void AuthorizationSet::Filter(std::function<bool(const KeyParameter&)> doKeep) {
+ std::vector<KeyParameter> result;
+ for (auto& param : data_) {
+ if (doKeep(param)) {
+ result.push_back(std::move(param));
+ }
+ }
+ std::swap(data_, result);
+}
+
+KeyParameter& AuthorizationSet::operator[](int at) {
+ return data_[at];
+}
+
+const KeyParameter& AuthorizationSet::operator[](int at) const {
+ return data_[at];
+}
+
+void AuthorizationSet::Clear() {
+ data_.clear();
+}
+
+size_t AuthorizationSet::GetTagCount(Tag tag) const {
+ size_t count = 0;
+ for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count;
+ return count;
+}
+
+int AuthorizationSet::find(Tag tag, int begin) const {
+ auto iter = data_.begin() + (1 + begin);
+
+ while (iter != data_.end() && iter->tag != tag) ++iter;
+
+ if (iter != data_.end()) return iter - data_.begin();
+ return -1;
+}
+
+bool AuthorizationSet::erase(int index) {
+ auto pos = data_.begin() + index;
+ if (pos != data_.end()) {
+ data_.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+ int pos = find(tag);
+ if (pos == -1) return {};
+ return data_[pos];
+}
+
+/**
+ * Persistent format is:
+ * | 32 bit indirect_size |
+ * --------------------------------
+ * | indirect_size bytes of data | this is where the blob data is stored
+ * --------------------------------
+ * | 32 bit element_count | number of entries
+ * | 32 bit elements_size | total bytes used by entries (entries have variable length)
+ * --------------------------------
+ * | elementes_size bytes of data | where the elements are stored
+ */
+
+/**
+ * Persistent format of blobs and bignums:
+ * | 32 bit tag |
+ * | 32 bit blob_length |
+ * | 32 bit indirect_offset |
+ */
+
+struct OutStreams {
+ std::ostream& indirect;
+ std::ostream& elements;
+ size_t skipped;
+};
+
+OutStreams& serializeParamValue(OutStreams& out, const vector<uint8_t>& blob) {
+ uint32_t buffer;
+
+ // write blob_length
+ auto blob_length = blob.size();
+ if (blob_length > std::numeric_limits<uint32_t>::max()) {
+ out.elements.setstate(std::ios_base::badbit);
+ return out;
+ }
+ buffer = blob_length;
+ out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+ // write indirect_offset
+ auto offset = out.indirect.tellp();
+ if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
+ uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check
+ out.elements.setstate(std::ios_base::badbit);
+ return out;
+ }
+ buffer = offset;
+ out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+ // write blob to indirect stream
+ if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
+
+ return out;
+}
+
+template <typename T>
+OutStreams& serializeParamValue(OutStreams& out, const T& value) {
+ out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
+ return out;
+}
+
+OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
+ // skip invalid entries.
+ ++out.skipped;
+ return out;
+}
+template <typename T>
+OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
+ out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t));
+ return serializeParamValue(out, accessTagValue(ttag, param));
+}
+
+template <typename... T>
+struct choose_serializer;
+template <typename... Tags>
+struct choose_serializer<MetaList<Tags...>> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ return choose_serializer<Tags...>::serialize(out, param);
+ }
+};
+
+template <>
+struct choose_serializer<> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ LOG(WARNING) << "Trying to serialize unknown tag " << unsigned(param.tag)
+ << ". Did you forget to add it to all_tags_t?";
+ ++out.skipped;
+ return out;
+ }
+};
+
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_serializer<android::hardware::keymint::TypedTag<tag_type, tag>, Tail...> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ if (param.tag == tag) {
+ return android::hardware::keymint::serialize(TypedTag<tag_type, tag>(), out, param);
+ } else {
+ return choose_serializer<Tail...>::serialize(out, param);
+ }
+ }
+};
+
+OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ return choose_serializer<all_tags_t>::serialize(out, param);
+}
+
+std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
+ std::stringstream indirect;
+ std::stringstream elements;
+ OutStreams streams = {indirect, elements, 0};
+ for (const auto& param : params) {
+ serialize(streams, param);
+ }
+ if (indirect.bad() || elements.bad()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ auto pos = indirect.tellp();
+ if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ uint32_t indirect_size = pos;
+ pos = elements.tellp();
+ if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ uint32_t elements_size = pos;
+ uint32_t element_count = params.size() - streams.skipped;
+
+ out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
+
+ pos = out.tellp();
+ if (indirect_size) out << indirect.rdbuf();
+ assert(out.tellp() - pos == indirect_size);
+
+ out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
+ out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
+
+ pos = out.tellp();
+ if (elements_size) out << elements.rdbuf();
+ assert(out.tellp() - pos == elements_size);
+
+ return out;
+}
+
+struct InStreams {
+ std::istream& indirect;
+ std::istream& elements;
+ size_t invalids;
+};
+
+InStreams& deserializeParamValue(InStreams& in, vector<uint8_t>* blob) {
+ uint32_t blob_length = 0;
+ uint32_t offset = 0;
+ in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
+ blob->resize(blob_length);
+ in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
+ in.indirect.seekg(offset);
+ in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
+ return in;
+}
+
+template <typename T>
+InStreams& deserializeParamValue(InStreams& in, T* value) {
+ in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
+ return in;
+}
+
+InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
+ // there should be no invalid KeyParameters but if handle them as zero sized.
+ ++in.invalids;
+ return in;
+}
+
+template <typename T>
+InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
+ return deserializeParamValue(in, &accessTagValue(ttag, *param));
+}
+
+template <typename... T>
+struct choose_deserializer;
+template <typename... Tags>
+struct choose_deserializer<MetaList<Tags...>> {
+ static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ return choose_deserializer<Tags...>::deserialize(in, param);
+ }
+};
+template <>
+struct choose_deserializer<> {
+ static InStreams& deserialize(InStreams& in, KeyParameter*) {
+ // encountered an unknown tag -> fail parsing
+ in.elements.setstate(std::ios_base::badbit);
+ return in;
+ }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
+ static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ if (param->tag == tag) {
+ return android::hardware::keymint::deserialize(TypedTag<tag_type, tag>(), in, param);
+ } else {
+ return choose_deserializer<Tail...>::deserialize(in, param);
+ }
+ }
+};
+
+InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag));
+ return choose_deserializer<all_tags_t>::deserialize(in, param);
+}
+
+std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
+ uint32_t indirect_size = 0;
+ in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
+ std::string indirect_buffer(indirect_size, '\0');
+ if (indirect_buffer.size() != indirect_size) {
+ in.setstate(std::ios_base::badbit);
+ return in;
+ }
+ in.read(&indirect_buffer[0], indirect_buffer.size());
+
+ uint32_t element_count = 0;
+ in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
+ uint32_t elements_size = 0;
+ in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
+
+ std::string elements_buffer(elements_size, '\0');
+ if (elements_buffer.size() != elements_size) {
+ in.setstate(std::ios_base::badbit);
+ return in;
+ }
+ in.read(&elements_buffer[0], elements_buffer.size());
+
+ if (in.bad()) return in;
+
+ // TODO write one-shot stream buffer to avoid copying here
+ std::stringstream indirect(indirect_buffer);
+ std::stringstream elements(elements_buffer);
+ InStreams streams = {indirect, elements, 0};
+
+ params->resize(element_count);
+
+ for (uint32_t i = 0; i < element_count; ++i) {
+ deserialize(streams, &(*params)[i]);
+ }
+
+ /*
+ * There are legacy blobs which have invalid tags in them due to a bug during serialization.
+ * This makes sure that invalid tags are filtered from the result before it is returned.
+ */
+ if (streams.invalids > 0) {
+ std::vector<KeyParameter> filtered(element_count - streams.invalids);
+ auto ifiltered = filtered.begin();
+ for (auto& p : *params) {
+ if (p.tag != Tag::INVALID) {
+ *ifiltered++ = std::move(p);
+ }
+ }
+ *params = std::move(filtered);
+ }
+ return in;
+}
+
+void AuthorizationSet::Serialize(std::ostream* out) const {
+ serialize(*out, data_);
+}
+
+void AuthorizationSet::Deserialize(std::istream* in) {
+ deserialize(*in, &data_);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
+ uint64_t public_exponent) {
+ Authorization(TAG_ALGORITHM, Algorithm::RSA);
+ Authorization(TAG_KEY_SIZE, key_size);
+ Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
+ return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::EC);
+ Authorization(TAG_KEY_SIZE, key_size);
+ return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) {
+ Authorization(TAG_ALGORITHM, Algorithm::EC);
+ Authorization(TAG_EC_CURVE, curve);
+ return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::AES);
+ return Authorization(TAG_KEY_SIZE, key_size);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES);
+ return Authorization(TAG_KEY_SIZE, key_size);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::HMAC);
+ Authorization(TAG_KEY_SIZE, key_size);
+ return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
+ uint64_t public_exponent) {
+ RsaKey(key_size, public_exponent);
+ return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size,
+ uint64_t public_exponent) {
+ RsaKey(key_size, public_exponent);
+ return EncryptionKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
+ EcdsaKey(key_size);
+ return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) {
+ EcdsaKey(curve);
+ return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
+ AesKey(key_size);
+ return EncryptionKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) {
+ TripleDesKey(key_size);
+ return EncryptionKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
+ Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
+ return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
+ Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+ return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
+ Authorization(TAG_DIGEST, Digest::NONE);
+ return Authorization(TAG_PADDING, PaddingMode::NONE);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
+ return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) {
+ return BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, minMacLength);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) {
+ return BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, macLength);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode(
+ std::initializer_list<android::hardware::keymint::BlockMode> blockModes) {
+ for (auto mode : blockModes) {
+ push_back(TAG_BLOCK_MODE, mode);
+ }
+ return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(
+ std::vector<android::hardware::keymint::Digest> digests) {
+ for (auto digest : digests) {
+ push_back(TAG_DIGEST, digest);
+ }
+ return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::Padding(
+ std::initializer_list<PaddingMode> paddingModes) {
+ for (auto paddingMode : paddingModes) {
+ push_back(TAG_PADDING, paddingMode);
+ }
+ return *this;
+}
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/support/include/keymintSupport/attestation_record.h b/keymint/support/include/keymintSupport/attestation_record.h
new file mode 100644
index 0000000..7a69789
--- /dev/null
+++ b/keymint/support/include/keymintSupport/attestation_record.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/keymint/ErrorCode.h>
+#include <android/hardware/keymint/IKeyMintDevice.h>
+
+#include <keymintSupport/attestation_record.h>
+#include <keymintSupport/authorization_set.h>
+#include <keymintSupport/openssl_utils.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using android::hardware::keymint::KeyParameter;
+using android::hardware::keymint::Tag;
+using android::hardware::keymint::TAG_ALGORITHM;
+
+class AuthorizationSet;
+
+/**
+ * The OID for Android attestation records. For the curious, it breaks down as follows:
+ *
+ * 1 = ISO
+ * 3 = org
+ * 6 = DoD (Huh? OIDs are weird.)
+ * 1 = IANA
+ * 4 = Private
+ * 1 = Enterprises
+ * 11129 = Google
+ * 2 = Google security
+ * 1 = certificate extension
+ * 17 = Android attestation extension.
+ */
+static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
+
+enum keymint_verified_boot_t {
+ KM_VERIFIED_BOOT_VERIFIED = 0,
+ KM_VERIFIED_BOOT_SELF_SIGNED = 1,
+ KM_VERIFIED_BOOT_UNVERIFIED = 2,
+ KM_VERIFIED_BOOT_FAILED = 3,
+};
+
+struct RootOfTrust {
+ SecurityLevel security_level;
+ vector<uint8_t> verified_boot_key;
+ vector<uint8_t> verified_boot_hash;
+ keymint_verified_boot_t verified_boot_state;
+ bool device_locked;
+};
+
+struct AttestationRecord {
+ RootOfTrust root_of_trust;
+ uint32_t attestation_version;
+ SecurityLevel attestation_security_level;
+ uint32_t keymint_version;
+ SecurityLevel keymint_security_level;
+ std::vector<uint8_t> attestation_challenge;
+ AuthorizationSet software_enforced;
+ AuthorizationSet hardware_enforced;
+ std::vector<uint8_t> unique_id;
+};
+
+ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ uint32_t* attestation_version, //
+ SecurityLevel* attestation_security_level,
+ uint32_t* keymint_version, SecurityLevel* keymint_security_level,
+ std::vector<uint8_t>* attestation_challenge,
+ AuthorizationSet* software_enforced,
+ AuthorizationSet* tee_enforced, //
+ std::vector<uint8_t>* unique_id);
+
+ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ std::vector<uint8_t>* verified_boot_key,
+ keymint_verified_boot_t* verified_boot_state, bool* device_locked,
+ std::vector<uint8_t>* verified_boot_hash);
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/support/include/keymintSupport/authorization_set.h b/keymint/support/include/keymintSupport/authorization_set.h
new file mode 100644
index 0000000..141426a
--- /dev/null
+++ b/keymint/support/include/keymintSupport/authorization_set.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
+#define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
+
+#include <vector>
+
+#include <android/hardware/keymint/BlockMode.h>
+#include <android/hardware/keymint/Digest.h>
+#include <android/hardware/keymint/EcCurve.h>
+#include <android/hardware/keymint/PaddingMode.h>
+
+#include <keymintSupport/keymint_tags.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using android::hardware::keymint::BlockMode;
+using android::hardware::keymint::Digest;
+using android::hardware::keymint::EcCurve;
+using android::hardware::keymint::PaddingMode;
+
+using std::vector;
+
+class AuthorizationSetBuilder;
+
+/**
+ * An ordered collection of KeyParameters. It provides memory ownership and some convenient
+ * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
+ * For serialization, wrap the backing store of this structure in a vector<KeyParameter>.
+ */
+class AuthorizationSet {
+ public:
+ typedef KeyParameter value_type;
+
+ /**
+ * Construct an empty, dynamically-allocated, growable AuthorizationSet.
+ */
+ AuthorizationSet(){};
+
+ // Copy constructor.
+ AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
+
+ // Move constructor.
+ AuthorizationSet(AuthorizationSet&& other) noexcept : data_(std::move(other.data_)) {}
+
+ // Constructor from vector<KeyParameter>
+ AuthorizationSet(const vector<KeyParameter>& other) { *this = other; }
+
+ // Copy assignment.
+ AuthorizationSet& operator=(const AuthorizationSet& other) {
+ data_ = other.data_;
+ return *this;
+ }
+
+ // Move assignment.
+ AuthorizationSet& operator=(AuthorizationSet&& other) noexcept {
+ data_ = std::move(other.data_);
+ return *this;
+ }
+
+ AuthorizationSet& operator=(const vector<KeyParameter>& other) {
+ if (other.size() > 0) {
+ data_.resize(other.size());
+ for (size_t i = 0; i < data_.size(); ++i) {
+ /* This makes a deep copy even of embedded blobs.
+ * See assignment operator/copy constructor of vector.*/
+ data_[i] = other[i];
+ }
+ }
+ return *this;
+ }
+
+ /**
+ * Clear existing authorization set data
+ */
+ void Clear();
+
+ ~AuthorizationSet() = default;
+
+ /**
+ * Returns the size of the set.
+ */
+ size_t size() const { return data_.size(); }
+
+ /**
+ * Returns true if the set is empty.
+ */
+ bool empty() const { return size() == 0; }
+
+ /**
+ * Returns the data in the set, directly. Be careful with this.
+ */
+ const KeyParameter* data() const { return data_.data(); }
+
+ /**
+ * Sorts the set
+ */
+ void Sort();
+
+ /**
+ * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
+ * AuthorizationSetBuilder).
+ */
+ void Deduplicate();
+
+ /**
+ * Adds all elements from \p set that are not already present in this AuthorizationSet. As a
+ * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
+ */
+ void Union(const AuthorizationSet& set);
+
+ /**
+ * Removes all elements in \p set from this AuthorizationSet.
+ */
+ void Subtract(const AuthorizationSet& set);
+
+ /**
+ * Returns the offset of the next entry that matches \p tag, starting from the element after \p
+ * begin. If not found, returns -1.
+ */
+ int find(Tag tag, int begin = -1) const;
+
+ /**
+ * Removes the entry at the specified index. Returns true if successful, false if the index was
+ * out of bounds.
+ */
+ bool erase(int index);
+
+ /**
+ * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
+ */
+ std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
+
+ /**
+ * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
+ */
+ std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
+
+ /**
+ * Modifies this Authorization set such that it only keeps the entries for which doKeep
+ * returns true.
+ */
+ void Filter(std::function<bool(const KeyParameter&)> doKeep);
+ /**
+ * Returns the nth element of the set.
+ * Like for std::vector::operator[] there is no range check performed. Use of out of range
+ * indices is undefined.
+ */
+ KeyParameter& operator[](int n);
+
+ /**
+ * Returns the nth element of the set.
+ * Like for std::vector::operator[] there is no range check performed. Use of out of range
+ * indices is undefined.
+ */
+ const KeyParameter& operator[](int n) const;
+
+ /**
+ * Returns true if the set contains at least one instance of \p tag
+ */
+ bool Contains(Tag tag) const { return find(tag) != -1; }
+
+ template <TagType tag_type, Tag tag, typename ValueT>
+ bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+ for (const auto& param : data_) {
+ auto entry = authorizationValue(ttag, param);
+ if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+ }
+ return false;
+ }
+ /**
+ * Returns the number of \p tag entries.
+ */
+ size_t GetTagCount(Tag tag) const;
+
+ template <typename T>
+ inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+ auto entry = GetEntry(tag);
+ if (entry.isOk()) return authorizationValue(tag, entry.value());
+ return {};
+ }
+
+ void push_back(const KeyParameter& param) { data_.push_back(param); }
+ void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); }
+ void push_back(const AuthorizationSet& set) {
+ for (auto& entry : set) {
+ push_back(entry);
+ }
+ }
+ void push_back(AuthorizationSet&& set) {
+ std::move(set.begin(), set.end(), std::back_inserter(*this));
+ }
+
+ /**
+ * Append the tag and enumerated value to the set.
+ * "val" may be exactly one parameter unless a boolean parameter is added.
+ * In this case "val" is omitted. This condition is checked at compile time by Authorization()
+ */
+ template <typename TypedTagT, typename... Value>
+ void push_back(TypedTagT tag, Value&&... val) {
+ push_back(Authorization(tag, std::forward<Value>(val)...));
+ }
+
+ template <typename Iterator>
+ void append(Iterator begin, Iterator end) {
+ while (begin != end) {
+ push_back(*begin);
+ ++begin;
+ }
+ }
+
+ vector<KeyParameter> vector_data() const {
+ vector<KeyParameter> result(begin(), end());
+ return result;
+ }
+
+ void Serialize(std::ostream* out) const;
+ void Deserialize(std::istream* in);
+
+ private:
+ NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+
+ std::vector<KeyParameter> data_;
+};
+
+class AuthorizationSetBuilder : public AuthorizationSet {
+ public:
+ template <typename TagType, typename... ValueType>
+ AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
+ push_back(ttag, std::forward<ValueType>(value)...);
+ return *this;
+ }
+
+ template <Tag tag>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
+ size_t data_length) {
+ vector<uint8_t> new_blob(data, data + data_length);
+ push_back(ttag, new_blob);
+ return *this;
+ }
+
+ template <Tag tag>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
+ size_t data_length) {
+ return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
+ }
+
+ template <Tag tag>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, char* data,
+ size_t data_length) {
+ return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
+ }
+
+ template <Tag tag, size_t size>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag,
+ const char (&data)[size]) {
+ return Authorization(ttag, reinterpret_cast<const uint8_t*>(&data[0]),
+ size - 1); // drop the terminating '\0'
+ }
+
+ AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set) {
+ for (const auto& entry : set) {
+ push_back(entry);
+ }
+ return *this;
+ }
+
+ AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
+ AuthorizationSetBuilder& EcdsaKey(EcCurve curve);
+ AuthorizationSetBuilder& AesKey(uint32_t key_size);
+ AuthorizationSetBuilder& TripleDesKey(uint32_t key_size);
+ AuthorizationSetBuilder& HmacKey(uint32_t key_size);
+
+ AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
+ AuthorizationSetBuilder& EcdsaSigningKey(EcCurve curve);
+ AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
+ AuthorizationSetBuilder& TripleDesEncryptionKey(uint32_t key_size);
+
+ AuthorizationSetBuilder& SigningKey();
+ AuthorizationSetBuilder& EncryptionKey();
+
+ AuthorizationSetBuilder& NoDigestOrPadding();
+
+ AuthorizationSetBuilder& EcbMode();
+ AuthorizationSetBuilder& GcmModeMinMacLen(uint32_t minMacLength);
+ AuthorizationSetBuilder& GcmModeMacLen(uint32_t macLength);
+
+ AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes);
+ AuthorizationSetBuilder& Digest(std::vector<Digest> digests);
+ AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
+
+ template <typename... T>
+ AuthorizationSetBuilder& BlockMode(T&&... a) {
+ return BlockMode({std::forward<T>(a)...});
+ }
+ template <typename... T>
+ AuthorizationSetBuilder& Digest(T&&... a) {
+ return Digest({std::forward<T>(a)...});
+ }
+ template <typename... T>
+ AuthorizationSetBuilder& Padding(T&&... a) {
+ return Padding({std::forward<T>(a)...});
+ }
+};
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+#endif // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
diff --git a/keymint/support/include/keymintSupport/key_param_output.h b/keymint/support/include/keymintSupport/key_param_output.h
new file mode 100644
index 0000000..a35a981
--- /dev/null
+++ b/keymint/support/include/keymintSupport/key_param_output.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_
+#define HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_
+
+#include <iostream>
+#include <vector>
+
+#include "keymint_tags.h"
+
+#include <android/hardware/keymint/Algorithm.h>
+#include <android/hardware/keymint/BlockMode.h>
+#include <android/hardware/keymint/Digest.h>
+#include <android/hardware/keymint/EcCurve.h>
+#include <android/hardware/keymint/ErrorCode.h>
+#include <android/hardware/keymint/HardwareAuthenticatorType.h>
+#include <android/hardware/keymint/KeyCharacteristics.h>
+#include <android/hardware/keymint/KeyOrigin.h>
+#include <android/hardware/keymint/KeyParameter.h>
+#include <android/hardware/keymint/KeyPurpose.h>
+#include <android/hardware/keymint/PaddingMode.h>
+#include <android/hardware/keymint/SecurityLevel.h>
+#include <android/hardware/keymint/Tag.h>
+#include <android/hardware/keymint/TagType.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using namespace ::android::hardware::keymint;
+
+inline ::std::ostream& operator<<(::std::ostream& os, Algorithm value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, BlockMode value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, Digest value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, EcCurve value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, ErrorCode value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, PaddingMode value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, SecurityLevel value) {
+ return os << toString(value);
+}
+
+template <typename ValueT>
+::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
+ if (!value.isOk()) {
+ os << "(value not present)";
+ } else {
+ os << value.value();
+ }
+ return os;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const ::std::vector<KeyParameter>& set);
+::std::ostream& operator<<(::std::ostream& os, const KeyParameter& param);
+
+inline ::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& value) {
+ return os << "SW: " << value.softwareEnforced << ::std::endl
+ << "HW: " << value.hardwareEnforced << ::std::endl;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, KeyPurpose value) {
+ return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, Tag tag) {
+ return os << toString(tag);
+}
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+#endif // HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEY_PARAM_OUTPUT_H_
diff --git a/keymint/support/include/keymintSupport/keymint_tags.h b/keymint/support/include/keymintSupport/keymint_tags.h
new file mode 100644
index 0000000..f1060a9
--- /dev/null
+++ b/keymint/support/include/keymintSupport/keymint_tags.h
@@ -0,0 +1,414 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_
+#define HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_
+
+#include <android/hardware/keymint/Algorithm.h>
+#include <android/hardware/keymint/BlockMode.h>
+#include <android/hardware/keymint/Digest.h>
+#include <android/hardware/keymint/EcCurve.h>
+#include <android/hardware/keymint/HardwareAuthenticatorType.h>
+#include <android/hardware/keymint/KeyOrigin.h>
+#include <android/hardware/keymint/KeyParameter.h>
+#include <android/hardware/keymint/KeyPurpose.h>
+#include <android/hardware/keymint/PaddingMode.h>
+#include <android/hardware/keymint/SecurityLevel.h>
+#include <android/hardware/keymint/Tag.h>
+#include <android/hardware/keymint/TagType.h>
+
+namespace android::hardware::keymint {
+
+using android::hardware::keymint::KeyParameter;
+using android::hardware::keymint::Tag;
+using android::hardware::keymint::TagType;
+
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We
+// need these old values to be able to support old keys that use them.
+// TODO(seleneh) we should delete this code when we stop supporting keymaster1
+// and deletes it.
+static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+constexpr TagType typeFromTag(Tag tag) {
+ return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
+}
+
+/**
+ * TypedTag is a templatized version of Tag, which provides compile-time checking of
+ * keymint tag types. Instances are convertible to Tag, so they can be used wherever
+ * Tag is expected, and because they encode the tag type it's possible to create
+ * function overloads that only operate on tags with a particular type.
+ */
+template <TagType tag_type, Tag tag>
+struct TypedTag {
+ inline TypedTag() {
+ // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
+ // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile
+ // error (no match for template specialization StaticAssert<false>), with no run-time cost.
+ static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
+ }
+ operator Tag() const { return tag; }
+ int32_t maskedTag() { return static_cast<uint32_t>(tag) & 0x0FFFFFFF; }
+};
+
+template <Tag tag>
+struct Tag2TypedTag {
+ typedef TypedTag<typeFromTag(tag), tag> type;
+};
+
+#define DECLARE_TYPED_TAG(name) \
+ typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
+ static TAG_##name##_t TAG_##name;
+
+DECLARE_TYPED_TAG(ACTIVE_DATETIME);
+DECLARE_TYPED_TAG(ALGORITHM);
+DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
+DECLARE_TYPED_TAG(APPLICATION_DATA);
+DECLARE_TYPED_TAG(APPLICATION_ID);
+DECLARE_TYPED_TAG(ASSOCIATED_DATA);
+DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
+DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
+DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
+DECLARE_TYPED_TAG(AUTH_TIMEOUT);
+DECLARE_TYPED_TAG(BLOCK_MODE);
+DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
+DECLARE_TYPED_TAG(BOOT_PATCHLEVEL);
+DECLARE_TYPED_TAG(CALLER_NONCE);
+DECLARE_TYPED_TAG(CONFIRMATION_TOKEN);
+DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
+DECLARE_TYPED_TAG(DIGEST);
+DECLARE_TYPED_TAG(EARLY_BOOT_ONLY);
+DECLARE_TYPED_TAG(EC_CURVE);
+DECLARE_TYPED_TAG(HARDWARE_TYPE);
+DECLARE_TYPED_TAG(IDENTITY_CREDENTIAL_KEY);
+DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
+DECLARE_TYPED_TAG(INVALID);
+DECLARE_TYPED_TAG(KEY_SIZE);
+DECLARE_TYPED_TAG(MAC_LENGTH);
+DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
+DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
+DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+DECLARE_TYPED_TAG(NONCE);
+DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
+DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(OS_VERSION);
+DECLARE_TYPED_TAG(PADDING);
+DECLARE_TYPED_TAG(PURPOSE);
+DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
+DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE);
+DECLARE_TYPED_TAG(ROOT_OF_TRUST);
+DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
+DECLARE_TYPED_TAG(STORAGE_KEY);
+DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
+DECLARE_TYPED_TAG(TRUSTED_USER_PRESENCE_REQUIRED);
+DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
+DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(USER_ID);
+DECLARE_TYPED_TAG(USER_SECURE_ID);
+DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
+
+template <typename... Elems>
+struct MetaList {};
+
+using all_tags_t = MetaList<
+ TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+ TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
+ TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+ TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t, TAG_USER_SECURE_ID_t,
+ TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
+ TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
+ TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_HARDWARE_TYPE_t,
+ TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
+ TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
+ TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
+ TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+ TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
+ TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
+ TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
+ TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
+
+template <typename TypedTagType>
+struct TypedTag2ValueType;
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
+ template <Tag tag> \
+ struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
+ typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
+ }; \
+ template <Tag tag> \
+ inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
+ ->const decltype(param.field_name)& { \
+ return param.field_name; \
+ } \
+ template <Tag tag> \
+ inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \
+ ->decltype(param.field_name)& { \
+ return param.field_name; \
+ }
+
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
+
+// TODO(seleneh) change these MAKE_TAG_ENUM_VALUE_ACCESSOR back to the 2 parameter
+// version when aidl supports union
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name, field_type) \
+ template <> \
+ struct TypedTag2ValueType<decltype(typed_tag)> { \
+ typedef field_type type; \
+ }; \
+ inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \
+ ->const field_type& { \
+ return *reinterpret_cast<const field_type*>(¶m.field_name); \
+ } \
+ inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)->field_type& { \
+ return *reinterpret_cast<field_type*>(¶m.field_name); \
+ }
+
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, integer, Algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, integer, BlockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, integer, Digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, integer, EcCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, integer, KeyOrigin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, integer, PaddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, integer, KeyPurpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, integer, HardwareAuthenticatorType)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, integer, SecurityLevel)
+
+template <TagType tag_type, Tag tag, typename ValueT>
+inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
+ KeyParameter param;
+ param.tag = tag;
+ param.longInteger = 0;
+ accessTagValue(ttag, param) = std::forward<ValueT>(value);
+ return param;
+}
+
+// the boolean case
+template <Tag tag>
+inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
+ KeyParameter param;
+ param.tag = tag;
+ param.boolValue = true;
+ return param;
+}
+
+template <typename... Pack>
+struct FirstOrNoneHelper;
+template <typename First>
+struct FirstOrNoneHelper<First> {
+ typedef First type;
+};
+template <>
+struct FirstOrNoneHelper<> {
+ struct type {};
+};
+
+template <typename... Pack>
+using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
+
+template <TagType tag_type, Tag tag, typename... Args>
+inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
+ static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
+ "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
+ static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
+ "Authorization other then TagType::BOOL take exactly one parameter.");
+ static_assert(
+ tag_type == TagType::BOOL ||
+ std::is_convertible<
+ std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
+ typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
+ "Invalid argument type for given tag.");
+
+ return makeKeyParameter(ttag, std::forward<Args>(args)...);
+}
+
+/**
+ * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
+ * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
+ * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
+ * wrapped value. In this case the pointer will be NULL though, and the value will be default
+ * constructed.
+ *
+ * TODO(seleneh) replace this with std::optional.
+ */
+template <typename ValueT>
+class NullOr {
+ using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
+ std::remove_reference_t<ValueT>*, ValueT>;
+
+ struct pointer_initializer {
+ static std::nullptr_t init() { return nullptr; }
+ };
+ struct value_initializer {
+ static ValueT init() { return ValueT(); }
+ };
+ struct value_pointer_deref_t {
+ static ValueT& deref(ValueT& v) { return v; }
+ };
+ struct reference_deref_t {
+ static auto& deref(internal_t v) { return *v; }
+ };
+ using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
+ std::is_pointer<ValueT>::value,
+ pointer_initializer, value_initializer>;
+ using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
+ value_pointer_deref_t>;
+
+ public:
+ NullOr() : value_(initializer_t::init()), null_(true) {}
+ template <typename T>
+ NullOr(T&& value, typename std::enable_if<
+ !std::is_lvalue_reference<ValueT>::value &&
+ std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+ int>::type = 0)
+ : value_(std::forward<ValueT>(value)), null_(false) {}
+ template <typename T>
+ NullOr(T& value, typename std::enable_if<
+ std::is_lvalue_reference<ValueT>::value &&
+ std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+ int>::type = 0)
+ : value_(&value), null_(false) {}
+
+ bool isOk() const { return !null_; }
+
+ const ValueT& value() const& { return deref_t::deref(value_); }
+ ValueT& value() & { return deref_t::deref(value_); }
+ ValueT&& value() && { return std::move(deref_t::deref(value_)); }
+
+ private:
+ internal_t value_;
+ bool null_;
+};
+
+template <typename T>
+std::remove_reference_t<T> NullOrOr(T&& v) {
+ if (v.isOk()) return v;
+ return {};
+}
+
+template <typename Head, typename... Tail>
+std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
+ if (head.isOk()) return head;
+ return NullOrOr(std::forward<Tail>(tail)...);
+}
+
+template <typename Default, typename Wrapped>
+std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+ static_assert(std::is_convertible<std::remove_reference_t<Default>,
+ std::remove_reference_t<Wrapped>>::value,
+ "Type of default value must match the type wrapped by NullOr");
+ if (optional.isOk()) return optional.value();
+ return def;
+}
+
+template <TagType tag_type, Tag tag>
+inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
+ TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+ if (tag != param.tag) return {};
+ return accessTagValue(ttag, param);
+}
+
+} // namespace android::hardware::keymint
+
+namespace std {
+
+using namespace android::hardware::keymint;
+
+// Aidl generates KeyParameter operator<, >, ==, != for cpp translation but not ndk
+// translations. So we cannot straight forward overload these operators.
+// However we need our custom comparison for KeyParameters. So we will
+// overload std::less, equal_to instead.
+template <>
+struct std::less<KeyParameter> {
+ bool operator()(const KeyParameter& a, const KeyParameter& b) const {
+ if (a.tag != b.tag) return a.tag < b.tag;
+ int retval;
+ switch (typeFromTag(a.tag)) {
+ case TagType::INVALID:
+ case TagType::BOOL:
+ return false;
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ return a.integer < b.integer;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ case TagType::DATE:
+ return a.longInteger < b.longInteger;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ // Handle the empty cases.
+ if (a.blob.size() == 0) return b.blob.size() != 0;
+ if (b.blob.size() == 0) return false;
+ retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
+ // if one is the prefix of the other the longer wins
+ if (retval == 0) return a.blob.size() < b.blob.size();
+ // Otherwise a is less if a is less.
+ else
+ return retval < 0;
+ }
+ return false;
+ }
+};
+
+template <>
+struct std::equal_to<KeyParameter> {
+ bool operator()(const KeyParameter& a, const KeyParameter& b) const {
+ if (a.tag != b.tag) {
+ return false;
+ }
+ switch (typeFromTag(a.tag)) {
+ case TagType::INVALID:
+ case TagType::BOOL:
+ return true;
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ return a.integer == b.integer;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ case TagType::DATE:
+ return a.longInteger == b.longInteger;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ if (a.blob.size() != b.blob.size()) return false;
+ return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
+ }
+ return false;
+ }
+};
+
+} // namespace std
+
+#endif // HARDWARE_INTERFACES_KEYMINT_SUPPORT_INCLUDE_KEYMINT_TAGS_H_
diff --git a/keymint/support/include/keymintSupport/keymint_utils.h b/keymint/support/include/keymintSupport/keymint_utils.h
new file mode 100644
index 0000000..aa1e93b
--- /dev/null
+++ b/keymint/support/include/keymintSupport/keymint_utils.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_
+#define HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_
+
+#include <android/hardware/keymint/HardwareAuthToken.h>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using std::vector;
+
+inline static std::vector<uint8_t> blob2vector(const uint8_t* data, const size_t length) {
+ std::vector<uint8_t> result(data, data + length);
+ return result;
+}
+
+inline static std::vector<uint8_t> blob2vector(const std::string& value) {
+ vector<uint8_t> result(reinterpret_cast<const uint8_t*>(value.data()),
+ reinterpret_cast<const uint8_t*>(value.data()) + value.size());
+ return result;
+}
+
+HardwareAuthToken vector2AuthToken(const vector<uint8_t>& buffer);
+vector<uint8_t> authToken2vector(const HardwareAuthToken& token);
+
+uint32_t getOsVersion();
+uint32_t getOsPatchlevel();
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+
+#endif // HARDWARE_INTERFACES_KEYMINT_10_SUPPORT_KEYMINT_UTILS_H_
diff --git a/keymint/support/include/keymintSupport/openssl_utils.h b/keymint/support/include/keymintSupport/openssl_utils.h
new file mode 100644
index 0000000..39633ed
--- /dev/null
+++ b/keymint/support/include/keymintSupport/openssl_utils.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_
+#define HARDWARE_INTERFACES_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_
+
+#include <android/hardware/keymint/Digest.h>
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+template <typename T, void (*F)(T*)>
+struct UniquePtrDeleter {
+ void operator()(T* p) const { F(p); }
+};
+
+typedef UniquePtrDeleter<EVP_PKEY, EVP_PKEY_free> EVP_PKEY_Delete;
+
+#define MAKE_OPENSSL_PTR_TYPE(type) \
+ typedef std::unique_ptr<type, UniquePtrDeleter<type, type##_free>> type##_Ptr;
+
+MAKE_OPENSSL_PTR_TYPE(ASN1_OBJECT)
+MAKE_OPENSSL_PTR_TYPE(EVP_PKEY)
+MAKE_OPENSSL_PTR_TYPE(RSA)
+MAKE_OPENSSL_PTR_TYPE(X509)
+MAKE_OPENSSL_PTR_TYPE(BN_CTX)
+
+typedef std::unique_ptr<BIGNUM, UniquePtrDeleter<BIGNUM, BN_free>> BIGNUM_Ptr;
+
+inline const EVP_MD* openssl_digest(android::hardware::keymint::Digest digest) {
+ switch (digest) {
+ case android::hardware::keymint::Digest::NONE:
+ return nullptr;
+ case android::hardware::keymint::Digest::MD5:
+ return EVP_md5();
+ case android::hardware::keymint::Digest::SHA1:
+ return EVP_sha1();
+ case android::hardware::keymint::Digest::SHA_2_224:
+ return EVP_sha224();
+ case android::hardware::keymint::Digest::SHA_2_256:
+ return EVP_sha256();
+ case android::hardware::keymint::Digest::SHA_2_384:
+ return EVP_sha384();
+ case android::hardware::keymint::Digest::SHA_2_512:
+ return EVP_sha512();
+ }
+ return nullptr;
+}
+
+#endif // HARDWARE_INTERFACES_KEYMINT_1_0_SUPPORT_OPENSSL_UTILS_H_
diff --git a/keymint/support/key_param_output.cpp b/keymint/support/key_param_output.cpp
new file mode 100644
index 0000000..6e33558
--- /dev/null
+++ b/keymint/support/key_param_output.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 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 <keymintSupport/key_param_output.h>
+
+#include <keymintSupport/keymint_tags.h>
+
+#include <iomanip>
+
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using ::std::endl;
+using ::std::ostream;
+
+ostream& operator<<(ostream& os, const ::std::vector<KeyParameter>& set) {
+ if (set.size() == 0) {
+ os << "(Empty)" << endl;
+ } else {
+ os << "\n";
+ for (const auto& elem : set) os << elem << endl;
+ }
+ return os;
+}
+
+// TODO(seleneh) update this to a parsing that looks at each tags individually
+// such as ALGORITHM BLOCK_MODE when aidl union support is added.
+ostream& operator<<(ostream& os, const KeyParameter& param) {
+ os << param.tag << ": ";
+ switch (typeFromTag(param.tag)) {
+ case TagType::INVALID:
+ return os << " Invalid";
+ case TagType::ENUM_REP:
+ case TagType::ENUM:
+ case TagType::UINT_REP:
+ case TagType::UINT:
+ return os << param.integer;
+ case TagType::ULONG_REP:
+ case TagType::ULONG:
+ case TagType::DATE:
+ return os << param.longInteger;
+ case TagType::BOOL:
+ return os << "true";
+ case TagType::BIGNUM:
+ os << " Bignum: ";
+ for (size_t i = 0; i < param.blob.size(); ++i) {
+ os << std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
+ }
+ return os;
+ case TagType::BYTES:
+ os << " Bytes: ";
+ for (size_t i = 0; i < param.blob.size(); ++i) {
+ os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
+ }
+ return os;
+ }
+ return os << "UNKNOWN TAG TYPE!";
+}
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
diff --git a/keymint/support/keymint_utils.cpp b/keymint/support/keymint_utils.cpp
new file mode 100644
index 0000000..fd57cf5
--- /dev/null
+++ b/keymint/support/keymint_utils.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018 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 <regex.h>
+
+#include <android-base/properties.h>
+#include <hardware/hw_auth_token.h>
+#include <keymintSupport/keymint_utils.h>
+
+#include <arpa/inet.h>
+
+namespace android::hardware::keymint {
+
+namespace {
+
+constexpr char kPlatformVersionProp[] = "ro.build.version.release";
+constexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?";
+constexpr size_t kMajorVersionMatch = 1;
+constexpr size_t kMinorVersionMatch = 3;
+constexpr size_t kSubminorVersionMatch = 5;
+constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
+
+constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
+constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr size_t kYearMatch = 1;
+constexpr size_t kMonthMatch = 2;
+constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
+
+uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
+ if (match.rm_so == -1) return 0;
+
+ size_t len = match.rm_eo - match.rm_so;
+ std::string s(expression + match.rm_so, len);
+ return std::stoul(s);
+}
+
+std::string wait_and_get_property(const char* prop) {
+ std::string prop_value;
+ while (!::android::base::WaitForPropertyCreation(prop))
+ ;
+ prop_value = ::android::base::GetProperty(prop, "" /* default */);
+ return prop_value;
+}
+
+} // anonymous namespace
+
+uint32_t getOsVersion(const char* version_str) {
+ regex_t regex;
+ if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) {
+ return 0;
+ }
+
+ regmatch_t matches[kPlatformVersionMatchCount];
+ int not_match =
+ regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
+ return 0;
+ }
+
+ uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
+ uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
+ uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
+
+ return (major * 100 + minor) * 100 + subminor;
+}
+
+uint32_t getOsVersion() {
+ std::string version = wait_and_get_property(kPlatformVersionProp);
+ return getOsVersion(version.c_str());
+}
+
+uint32_t getOsPatchlevel(const char* patchlevel_str) {
+ regex_t regex;
+ if (regcomp(®ex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
+ return 0;
+ }
+
+ regmatch_t matches[kPlatformPatchlevelMatchCount];
+ int not_match =
+ regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
+ return 0;
+ }
+
+ uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
+ uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
+
+ if (month < 1 || month > 12) {
+ return 0;
+ }
+ return year * 100 + month;
+}
+
+uint32_t getOsPatchlevel() {
+ std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
+ return getOsPatchlevel(patchlevel.c_str());
+}
+
+} // namespace android::hardware::keymint
diff --git a/light/2.0/Android.bp b/light/2.0/Android.bp
index d51f10d..ae6d37c 100644
--- a/light/2.0/Android.bp
+++ b/light/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.light@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ILight.hal",
diff --git a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
index 6fcecd2..f65005e 100644
--- a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
+++ b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
@@ -150,6 +150,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LightHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, LightHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ILight::descriptor)),
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index 91de3e9..fbcdb32 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -7,7 +7,7 @@
stability: "vintf",
backend: {
java: {
- platform_apis: true,
+ sdk_version: "module_current",
},
ndk: {
vndk: {
diff --git a/light/aidl/vts/functional/VtsHalLightTargetTest.cpp b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
index 3c26278..5e3eabd 100644
--- a/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
+++ b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
@@ -159,6 +159,7 @@
EXPECT_TRUE(status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LightsAidl);
INSTANTIATE_TEST_SUITE_P(Lights, LightsAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(ILights::descriptor)),
android::PrintInstanceNameToString);
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index 079e47f..5dbbadd 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.media.bufferpool@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IAccessor.hal",
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index 391e6c4..089ce98 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.media.c2@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IComponent.hal",
diff --git a/media/c2/1.1/Android.bp b/media/c2/1.1/Android.bp
index c3e30b2..a3d31df 100644
--- a/media/c2/1.1/Android.bp
+++ b/media/c2/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.media.c2@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IComponent.hal",
"IComponentStore.hal",
diff --git a/media/omx/1.0/vts/functional/README.md b/media/omx/1.0/vts/functional/README.md
index c5a6867..67f4aa5 100644
--- a/media/omx/1.0/vts/functional/README.md
+++ b/media/omx/1.0/vts/functional/README.md
@@ -1,12 +1,12 @@
## Omx Hal @ 1.0 tests ##
---
## Overview :
-The scope of the tests presented here is not restricted solely to testing omx hal @ 1.0 API but also test to omx core functionality and to an extent omx components as well. The current directory contains the following folders: audio, common, component, master and video. Besides common all other folders contain test fixtures for testing AV decoder, encoder components. Common constitutes files that are used across by these test applications.
+The scope of the tests presented here is not restricted solely to testing omx hal @ 1.0 API but also test to omx core functionality and to an extent omx components as well. The current directory contains the following folders: audio, common, component, store and video. Besides common all other folders contain test fixtures for testing AV decoder, encoder components. Common constitutes files that are used across by these test applications.
-#### master :
-Functionality of master is to enumerate all the omx components (and the roles it supports) available in android media framework.
+#### store :
+Functionality of store is to enumerate all the omx components (and the roles it supports) available in android media framework.
-usage: atest VtsHalMediaOmxV1\_0TargetMasterTest
+usage: atest VtsHalMediaOmxV1\_0TargetStoreTest
#### component :
This folder includes test fixtures that tests aspects common to all omx compatible components. For instance, port enabling/disabling, enumerating port formats, state transitions, flush, ..., stay common to all components irrespective of the service they offer. Test fixtures here are directed towards testing these (omx core). Every standard OMX compatible component is expected to pass these tests.
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 3ed5670..e7dfce3 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -1152,6 +1152,7 @@
kPortIndexOutput));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioDecHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, AudioDecHidlTest, testing::ValuesIn(kTestParameters),
android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
index 32e6f4c..231d758 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
@@ -486,6 +486,7 @@
kPortIndexOutput));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEncHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, AudioEncHidlTest, testing::ValuesIn(kTestParameters),
android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 064aaa5..89df4ff 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -59,11 +59,11 @@
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libhidlmemory",
- "libnativehelper",
],
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
+ "libnativehelper",
"libui",
"libstagefright_foundation",
"libstagefright_omx_utils",
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 64f27e8..9184c56 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -713,8 +713,8 @@
for (IOmx::ComponentInfo info : componentInfos) {
for (std::string role : info.mRoles) {
if (filter.empty()) {
- if (kWhiteListRoles.find(role.c_str()) == kWhiteListRoles.end()) {
- // This is for component test and the role is not in the white list.
+ if (kKnownRoles.find(role.c_str()) == kKnownRoles.end()) {
+ // This is for component test and the role is not supported.
continue;
}
} else if (role.find(filter) == std::string::npos) {
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index 044408d..b16c772 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -71,8 +71,8 @@
unknown,
};
-// White list audio/video roles to be tested.
-static std::set<std::string> kWhiteListRoles{
+// List known and thus tested audio/video roles.
+static std::set<std::string> kKnownRoles{
"audio_encoder.aac", "audio_encoder.amrnb", "audio_encoder.amrwb",
"audio_encoder.flac", "audio_decoder.aac", "audio_decoder.amrnb",
"audio_decoder.amrwb", "audio_decoder.flac", "audio_decoder.g711alaw",
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 01cec6d..d20139f 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -1264,6 +1264,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComponentHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, ComponentHidlTest, testing::ValuesIn(kTestParameters),
android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/media/omx/1.0/vts/functional/master/Android.bp b/media/omx/1.0/vts/functional/store/Android.bp
similarity index 87%
rename from media/omx/1.0/vts/functional/master/Android.bp
rename to media/omx/1.0/vts/functional/store/Android.bp
index 5953eb5..28d12ff 100644
--- a/media/omx/1.0/vts/functional/master/Android.bp
+++ b/media/omx/1.0/vts/functional/store/Android.bp
@@ -15,9 +15,9 @@
//
cc_test {
- name: "VtsHalMediaOmxV1_0TargetMasterTest",
+ name: "VtsHalMediaOmxV1_0TargetStoreTest",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
- srcs: ["VtsHalMediaOmxV1_0TargetMasterTest.cpp"],
+ srcs: ["VtsHalMediaOmxV1_0TargetStoreTest.cpp"],
test_suites: [
"general-tests",
"vts",
diff --git a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
similarity index 97%
rename from media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
rename to media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index 68ee900..e73196c 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "media_omx_hidl_master_test"
+#define LOG_TAG "media_omx_hidl_store_test"
#ifdef __LP64__
#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
#endif
@@ -55,7 +55,7 @@
#include <getopt.h>
#include <media_hidl_test_common.h>
-class MasterHidlTest : public ::testing::TestWithParam<std::string> {
+class StoreHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
omxStore = IOmxStore::getService(GetParam());
@@ -127,7 +127,7 @@
}
// Make sure IOmx and IOmxStore have the same set of instances.
-TEST(MasterHidlTest, instanceMatchValidation) {
+TEST(StoreHidlTest, instanceMatchValidation) {
auto omxInstances = android::hardware::getAllHalInstanceNames(IOmx::descriptor);
auto omxStoreInstances = android::hardware::getAllHalInstanceNames(IOmxStore::descriptor);
ASSERT_EQ(omxInstances.size(), omxInstances.size());
@@ -138,7 +138,7 @@
}
// list service attributes and verify expected formats
-TEST_P(MasterHidlTest, ListServiceAttr) {
+TEST_P(StoreHidlTest, ListServiceAttr) {
description("list service attributes");
android::hardware::media::omx::V1_0::Status status;
hidl_vec<IOmxStore::Attribute> attributes;
@@ -184,7 +184,7 @@
}
// get node prefix
-TEST_P(MasterHidlTest, getNodePrefix) {
+TEST_P(StoreHidlTest, getNodePrefix) {
description("get node prefix");
hidl_string prefix;
omxStore->getNodePrefix(
@@ -193,7 +193,7 @@
}
// list roles and validate all RoleInfo objects
-TEST_P(MasterHidlTest, ListRoles) {
+TEST_P(StoreHidlTest, ListRoles) {
description("list roles");
hidl_vec<IOmxStore::RoleInfo> roleList;
omxStore->listRoles([&roleList](hidl_vec<IOmxStore::RoleInfo> const& _nl) {
@@ -370,7 +370,7 @@
}
// list components and roles.
-TEST_P(MasterHidlTest, ListNodes) {
+TEST_P(StoreHidlTest, ListNodes) {
description("enumerate component and roles");
android::hardware::media::omx::V1_0::Status status;
hidl_vec<IOmx::ComponentInfo> nodeList;
@@ -418,7 +418,8 @@
EXPECT_TRUE(isPass);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StoreHidlTest);
INSTANTIATE_TEST_CASE_P(
- PerInstance, MasterHidlTest,
+ PerInstance, StoreHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IOmxStore::descriptor)),
android::hardware::PrintInstanceNameToString);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index 29a32a5..67b9895 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -1419,6 +1419,7 @@
kPortIndexOutput));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VideoDecHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, VideoDecHidlTest, testing::ValuesIn(kTestParameters),
android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 7519f2f..3c0734e 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -287,11 +287,11 @@
};
// Mock IOmxBufferSource class. GraphicBufferSource.cpp in libstagefright/omx/
-// implements this class. Below is dummy class introduced to test if callback
+// implements this class. Below class is introduced to test if callback
// functions are actually being called or not
-struct DummyBufferSource : public IOmxBufferSource {
+struct MockBufferSource : public IOmxBufferSource {
public:
- DummyBufferSource(sp<IOmxNode> node) {
+ MockBufferSource(sp<IOmxNode> node) {
callback = 0;
executing = false;
omxNode = node;
@@ -309,7 +309,7 @@
android::Vector<BufferInfo> iBuffer, oBuffer;
};
-Return<void> DummyBufferSource::onOmxExecuting() {
+Return<void> MockBufferSource::onOmxExecuting() {
executing = true;
callback |= 0x1;
size_t index;
@@ -330,25 +330,25 @@
return Void();
};
-Return<void> DummyBufferSource::onOmxIdle() {
+Return<void> MockBufferSource::onOmxIdle() {
callback |= 0x2;
executing = false;
return Void();
};
-Return<void> DummyBufferSource::onOmxLoaded() {
+Return<void> MockBufferSource::onOmxLoaded() {
callback |= 0x4;
return Void();
};
-Return<void> DummyBufferSource::onInputBufferAdded(uint32_t buffer) {
+Return<void> MockBufferSource::onInputBufferAdded(uint32_t buffer) {
(void)buffer;
EXPECT_EQ(executing, false);
callback |= 0x8;
return Void();
};
-Return<void> DummyBufferSource::onInputBufferEmptied(
+Return<void> MockBufferSource::onInputBufferEmptied(
uint32_t buffer, const ::android::hardware::hidl_handle& fence) {
(void)fence;
callback |= 0x10;
@@ -1031,7 +1031,7 @@
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
xFramerate, eColorFormat);
- sp<DummyBufferSource> buffersource = new DummyBufferSource(omxNode);
+ sp<MockBufferSource> buffersource = new MockBufferSource(omxNode);
ASSERT_NE(buffersource, nullptr);
status = omxNode->setInputSurface(buffersource);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
@@ -1461,6 +1461,7 @@
ASSERT_EQ(returnval, 0);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VideoEncHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, VideoEncHidlTest, testing::ValuesIn(kTestParameters),
android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
index cccedca..26edd11 100644
--- a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
+++ b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
@@ -160,6 +160,7 @@
static_cast<uint32_t>(MemtrackType::NUM_TYPES));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemtrackHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, MemtrackHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMemtrack::descriptor)),
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 3e740c4..20de9d5 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.neuralnetworks@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
new file mode 100644
index 0000000..4d61fc0
--- /dev/null
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_1_0",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal/1.0/"],
+ export_include_dirs: ["include"],
+ cflags: ["-Wthread-safety"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_common",
+ ],
+ shared_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ ],
+ export_static_lib_headers: [
+ "neuralnetworks_utils_hal_common",
+ ],
+}
diff --git a/neuralnetworks/1.0/utils/OWNERS b/neuralnetworks/1.0/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.0/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
new file mode 100644
index 0000000..65b75e5
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_CALLBACKS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_CALLBACKS_H
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+class PreparedModelCallback final : public IPreparedModelCallback,
+ public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::GeneralResult<nn::SharedPreparedModel>;
+
+ Return<void> notify(ErrorStatus status, const sp<IPreparedModel>& preparedModel) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
+
+ Return<void> notify(ErrorStatus status) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_CALLBACKS_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
new file mode 100644
index 0000000..fb77cb2
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+GeneralResult<OperandType> convert(const hal::V1_0::OperandType& operandType);
+GeneralResult<OperationType> convert(const hal::V1_0::OperationType& operationType);
+GeneralResult<Operand::LifeTime> convert(const hal::V1_0::OperandLifeTime& lifetime);
+GeneralResult<DeviceStatus> convert(const hal::V1_0::DeviceStatus& deviceStatus);
+GeneralResult<Capabilities::PerformanceInfo> convert(
+ const hal::V1_0::PerformanceInfo& performanceInfo);
+GeneralResult<Capabilities> convert(const hal::V1_0::Capabilities& capabilities);
+GeneralResult<DataLocation> convert(const hal::V1_0::DataLocation& location);
+GeneralResult<Operand> convert(const hal::V1_0::Operand& operand);
+GeneralResult<Operation> convert(const hal::V1_0::Operation& operation);
+GeneralResult<Model::OperandValues> convert(const hardware::hidl_vec<uint8_t>& operandValues);
+GeneralResult<Memory> convert(const hardware::hidl_memory& memory);
+GeneralResult<Model> convert(const hal::V1_0::Model& model);
+GeneralResult<Request::Argument> convert(const hal::V1_0::RequestArgument& requestArgument);
+GeneralResult<Request> convert(const hal::V1_0::Request& request);
+GeneralResult<ErrorStatus> convert(const hal::V1_0::ErrorStatus& status);
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType);
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType);
+nn::GeneralResult<OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime);
+nn::GeneralResult<DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
+nn::GeneralResult<PerformanceInfo> convert(
+ const nn::Capabilities::PerformanceInfo& performanceInfo);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<DataLocation> convert(const nn::DataLocation& location);
+nn::GeneralResult<Operand> convert(const nn::Operand& operand);
+nn::GeneralResult<Operation> convert(const nn::Operation& operation);
+nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues);
+nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory);
+nn::GeneralResult<Model> convert(const nn::Model& model);
+nn::GeneralResult<RequestArgument> convert(const nn::Request::Argument& requestArgument);
+nn::GeneralResult<hidl_memory> convert(const nn::Request::MemoryPool& memoryPool);
+nn::GeneralResult<Request> convert(const nn::Request& request);
+nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& status);
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_CONVERSIONS_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
new file mode 100644
index 0000000..ee103ba
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_DEVICE_H
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+class Device final : public nn::IDevice {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Device>> create(std::string name,
+ sp<V1_0::IDevice> device);
+
+ Device(PrivateConstructorTag tag, std::string name, nn::Capabilities capabilities,
+ sp<V1_0::IDevice> device, hal::utils::DeathHandler deathHandler);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString = "UNKNOWN";
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const sp<V1_0::IDevice> kDevice;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_DEVICE_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
new file mode 100644
index 0000000..31f366d
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PREPARED_MODEL_H
+
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+class PreparedModel final : public nn::IPreparedModel {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
+ sp<V1_0::IPreparedModel> preparedModel);
+
+ PreparedModel(PrivateConstructorTag tag, sp<V1_0::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler);
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+
+ private:
+ const sp<V1_0::IPreparedModel> kPreparedModel;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PREPARED_MODEL_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Service.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Service.h
new file mode 100644
index 0000000..11fbb9e
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Service.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_SERVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_SERVICE_H
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <string>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_SERVICE_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
new file mode 100644
index 0000000..baa2b95
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_H
+
+#include "nnapi/hal/1.0/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+constexpr auto kVersion = nn::Version::ANDROID_OC_MR1;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+ const auto maybeCanonical = nn::convert(halObject);
+ if (!maybeCanonical.has_value()) {
+ return nn::error() << maybeCanonical.error().message;
+ }
+ const auto version = NN_TRY(nn::validate(maybeCanonical.value()));
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+ const auto result = utils::validate(halObject);
+ if (!result.has_value()) {
+ LOG(ERROR) << result.error();
+ }
+ return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+ auto canonical = NN_TRY(nn::convert(halObject));
+ const auto maybeVersion = nn::validate(canonical);
+ if (!maybeVersion.has_value()) {
+ return nn::error() << maybeVersion.error();
+ }
+ const auto version = maybeVersion.value();
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return canonical;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_H
diff --git a/neuralnetworks/1.0/utils/src/Assertions.cpp b/neuralnetworks/1.0/utils/src/Assertions.cpp
new file mode 100644
index 0000000..0f00951
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Assertions.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(lhsType, rhsType) \
+ static_assert( \
+ std::is_same_v< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_0::lhsType>, \
+ std::underlying_type_t<::android::nn::rhsType>>, \
+ "::android::hardware::neuralnetworks::V1_0::" #lhsType \
+ " does not have the same underlying type as ::android::nn::" #rhsType)
+
+COMPARE_ENUMS_TYPES(OperandType, OperandType);
+COMPARE_ENUMS_TYPES(OperationType, OperationType);
+COMPARE_ENUMS_TYPES(ErrorStatus, ErrorStatus);
+COMPARE_ENUMS_TYPES(OperandLifeTime, Operand::LifeTime);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(lhsSymbol, rhsSymbol, lhsType, rhsType) \
+ static_assert( \
+ static_cast< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_0::lhsType>>( \
+ ::android::hardware::neuralnetworks::V1_0::lhsType::lhsSymbol) == \
+ static_cast<std::underlying_type_t<::android::nn::rhsType>>( \
+ ::android::nn::rhsType::rhsSymbol), \
+ "::android::hardware::neuralnetworks::V1_0::" #lhsType "::" #lhsSymbol \
+ " does not match ::android::nn::" #rhsType "::" #rhsSymbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, OperandType, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, OperationType, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, symbol, ErrorStatus, ErrorStatus)
+
+COMPARE_ENUMS(NONE);
+COMPARE_ENUMS(DEVICE_UNAVAILABLE);
+COMPARE_ENUMS(GENERAL_FAILURE);
+COMPARE_ENUMS(OUTPUT_INSUFFICIENT_SIZE);
+COMPARE_ENUMS(INVALID_ARGUMENT);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(lhsSymbol, rhsSymbol) \
+ COMPARE_ENUMS_FULL(lhsSymbol, rhsSymbol, OperandLifeTime, Operand::LifeTime)
+
+COMPARE_ENUMS(TEMPORARY_VARIABLE, TEMPORARY_VARIABLE);
+COMPARE_ENUMS(MODEL_INPUT, SUBGRAPH_INPUT);
+COMPARE_ENUMS(MODEL_OUTPUT, SUBGRAPH_OUTPUT);
+COMPARE_ENUMS(CONSTANT_COPY, CONSTANT_COPY);
+COMPARE_ENUMS(CONSTANT_REFERENCE, CONSTANT_REFERENCE);
+COMPARE_ENUMS(NO_VALUE, NO_VALUE);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+} // anonymous namespace
diff --git a/neuralnetworks/1.0/utils/src/Callbacks.cpp b/neuralnetworks/1.0/utils/src/Callbacks.cpp
new file mode 100644
index 0000000..f286bcc
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Callbacks.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Callbacks.h"
+
+#include "Conversions.h"
+#include "PreparedModel.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <utility>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+namespace {
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<IPreparedModel>& preparedModel) {
+ return NN_TRY(utils::PreparedModel::create(preparedModel));
+}
+
+} // namespace
+
+Return<void> PreparedModelCallback::notify(ErrorStatus status,
+ const sp<IPreparedModel>& preparedModel) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+void PreparedModelCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+PreparedModelCallback::Data PreparedModelCallback::get() {
+ return mData.take();
+}
+
+void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+// ExecutionCallback methods begin here
+
+Return<void> ExecutionCallback::notify(ErrorStatus status) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal({});
+ }
+ return Void();
+}
+
+void ExecutionCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+ExecutionCallback::Data ExecutionCallback::get() {
+ return mData.take();
+}
+
+void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Conversions.cpp b/neuralnetworks/1.0/utils/src/Conversions.cpp
new file mode 100644
index 0000000..6cf9073
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Conversions.cpp
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+ return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+} // namespace
+
+namespace android::nn {
+namespace {
+
+using hardware::hidl_memory;
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+GeneralResult<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+ std::vector<ConvertOutput<Type>> canonical;
+ canonical.reserve(arguments.size());
+ for (const auto& argument : arguments) {
+ canonical.push_back(NN_TRY(nn::convert(argument)));
+ }
+ return canonical;
+}
+
+} // anonymous namespace
+
+GeneralResult<OperandType> convert(const hal::V1_0::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+GeneralResult<OperationType> convert(const hal::V1_0::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+GeneralResult<Operand::LifeTime> convert(const hal::V1_0::OperandLifeTime& lifetime) {
+ return static_cast<Operand::LifeTime>(lifetime);
+}
+
+GeneralResult<DeviceStatus> convert(const hal::V1_0::DeviceStatus& deviceStatus) {
+ return static_cast<DeviceStatus>(deviceStatus);
+}
+
+GeneralResult<Capabilities::PerformanceInfo> convert(
+ const hal::V1_0::PerformanceInfo& performanceInfo) {
+ return Capabilities::PerformanceInfo{
+ .execTime = performanceInfo.execTime,
+ .powerUsage = performanceInfo.powerUsage,
+ };
+}
+
+GeneralResult<Capabilities> convert(const hal::V1_0::Capabilities& capabilities) {
+ const auto quantized8Performance = NN_TRY(convert(capabilities.quantized8Performance));
+ const auto float32Performance = NN_TRY(convert(capabilities.float32Performance));
+
+ auto table = hal::utils::makeQuantized8PerformanceConsistentWithP(float32Performance,
+ quantized8Performance);
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar = float32Performance,
+ .relaxedFloat32toFloat16PerformanceTensor = float32Performance,
+ .operandPerformance = std::move(table),
+ };
+}
+
+GeneralResult<DataLocation> convert(const hal::V1_0::DataLocation& location) {
+ return DataLocation{
+ .poolIndex = location.poolIndex,
+ .offset = location.offset,
+ .length = location.length,
+ };
+}
+
+GeneralResult<Operand> convert(const hal::V1_0::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ };
+}
+
+GeneralResult<Operation> convert(const hal::V1_0::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+GeneralResult<Model::OperandValues> convert(const hidl_vec<uint8_t>& operandValues) {
+ return Model::OperandValues(operandValues.data(), operandValues.size());
+}
+
+GeneralResult<Memory> convert(const hidl_memory& memory) {
+ return createSharedMemoryFromHidlMemory(memory);
+}
+
+GeneralResult<Model> convert(const hal::V1_0::Model& model) {
+ auto operations = NN_TRY(convert(model.operations));
+
+ // Verify number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+ CHECK(model.operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < model.operands.size(); ++i) {
+ if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+ return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
+ << "Invalid numberOfConsumers for operand " << i << ", expected "
+ << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
+ }
+ }
+
+ auto main = Model::Subgraph{
+ .operands = NN_TRY(convert(model.operands)),
+ .operations = std::move(operations),
+ .inputIndexes = model.inputIndexes,
+ .outputIndexes = model.outputIndexes,
+ };
+
+ return Model{
+ .main = std::move(main),
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ };
+}
+
+GeneralResult<Request::Argument> convert(const hal::V1_0::RequestArgument& argument) {
+ const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
+ : Request::Argument::LifeTime::POOL;
+ return Request::Argument{
+ .lifetime = lifetime,
+ .location = NN_TRY(convert(argument.location)),
+ .dimensions = argument.dimensions,
+ };
+}
+
+GeneralResult<Request> convert(const hal::V1_0::Request& request) {
+ auto memories = NN_TRY(convert(request.pools));
+ std::vector<Request::MemoryPool> pools;
+ pools.reserve(memories.size());
+ std::move(memories.begin(), memories.end(), std::back_inserter(pools));
+
+ return Request{
+ .inputs = NN_TRY(convert(request.inputs)),
+ .outputs = NN_TRY(convert(request.outputs)),
+ .pools = std::move(pools),
+ };
+}
+
+GeneralResult<ErrorStatus> convert(const hal::V1_0::ErrorStatus& status) {
+ switch (status) {
+ case hal::V1_0::ErrorStatus::NONE:
+ case hal::V1_0::ErrorStatus::DEVICE_UNAVAILABLE:
+ case hal::V1_0::ErrorStatus::GENERAL_FAILURE:
+ case hal::V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ case hal::V1_0::ErrorStatus::INVALID_ARGUMENT:
+ return static_cast<ErrorStatus>(status);
+ }
+ return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
+ << "Invalid ErrorStatus " << underlyingType(status);
+}
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+namespace {
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+ hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ halObject[i] = NN_TRY(utils::convert(arguments[i]));
+ }
+ return halObject;
+}
+
+} // anonymous namespace
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+nn::GeneralResult<OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime) {
+ if (lifetime == nn::Operand::LifeTime::POINTER) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Model cannot be converted because it contains pointer-based memory";
+ }
+ return static_cast<OperandLifeTime>(lifetime);
+}
+
+nn::GeneralResult<DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
+ return static_cast<DeviceStatus>(deviceStatus);
+}
+
+nn::GeneralResult<PerformanceInfo> convert(
+ const nn::Capabilities::PerformanceInfo& performanceInfo) {
+ return PerformanceInfo{
+ .execTime = performanceInfo.execTime,
+ .powerUsage = performanceInfo.powerUsage,
+ };
+}
+
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+ return Capabilities{
+ .float32Performance = NN_TRY(convert(
+ capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
+ .quantized8Performance = NN_TRY(convert(
+ capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
+ };
+}
+
+nn::GeneralResult<DataLocation> convert(const nn::DataLocation& location) {
+ return DataLocation{
+ .poolIndex = location.poolIndex,
+ .offset = location.offset,
+ .length = location.length,
+ };
+}
+
+nn::GeneralResult<Operand> convert(const nn::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .numberOfConsumers = 0,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ };
+}
+
+nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+ return hidl_vec<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
+}
+
+nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
+ return hidl_memory(memory.name, NN_TRY(hal::utils::hidlHandleFromSharedHandle(memory.handle)),
+ memory.size);
+}
+
+nn::GeneralResult<Model> convert(const nn::Model& model) {
+ if (!hal::utils::hasNoPointerData(model)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Mdoel cannot be converted because it contains pointer-based memory";
+ }
+
+ auto operands = NN_TRY(convert(model.main.operands));
+
+ // Update number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+ CHECK(operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < operands.size(); ++i) {
+ operands[i].numberOfConsumers = numberOfConsumers[i];
+ }
+
+ return Model{
+ .operands = std::move(operands),
+ .operations = NN_TRY(convert(model.main.operations)),
+ .inputIndexes = model.main.inputIndexes,
+ .outputIndexes = model.main.outputIndexes,
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ };
+}
+
+nn::GeneralResult<RequestArgument> convert(const nn::Request::Argument& requestArgument) {
+ if (requestArgument.lifetime == nn::Request::Argument::LifeTime::POINTER) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Request cannot be converted because it contains pointer-based memory";
+ }
+ const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
+ return RequestArgument{
+ .hasNoValue = hasNoValue,
+ .location = NN_TRY(convert(requestArgument.location)),
+ .dimensions = requestArgument.dimensions,
+ };
+}
+
+nn::GeneralResult<hidl_memory> convert(const nn::Request::MemoryPool& memoryPool) {
+ return convert(std::get<nn::Memory>(memoryPool));
+}
+
+nn::GeneralResult<Request> convert(const nn::Request& request) {
+ if (!hal::utils::hasNoPointerData(request)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Request cannot be converted because it contains pointer-based memory";
+ }
+
+ return Request{
+ .inputs = NN_TRY(convert(request.inputs)),
+ .outputs = NN_TRY(convert(request.outputs)),
+ .pools = NN_TRY(convert(request.pools)),
+ };
+}
+
+nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& status) {
+ switch (status) {
+ case nn::ErrorStatus::NONE:
+ case nn::ErrorStatus::DEVICE_UNAVAILABLE:
+ case nn::ErrorStatus::GENERAL_FAILURE:
+ case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ case nn::ErrorStatus::INVALID_ARGUMENT:
+ return static_cast<ErrorStatus>(status);
+ default:
+ return ErrorStatus::GENERAL_FAILURE;
+ }
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
new file mode 100644
index 0000000..671416b
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Device.h"
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+namespace {
+
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_0::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](ErrorStatus status, const Capabilities& capabilities) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getCapabilities failed with " << toString(status);
+ } else {
+ result = validatedConvertToCanonical(capabilities);
+ }
+ };
+
+ const auto ret = device->getCapabilities(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
+ sp<V1_0::IDevice> device) {
+ if (name.empty()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_0::utils::Device::create must have non-empty name";
+ }
+ if (device == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_0::utils::Device::create must have non-null device";
+ }
+
+ auto capabilities = NN_TRY(initCapabilities(device.get()));
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
+ return std::make_shared<const Device>(PrivateConstructorTag{}, std::move(name),
+ std::move(capabilities), std::move(device),
+ std::move(deathHandler));
+}
+
+Device::Device(PrivateConstructorTag /*tag*/, std::string name, nn::Capabilities capabilities,
+ sp<V1_0::IDevice> device, hal::utils::DeathHandler deathHandler)
+ : kName(std::move(name)),
+ kCapabilities(std::move(capabilities)),
+ kDevice(std::move(device)),
+ kDeathHandler(std::move(deathHandler)) {}
+
+const std::string& Device::getName() const {
+ return kName;
+}
+
+const std::string& Device::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version Device::getFeatureLevel() const {
+ return nn::Version::ANDROID_OC_MR1;
+}
+
+nn::DeviceType Device::getType() const {
+ return nn::DeviceType::OTHER;
+}
+
+const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& Device::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> Device::getNumberOfCacheFilesNeeded() const {
+ return std::make_pair(/*numModelCache=*/0, /*numDataCache=*/0);
+}
+
+nn::GeneralResult<void> Device::wait() const {
+ const auto ret = kDevice->ping();
+ return hal::utils::handleTransportError(ret);
+}
+
+nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Model& model) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+
+ nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ auto cb = [&result, &model](ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical)
+ << "getSupportedOperations failed with " << toString(status);
+ } else if (supportedOperations.size() != model.main.operations.size()) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "getSupportedOperations returned vector of size "
+ << supportedOperations.size() << " but expected "
+ << model.main.operations.size();
+ } else {
+ result = supportedOperations;
+ }
+ };
+
+ const auto ret = kDevice->getSupportedOperations(hidlModel, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
+ const nn::Model& model, nn::ExecutionPreference /*preference*/, nn::Priority /*priority*/,
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+
+ const auto cb = sp<PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kDevice->prepareModel(hidlModel, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModel failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache(
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::prepareModelFromCache not supported on 1.0 HAL service";
+}
+
+nn::GeneralResult<nn::SharedBuffer> Device::allocate(
+ const nn::BufferDesc& /*desc*/,
+ const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+ const std::vector<nn::BufferRole>& /*inputRoles*/,
+ const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::allocate not supported on 1.0 HAL service";
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
new file mode 100644
index 0000000..11ccbe3
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PreparedModel.h"
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
+ sp<V1_0::IPreparedModel> preparedModel) {
+ if (preparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_0::utils::PreparedModel::create must have non-null preparedModel";
+ }
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
+ std::move(deathHandler));
+}
+
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, sp<V1_0::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler)
+ : kPreparedModel(std::move(preparedModel)), kDeathHandler(std::move(deathHandler)) {}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
+ const nn::Request& request, nn::MeasureTiming /*measure*/,
+ const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared)));
+
+ const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
+
+ const auto cb = sp<ExecutionCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kPreparedModel->execute(hidlRequest, cb);
+ const auto status =
+ NN_TRY(hal::utils::makeExecutionFailure(hal::utils::handleTransportError(ret)));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "execute failed with " << toString(status);
+ }
+
+ auto result = NN_TRY(cb->get());
+ NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
+
+ return result;
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IPreparedModel::executeFenced is not supported on 1.0 HAL service";
+}
+
+std::any PreparedModel::getUnderlyingResource() const {
+ sp<V1_0::IPreparedModel> resource = kPreparedModel;
+ return resource;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Service.cpp b/neuralnetworks/1.0/utils/src/Service.cpp
new file mode 100644
index 0000000..ec28b1d
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/Service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Service.h"
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/ResilientDevice.h>
+#include <string>
+#include "Device.h"
+
+namespace android::hardware::neuralnetworks::V1_0::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+ hal::utils::ResilientDevice::Factory makeDevice =
+ [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ auto service = blocking ? IDevice::getService(name) : IDevice::tryGetService(name);
+ if (service == nullptr) {
+ return NN_ERROR() << (blocking ? "getService" : "tryGetService") << " returned nullptr";
+ }
+ return Device::create(name, std::move(service));
+ };
+
+ return hal::utils::ResilientDevice::create(std::move(makeDevice));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
index 1a55c2f..66fefb1 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -43,6 +43,7 @@
std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite, \
testing::Combine(testing::ValuesIn(getNamedDevices()), \
testing::ValuesIn(getNamedModels(filter))), \
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index 17f4613..d2cd20c 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -42,6 +42,7 @@
const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
#define INSTANTIATE_DEVICE_TEST(TestSuite) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
printNeuralnetworksHidlTest)
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index bef21c0..52d866f 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.neuralnetworks@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDevice.hal",
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
new file mode 100644
index 0000000..909575b
--- /dev/null
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_1_1",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal/1.1/"],
+ export_include_dirs: ["include"],
+ cflags: ["-Wthread-safety"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_common",
+ "neuralnetworks_utils_hal_1_0",
+ ],
+ shared_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ ],
+ export_static_lib_headers: [
+ "neuralnetworks_utils_hal_common",
+ ],
+}
diff --git a/neuralnetworks/1.1/utils/OWNERS b/neuralnetworks/1.1/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.1/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
new file mode 100644
index 0000000..16ddd53
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+GeneralResult<OperationType> convert(const hal::V1_1::OperationType& operationType);
+GeneralResult<Capabilities> convert(const hal::V1_1::Capabilities& capabilities);
+GeneralResult<Operation> convert(const hal::V1_1::Operation& operation);
+GeneralResult<Model> convert(const hal::V1_1::Model& model);
+GeneralResult<ExecutionPreference> convert(
+ const hal::V1_1::ExecutionPreference& executionPreference);
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Operation> convert(const nn::Operation& operation);
+nn::GeneralResult<Model> convert(const nn::Model& model);
+nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference);
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
new file mode 100644
index 0000000..c1e95fe1a
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_DEVICE_H
+
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+class Device final : public nn::IDevice {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Device>> create(std::string name,
+ sp<V1_1::IDevice> device);
+
+ Device(PrivateConstructorTag tag, std::string name, nn::Capabilities capabilities,
+ sp<V1_1::IDevice> device, hal::utils::DeathHandler deathHandler);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString = "UNKNOWN";
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const sp<V1_1::IDevice> kDevice;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_DEVICE_H
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Service.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Service.h
new file mode 100644
index 0000000..a3ad3cf
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Service.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_SERVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_SERVICE_H
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <string>
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_SERVICE_H
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
new file mode 100644
index 0000000..0fee628
--- /dev/null
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_H
+
+#include "nnapi/hal/1.1/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+constexpr auto kDefaultExecutionPreference = ExecutionPreference::FAST_SINGLE_ANSWER;
+constexpr auto kVersion = nn::Version::ANDROID_P;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+ const auto maybeCanonical = nn::convert(halObject);
+ if (!maybeCanonical.has_value()) {
+ return nn::error() << maybeCanonical.error().message;
+ }
+ const auto version = NN_TRY(nn::validate(maybeCanonical.value()));
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+ const auto result = utils::validate(halObject);
+ if (!result.has_value()) {
+ LOG(ERROR) << result.error();
+ }
+ return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+ auto canonical = NN_TRY(nn::convert(halObject));
+ const auto maybeVersion = nn::validate(canonical);
+ if (!maybeVersion.has_value()) {
+ return nn::error() << maybeVersion.error();
+ }
+ const auto version = maybeVersion.value();
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return canonical;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_UTILS_H
diff --git a/neuralnetworks/1.1/utils/src/Assertions.cpp b/neuralnetworks/1.1/utils/src/Assertions.cpp
new file mode 100644
index 0000000..ba4a388
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Assertions.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(type) \
+ static_assert(std::is_same_v< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_1::type>, \
+ std::underlying_type_t<::android::nn::type>>, \
+ "::android::hardware::neuralnetworks::V1_1::" #type \
+ " does not have the same underlying type as ::android::nn::" #type)
+
+COMPARE_ENUMS_TYPES(OperationType);
+COMPARE_ENUMS_TYPES(ExecutionPreference);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, type) \
+ static_assert( \
+ static_cast<std::underlying_type_t<::android::hardware::neuralnetworks::V1_1::type>>( \
+ ::android::hardware::neuralnetworks::V1_1::type::symbol) == \
+ static_cast<std::underlying_type_t<::android::nn::type>>( \
+ ::android::nn::type::symbol), \
+ "::android::hardware::neuralnetworks::V1_1::" #type "::" #symbol \
+ " does not match ::android::nn::" #type "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, ExecutionPreference)
+
+COMPARE_ENUMS(LOW_POWER);
+COMPARE_ENUMS(FAST_SINGLE_ANSWER);
+COMPARE_ENUMS(SUSTAINED_SPEED);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+} // anonymous namespace
diff --git a/neuralnetworks/1.1/utils/src/Conversions.cpp b/neuralnetworks/1.1/utils/src/Conversions.cpp
new file mode 100644
index 0000000..ffe0752
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Conversions.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+namespace android::nn {
+namespace {
+
+using hardware::hidl_vec;
+
+template <typename Input>
+using convertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+GeneralResult<std::vector<convertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+ std::vector<convertOutput<Type>> canonical;
+ canonical.reserve(arguments.size());
+ for (const auto& argument : arguments) {
+ canonical.push_back(NN_TRY(nn::convert(argument)));
+ }
+ return canonical;
+}
+
+} // anonymous namespace
+
+GeneralResult<OperationType> convert(const hal::V1_1::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+GeneralResult<Capabilities> convert(const hal::V1_1::Capabilities& capabilities) {
+ const auto quantized8Performance = NN_TRY(convert(capabilities.quantized8Performance));
+ const auto float32Performance = NN_TRY(convert(capabilities.float32Performance));
+ const auto relaxedFloat32toFloat16Performance =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16Performance));
+
+ auto table = hal::utils::makeQuantized8PerformanceConsistentWithP(float32Performance,
+ quantized8Performance);
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16Performance,
+ .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16Performance,
+ .operandPerformance = std::move(table),
+ };
+}
+
+GeneralResult<Operation> convert(const hal::V1_1::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+GeneralResult<Model> convert(const hal::V1_1::Model& model) {
+ auto operations = NN_TRY(convert(model.operations));
+
+ // Verify number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+ CHECK(model.operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < model.operands.size(); ++i) {
+ if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid numberOfConsumers for operand " << i << ", expected "
+ << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
+ }
+ }
+
+ auto main = Model::Subgraph{
+ .operands = NN_TRY(convert(model.operands)),
+ .operations = std::move(operations),
+ .inputIndexes = model.inputIndexes,
+ .outputIndexes = model.outputIndexes,
+ };
+
+ return Model{
+ .main = std::move(main),
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ };
+}
+
+GeneralResult<ExecutionPreference> convert(
+ const hal::V1_1::ExecutionPreference& executionPreference) {
+ return static_cast<ExecutionPreference>(executionPreference);
+}
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+namespace {
+
+using utils::convert;
+
+nn::GeneralResult<V1_0::PerformanceInfo> convert(
+ const nn::Capabilities::PerformanceInfo& performanceInfo) {
+ return V1_0::utils::convert(performanceInfo);
+}
+
+nn::GeneralResult<V1_0::Operand> convert(const nn::Operand& operand) {
+ return V1_0::utils::convert(operand);
+}
+
+nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+ return V1_0::utils::convert(operandValues);
+}
+
+nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
+ return V1_0::utils::convert(memory);
+}
+
+template <typename Input>
+using convertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<convertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+ hidl_vec<convertOutput<Type>> halObject(arguments.size());
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ halObject[i] = NN_TRY(convert(arguments[i]));
+ }
+ return halObject;
+}
+
+} // anonymous namespace
+
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+ return Capabilities{
+ .float32Performance = NN_TRY(convert(
+ capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
+ .quantized8Performance = NN_TRY(convert(
+ capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
+ .relaxedFloat32toFloat16Performance =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+ };
+}
+
+nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+nn::GeneralResult<Model> convert(const nn::Model& model) {
+ if (!hal::utils::hasNoPointerData(model)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Mdoel cannot be converted because it contains pointer-based memory";
+ }
+
+ auto operands = NN_TRY(convert(model.main.operands));
+
+ // Update number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+ CHECK(operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < operands.size(); ++i) {
+ operands[i].numberOfConsumers = numberOfConsumers[i];
+ }
+
+ return Model{
+ .operands = std::move(operands),
+ .operations = NN_TRY(convert(model.main.operations)),
+ .inputIndexes = model.main.inputIndexes,
+ .outputIndexes = model.main.outputIndexes,
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ };
+}
+
+nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference) {
+ return static_cast<ExecutionPreference>(executionPreference);
+}
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
new file mode 100644
index 0000000..a0378c9
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Device.h"
+
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+namespace {
+
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_1::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getCapabilities_1_1 failed with " << toString(status);
+ } else {
+ result = validatedConvertToCanonical(capabilities);
+ }
+ };
+
+ const auto ret = device->getCapabilities_1_1(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
+ sp<V1_1::IDevice> device) {
+ if (name.empty()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_1::utils::Device::create must have non-empty name";
+ }
+ if (device == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_1::utils::Device::create must have non-null device";
+ }
+
+ auto capabilities = NN_TRY(initCapabilities(device.get()));
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
+ return std::make_shared<const Device>(PrivateConstructorTag{}, std::move(name),
+ std::move(capabilities), std::move(device),
+ std::move(deathHandler));
+}
+
+Device::Device(PrivateConstructorTag /*tag*/, std::string name, nn::Capabilities capabilities,
+ sp<V1_1::IDevice> device, hal::utils::DeathHandler deathHandler)
+ : kName(std::move(name)),
+ kCapabilities(std::move(capabilities)),
+ kDevice(std::move(device)),
+ kDeathHandler(std::move(deathHandler)) {}
+
+const std::string& Device::getName() const {
+ return kName;
+}
+
+const std::string& Device::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version Device::getFeatureLevel() const {
+ return nn::Version::ANDROID_P;
+}
+
+nn::DeviceType Device::getType() const {
+ return nn::DeviceType::UNKNOWN;
+}
+
+const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& Device::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> Device::getNumberOfCacheFilesNeeded() const {
+ return std::make_pair(/*numModelCache=*/0, /*numDataCache=*/0);
+}
+
+nn::GeneralResult<void> Device::wait() const {
+ const auto ret = kDevice->ping();
+ return hal::utils::handleTransportError(ret);
+}
+
+nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Model& model) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+
+ nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ auto cb = [&result, &model](V1_0::ErrorStatus status,
+ const hidl_vec<bool>& supportedOperations) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical)
+ << "getSupportedOperations_1_1 failed with " << toString(status);
+ } else if (supportedOperations.size() != model.main.operations.size()) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "getSupportedOperations_1_1 returned vector of size "
+ << supportedOperations.size() << " but expected "
+ << model.main.operations.size();
+ } else {
+ result = supportedOperations;
+ }
+ };
+
+ const auto ret = kDevice->getSupportedOperations_1_1(hidlModel, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/,
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+ const auto hidlPreference = NN_TRY(convert(preference));
+
+ const auto cb = sp<V1_0::utils::PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kDevice->prepareModel_1_1(hidlModel, hidlPreference, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModel failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache(
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::prepareModelFromCache not supported on 1.1 HAL service";
+}
+
+nn::GeneralResult<nn::SharedBuffer> Device::allocate(
+ const nn::BufferDesc& /*desc*/,
+ const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+ const std::vector<nn::BufferRole>& /*inputRoles*/,
+ const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::allocate not supported on 1.1 HAL service";
+}
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
diff --git a/neuralnetworks/1.1/utils/src/Service.cpp b/neuralnetworks/1.1/utils/src/Service.cpp
new file mode 100644
index 0000000..e2d3240
--- /dev/null
+++ b/neuralnetworks/1.1/utils/src/Service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Service.h"
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/ResilientDevice.h>
+#include <string>
+#include "Device.h"
+
+namespace android::hardware::neuralnetworks::V1_1::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+ hal::utils::ResilientDevice::Factory makeDevice =
+ [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ auto service = blocking ? IDevice::getService(name) : IDevice::tryGetService(name);
+ if (service == nullptr) {
+ return NN_ERROR() << (blocking ? "getService" : "tryGetService") << " returned nullptr";
+ }
+ return Device::create(name, std::move(service));
+ };
+
+ return hal::utils::ResilientDevice::create(std::move(makeDevice));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_1::utils
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
index 4b1a96e..7a4a03b 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
@@ -43,6 +43,7 @@
std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite, \
testing::Combine(testing::ValuesIn(getNamedDevices()), \
testing::ValuesIn(getNamedModels(filter))), \
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index e879d84..208a930 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -41,6 +41,7 @@
const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
#define INSTANTIATE_DEVICE_TEST(TestSuite) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
printNeuralnetworksHidlTest)
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 4aa90aa..9e1db1e 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.neuralnetworks@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBurstCallback.hal",
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index ff20c12..5fb339f 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -40,7 +40,7 @@
* NNAPI applications filter devices based on their needs:
* - An application demands a certain level of performance, but a specific version of
* the driver cannot meet that requirement because of a performance regression.
- * The application can blacklist the driver based on the version provided.
+ * The application can disallow the driver based on the version provided.
* - An application has a minimum precision requirement, but certain versions of
* the driver cannot meet that requirement because of bugs or certain optimizations.
* The application can filter out versions of these drivers.
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 92cf2aa..7441a54 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -4853,15 +4853,18 @@
/**
* Quantized scale of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
- * TENSOR_INT32.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
float scale;
/**
* Quantized zero-point offset of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
int32_t zeroPoint;
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
index d197f6b..21d88ac 100644
--- a/neuralnetworks/1.2/types.t
+++ b/neuralnetworks/1.2/types.t
@@ -251,15 +251,18 @@
/**
* Quantized scale of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
- * TENSOR_INT32.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
float scale;
/**
* Quantized zero-point offset of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
int32_t zeroPoint;
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
new file mode 100644
index 0000000..22e8659
--- /dev/null
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_1_2",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal/1.2/"],
+ export_include_dirs: ["include"],
+ cflags: ["-Wthread-safety"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_common",
+ "neuralnetworks_utils_hal_1_0",
+ "neuralnetworks_utils_hal_1_1",
+ ],
+ shared_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ ],
+ export_static_lib_headers: [
+ "neuralnetworks_utils_hal_common",
+ ],
+}
diff --git a/neuralnetworks/1.2/utils/OWNERS b/neuralnetworks/1.2/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.2/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
new file mode 100644
index 0000000..bc7d92a
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_CALLBACKS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_CALLBACKS_H
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+class PreparedModelCallback final : public IPreparedModelCallback,
+ public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::GeneralResult<nn::SharedPreparedModel>;
+
+ Return<void> notify(V1_0::ErrorStatus status,
+ const sp<V1_0::IPreparedModel>& preparedModel) override;
+ Return<void> notify_1_2(V1_0::ErrorStatus status,
+ const sp<IPreparedModel>& preparedModel) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
+
+ Return<void> notify(V1_0::ErrorStatus status) override;
+ Return<void> notify_1_2(V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+ const Timing& timing) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_CALLBACKS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
new file mode 100644
index 0000000..24911fe
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+GeneralResult<OperandType> convert(const hal::V1_2::OperandType& operandType);
+GeneralResult<OperationType> convert(const hal::V1_2::OperationType& operationType);
+GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType);
+GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities);
+GeneralResult<Capabilities::OperandPerformance> convert(
+ const hal::V1_2::Capabilities::OperandPerformance& operandPerformance);
+GeneralResult<Operation> convert(const hal::V1_2::Operation& operation);
+GeneralResult<Operand::SymmPerChannelQuantParams> convert(
+ const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams);
+GeneralResult<Operand> convert(const hal::V1_2::Operand& operand);
+GeneralResult<Operand::ExtraParams> convert(const hal::V1_2::Operand::ExtraParams& extraParams);
+GeneralResult<Model> convert(const hal::V1_2::Model& model);
+GeneralResult<Model::ExtensionNameAndPrefix> convert(
+ const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+GeneralResult<OutputShape> convert(const hal::V1_2::OutputShape& outputShape);
+GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming);
+GeneralResult<Timing> convert(const hal::V1_2::Timing& timing);
+GeneralResult<Extension> convert(const hal::V1_2::Extension& extension);
+GeneralResult<Extension::OperandTypeInformation> convert(
+ const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation);
+GeneralResult<SharedHandle> convert(const hardware::hidl_handle& handle);
+
+GeneralResult<std::vector<Extension>> convert(
+ const hardware::hidl_vec<hal::V1_2::Extension>& extensions);
+GeneralResult<std::vector<SharedHandle>> convert(
+ const hardware::hidl_vec<hardware::hidl_handle>& handles);
+GeneralResult<std::vector<OutputShape>> convert(
+ const hardware::hidl_vec<hal::V1_2::OutputShape>& outputShapes);
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType);
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType);
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Capabilities::OperandPerformance> convert(
+ const nn::Capabilities::OperandPerformance& operandPerformance);
+nn::GeneralResult<Operation> convert(const nn::Operation& operation);
+nn::GeneralResult<SymmPerChannelQuantParams> convert(
+ const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams);
+nn::GeneralResult<Operand> convert(const nn::Operand& operand);
+nn::GeneralResult<Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams);
+nn::GeneralResult<Model> convert(const nn::Model& model);
+nn::GeneralResult<Model::ExtensionNameAndPrefix> convert(
+ const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+nn::GeneralResult<OutputShape> convert(const nn::OutputShape& outputShape);
+nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming);
+nn::GeneralResult<Timing> convert(const nn::Timing& timing);
+nn::GeneralResult<Extension> convert(const nn::Extension& extension);
+nn::GeneralResult<Extension::OperandTypeInformation> convert(
+ const nn::Extension::OperandTypeInformation& operandTypeInformation);
+nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle);
+
+nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions);
+nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles);
+nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes);
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
new file mode 100644
index 0000000..bbd5343
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_DEVICE_H
+
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device);
+nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device);
+nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device);
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device);
+nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
+ V1_2::IDevice* device);
+
+class Device final : public nn::IDevice {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Device>> create(std::string name,
+ sp<V1_2::IDevice> device);
+
+ Device(PrivateConstructorTag tag, std::string name, std::string versionString,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities, std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
+ sp<V1_2::IDevice> device, hal::utils::DeathHandler deathHandler);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString;
+ const nn::DeviceType kDeviceType;
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
+ const sp<V1_2::IDevice> kDevice;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_DEVICE_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
new file mode 100644
index 0000000..65e1e8a
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_PREPARED_MODEL_H
+
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+class PreparedModel final : public nn::IPreparedModel {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
+ sp<V1_2::IPreparedModel> preparedModel);
+
+ PreparedModel(PrivateConstructorTag tag, sp<V1_2::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler);
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+
+ private:
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeSynchronously(
+ const V1_0::Request& request, MeasureTiming measure) const;
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeAsynchronously(
+ const V1_0::Request& request, MeasureTiming measure) const;
+
+ const sp<V1_2::IPreparedModel> kPreparedModel;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_PREPARED_MODEL_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Service.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Service.h
new file mode 100644
index 0000000..44f004f
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Service.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_SERVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_SERVICE_H
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <string>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_SERVICE_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
new file mode 100644
index 0000000..a9a6bae
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_H
+
+#include "nnapi/hal/1.2/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.1/Conversions.h>
+
+#include <limits>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+constexpr auto kDefaultMesaureTiming = MeasureTiming::NO;
+constexpr auto kNoTiming = Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
+ .timeInDriver = std::numeric_limits<uint64_t>::max()};
+constexpr auto kVersion = nn::Version::ANDROID_Q;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+ const auto maybeCanonical = nn::convert(halObject);
+ if (!maybeCanonical.has_value()) {
+ return nn::error() << maybeCanonical.error().message;
+ }
+ const auto version = NN_TRY(nn::validate(maybeCanonical.value()));
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+ const auto result = utils::validate(halObject);
+ if (!result.has_value()) {
+ LOG(ERROR) << result.error();
+ }
+ return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+ auto canonical = NN_TRY(nn::convert(halObject));
+ const auto maybeVersion = nn::validate(canonical);
+ if (!maybeVersion.has_value()) {
+ return nn::error() << maybeVersion.error();
+ }
+ const auto version = maybeVersion.value();
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return canonical;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_H
diff --git a/neuralnetworks/1.2/utils/src/Assertions.cpp b/neuralnetworks/1.2/utils/src/Assertions.cpp
new file mode 100644
index 0000000..9d9716a
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Assertions.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(type) \
+ static_assert(std::is_same_v< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_2::type>, \
+ std::underlying_type_t<::android::nn::type>>, \
+ "::android::hardware::neuralnetworks::V1_2::" #type \
+ " does not have the same underlying type as ::android::nn::" #type)
+
+COMPARE_ENUMS_TYPES(OperandType);
+COMPARE_ENUMS_TYPES(OperationType);
+COMPARE_ENUMS_TYPES(DeviceType);
+COMPARE_ENUMS_TYPES(MeasureTiming);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, type) \
+ static_assert( \
+ static_cast<std::underlying_type_t<::android::hardware::neuralnetworks::V1_2::type>>( \
+ ::android::hardware::neuralnetworks::V1_2::type::symbol) == \
+ static_cast<std::underlying_type_t<::android::nn::type>>( \
+ ::android::nn::type::symbol), \
+ "::android::hardware::neuralnetworks::V1_2::" #type "::" #symbol \
+ " does not match ::android::nn::" #type "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(BOOL);
+COMPARE_ENUMS(TENSOR_QUANT16_SYMM);
+COMPARE_ENUMS(TENSOR_FLOAT16);
+COMPARE_ENUMS(TENSOR_BOOL8);
+COMPARE_ENUMS(FLOAT16);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM_PER_CHANNEL);
+COMPARE_ENUMS(TENSOR_QUANT16_ASYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(ABS);
+COMPARE_ENUMS(ARGMAX);
+COMPARE_ENUMS(ARGMIN);
+COMPARE_ENUMS(AXIS_ALIGNED_BBOX_TRANSFORM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(BOX_WITH_NMS_LIMIT);
+COMPARE_ENUMS(CAST);
+COMPARE_ENUMS(CHANNEL_SHUFFLE);
+COMPARE_ENUMS(DETECTION_POSTPROCESSING);
+COMPARE_ENUMS(EQUAL);
+COMPARE_ENUMS(EXP);
+COMPARE_ENUMS(EXPAND_DIMS);
+COMPARE_ENUMS(GATHER);
+COMPARE_ENUMS(GENERATE_PROPOSALS);
+COMPARE_ENUMS(GREATER);
+COMPARE_ENUMS(GREATER_EQUAL);
+COMPARE_ENUMS(GROUPED_CONV_2D);
+COMPARE_ENUMS(HEATMAP_MAX_KEYPOINT);
+COMPARE_ENUMS(INSTANCE_NORMALIZATION);
+COMPARE_ENUMS(LESS);
+COMPARE_ENUMS(LESS_EQUAL);
+COMPARE_ENUMS(LOG);
+COMPARE_ENUMS(LOGICAL_AND);
+COMPARE_ENUMS(LOGICAL_NOT);
+COMPARE_ENUMS(LOGICAL_OR);
+COMPARE_ENUMS(LOG_SOFTMAX);
+COMPARE_ENUMS(MAXIMUM);
+COMPARE_ENUMS(MINIMUM);
+COMPARE_ENUMS(NEG);
+COMPARE_ENUMS(NOT_EQUAL);
+COMPARE_ENUMS(PAD_V2);
+COMPARE_ENUMS(POW);
+COMPARE_ENUMS(PRELU);
+COMPARE_ENUMS(QUANTIZE);
+COMPARE_ENUMS(QUANTIZED_16BIT_LSTM);
+COMPARE_ENUMS(RANDOM_MULTINOMIAL);
+COMPARE_ENUMS(REDUCE_ALL);
+COMPARE_ENUMS(REDUCE_ANY);
+COMPARE_ENUMS(REDUCE_MAX);
+COMPARE_ENUMS(REDUCE_MIN);
+COMPARE_ENUMS(REDUCE_PROD);
+COMPARE_ENUMS(REDUCE_SUM);
+COMPARE_ENUMS(ROI_ALIGN);
+COMPARE_ENUMS(ROI_POOLING);
+COMPARE_ENUMS(RSQRT);
+COMPARE_ENUMS(SELECT);
+COMPARE_ENUMS(SIN);
+COMPARE_ENUMS(SLICE);
+COMPARE_ENUMS(SPLIT);
+COMPARE_ENUMS(SQRT);
+COMPARE_ENUMS(TILE);
+COMPARE_ENUMS(TOPK_V2);
+COMPARE_ENUMS(TRANSPOSE_CONV_2D);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(RESIZE_NEAREST_NEIGHBOR);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, DeviceType)
+
+COMPARE_ENUMS(OTHER);
+COMPARE_ENUMS(CPU);
+COMPARE_ENUMS(GPU);
+COMPARE_ENUMS(ACCELERATOR);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, MeasureTiming)
+
+COMPARE_ENUMS(NO);
+COMPARE_ENUMS(YES);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+} // anonymous namespace
diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp
new file mode 100644
index 0000000..cb739f0
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Callbacks.h"
+
+#include "Conversions.h"
+#include "PreparedModel.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/PreparedModel.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <utility>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<V1_0::IPreparedModel>& preparedModel) {
+ return NN_TRY(V1_0::utils::PreparedModel::create(preparedModel));
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<IPreparedModel>& preparedModel) {
+ return NN_TRY(utils::PreparedModel::create(preparedModel));
+}
+
+nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionGeneralResultsHelper(const hidl_vec<OutputShape>& outputShapes,
+ const Timing& timing) {
+ return std::make_pair(NN_TRY(validatedConvertToCanonical(outputShapes)),
+ NN_TRY(validatedConvertToCanonical(timing)));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionGeneralResults(const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+ return hal::utils::makeExecutionFailure(
+ convertExecutionGeneralResultsHelper(outputShapes, timing));
+}
+
+} // namespace
+
+Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
+ const sp<V1_0::IPreparedModel>& preparedModel) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_2(V1_0::ErrorStatus status,
+ const sp<IPreparedModel>& preparedModel) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+void PreparedModelCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+PreparedModelCallback::Data PreparedModelCallback::get() {
+ return mData.take();
+}
+
+void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+// ExecutionCallback methods begin here
+
+Return<void> ExecutionCallback::notify(V1_0::ErrorStatus status) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal({});
+ }
+ return Void();
+}
+
+Return<void> ExecutionCallback::notify_1_2(V1_0::ErrorStatus status,
+ const hidl_vec<OutputShape>& outputShapes,
+ const Timing& timing) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
+ }
+ return Void();
+}
+
+void ExecutionCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+ExecutionCallback::Data ExecutionCallback::get() {
+ return mData.take();
+}
+
+void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
new file mode 100644
index 0000000..08c94de
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+ return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+} // namespace
+
+namespace android::nn {
+namespace {
+
+constexpr bool validOperandType(OperandType operandType) {
+ switch (operandType) {
+ case OperandType::FLOAT32:
+ case OperandType::INT32:
+ case OperandType::UINT32:
+ case OperandType::TENSOR_FLOAT32:
+ case OperandType::TENSOR_INT32:
+ case OperandType::TENSOR_QUANT8_ASYMM:
+ case OperandType::BOOL:
+ case OperandType::TENSOR_QUANT16_SYMM:
+ case OperandType::TENSOR_FLOAT16:
+ case OperandType::TENSOR_BOOL8:
+ case OperandType::FLOAT16:
+ case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+ case OperandType::TENSOR_QUANT16_ASYMM:
+ case OperandType::TENSOR_QUANT8_SYMM:
+ case OperandType::OEM:
+ case OperandType::TENSOR_OEM_BYTE:
+ return true;
+ default:
+ break;
+ }
+ return isExtension(operandType);
+}
+
+using hardware::hidl_handle;
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+GeneralResult<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
+ std::vector<ConvertOutput<Type>> canonical;
+ canonical.reserve(arguments.size());
+ for (const auto& argument : arguments) {
+ canonical.push_back(NN_TRY(nn::convert(argument)));
+ }
+ return canonical;
+}
+
+template <typename Type>
+GeneralResult<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+ return convertVec(arguments);
+}
+
+} // anonymous namespace
+
+GeneralResult<OperandType> convert(const hal::V1_2::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+GeneralResult<OperationType> convert(const hal::V1_2::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
+ return static_cast<DeviceType>(deviceType);
+}
+
+GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
+ const bool validOperandTypes = std::all_of(
+ capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
+ [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
+ const auto maybeType = convert(operandPerformance.type);
+ return !maybeType.has_value() ? false : validOperandType(maybeType.value());
+ });
+ if (!validOperandTypes) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid OperandType when converting OperandPerformance in Capabilities";
+ }
+
+ const auto relaxedFloat32toFloat16PerformanceScalar =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+ const auto relaxedFloat32toFloat16PerformanceTensor =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+ auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
+
+ auto table = NN_TRY(hal::utils::makeGeneralFailure(
+ Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
+ nn::ErrorStatus::GENERAL_FAILURE));
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+ .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
+ .operandPerformance = std::move(table),
+ };
+}
+
+GeneralResult<Capabilities::OperandPerformance> convert(
+ const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
+ return Capabilities::OperandPerformance{
+ .type = NN_TRY(convert(operandPerformance.type)),
+ .info = NN_TRY(convert(operandPerformance.info)),
+ };
+}
+
+GeneralResult<Operation> convert(const hal::V1_2::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+GeneralResult<Operand::SymmPerChannelQuantParams> convert(
+ const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
+ return Operand::SymmPerChannelQuantParams{
+ .scales = symmPerChannelQuantParams.scales,
+ .channelDim = symmPerChannelQuantParams.channelDim,
+ };
+}
+
+GeneralResult<Operand> convert(const hal::V1_2::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ .extraParams = NN_TRY(convert(operand.extraParams)),
+ };
+}
+
+GeneralResult<Operand::ExtraParams> convert(const hal::V1_2::Operand::ExtraParams& extraParams) {
+ using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
+ switch (extraParams.getDiscriminator()) {
+ case Discriminator::none:
+ return Operand::NoParams{};
+ case Discriminator::channelQuant:
+ return convert(extraParams.channelQuant());
+ case Discriminator::extension:
+ return extraParams.extension();
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Unrecognized Operand::ExtraParams discriminator: "
+ << underlyingType(extraParams.getDiscriminator());
+}
+
+GeneralResult<Model> convert(const hal::V1_2::Model& model) {
+ auto operations = NN_TRY(convert(model.operations));
+
+ // Verify number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(model.operands.size(), operations);
+ CHECK(model.operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < model.operands.size(); ++i) {
+ if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid numberOfConsumers for operand " << i << ", expected "
+ << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
+ }
+ }
+
+ auto main = Model::Subgraph{
+ .operands = NN_TRY(convert(model.operands)),
+ .operations = std::move(operations),
+ .inputIndexes = model.inputIndexes,
+ .outputIndexes = model.outputIndexes,
+ };
+
+ return Model{
+ .main = std::move(main),
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+ };
+}
+
+GeneralResult<Model::ExtensionNameAndPrefix> convert(
+ const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+ return Model::ExtensionNameAndPrefix{
+ .name = extensionNameAndPrefix.name,
+ .prefix = extensionNameAndPrefix.prefix,
+ };
+}
+
+GeneralResult<OutputShape> convert(const hal::V1_2::OutputShape& outputShape) {
+ return OutputShape{
+ .dimensions = outputShape.dimensions,
+ .isSufficient = outputShape.isSufficient,
+ };
+}
+
+GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
+ return static_cast<MeasureTiming>(measureTiming);
+}
+
+GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
+ return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+}
+
+GeneralResult<Extension> convert(const hal::V1_2::Extension& extension) {
+ return Extension{
+ .name = extension.name,
+ .operandTypes = NN_TRY(convert(extension.operandTypes)),
+ };
+}
+
+GeneralResult<Extension::OperandTypeInformation> convert(
+ const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
+ return Extension::OperandTypeInformation{
+ .type = operandTypeInformation.type,
+ .isTensor = operandTypeInformation.isTensor,
+ .byteSize = operandTypeInformation.byteSize,
+ };
+}
+
+GeneralResult<SharedHandle> convert(const hidl_handle& hidlHandle) {
+ return hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle());
+}
+
+GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
+ return convertVec(extensions);
+}
+
+GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
+ return convertVec(handles);
+}
+
+GeneralResult<std::vector<OutputShape>> convert(
+ const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
+ return convertVec(outputShapes);
+}
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+using utils::convert;
+
+nn::GeneralResult<V1_0::OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime) {
+ return V1_0::utils::convert(lifetime);
+}
+
+nn::GeneralResult<V1_0::PerformanceInfo> convert(
+ const nn::Capabilities::PerformanceInfo& performanceInfo) {
+ return V1_0::utils::convert(performanceInfo);
+}
+
+nn::GeneralResult<V1_0::DataLocation> convert(const nn::DataLocation& location) {
+ return V1_0::utils::convert(location);
+}
+
+nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+ return V1_0::utils::convert(operandValues);
+}
+
+nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
+ return V1_0::utils::convert(memory);
+}
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
+ hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ halObject[i] = NN_TRY(convert(arguments[i]));
+ }
+ return halObject;
+}
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+ return convertVec(arguments);
+}
+
+nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
+ return Operand::ExtraParams{};
+}
+
+nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
+ const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
+ Operand::ExtraParams ret;
+ ret.channelQuant(NN_TRY(convert(channelQuant)));
+ return ret;
+}
+
+nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
+ const nn::Operand::ExtensionParams& extension) {
+ Operand::ExtraParams ret;
+ ret.extension(extension);
+ return ret;
+}
+
+} // anonymous namespace
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
+ switch (deviceType) {
+ case nn::DeviceType::UNKNOWN:
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
+ case nn::DeviceType::OTHER:
+ case nn::DeviceType::CPU:
+ case nn::DeviceType::GPU:
+ case nn::DeviceType::ACCELERATOR:
+ return static_cast<DeviceType>(deviceType);
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid DeviceType " << underlyingType(deviceType);
+}
+
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+ std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
+ operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+ std::copy_if(capabilities.operandPerformance.asVector().begin(),
+ capabilities.operandPerformance.asVector().end(),
+ std::back_inserter(operandPerformance),
+ [](const nn::Capabilities::OperandPerformance& operandPerformance) {
+ return nn::validOperandType(operandPerformance.type);
+ });
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+ .relaxedFloat32toFloat16PerformanceTensor =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+ .operandPerformance = NN_TRY(convert(operandPerformance)),
+ };
+}
+
+nn::GeneralResult<Capabilities::OperandPerformance> convert(
+ const nn::Capabilities::OperandPerformance& operandPerformance) {
+ return Capabilities::OperandPerformance{
+ .type = NN_TRY(convert(operandPerformance.type)),
+ .info = NN_TRY(convert(operandPerformance.info)),
+ };
+}
+
+nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+nn::GeneralResult<SymmPerChannelQuantParams> convert(
+ const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
+ return SymmPerChannelQuantParams{
+ .scales = symmPerChannelQuantParams.scales,
+ .channelDim = symmPerChannelQuantParams.channelDim,
+ };
+}
+
+nn::GeneralResult<Operand> convert(const nn::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .numberOfConsumers = 0,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ .extraParams = NN_TRY(convert(operand.extraParams)),
+ };
+}
+
+nn::GeneralResult<Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
+ return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
+}
+
+nn::GeneralResult<Model> convert(const nn::Model& model) {
+ if (!hal::utils::hasNoPointerData(model)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Model cannot be converted because it contains pointer-based memory";
+ }
+
+ auto operands = NN_TRY(convert(model.main.operands));
+
+ // Update number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
+ CHECK(operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < operands.size(); ++i) {
+ operands[i].numberOfConsumers = numberOfConsumers[i];
+ }
+
+ return Model{
+ .operands = std::move(operands),
+ .operations = NN_TRY(convert(model.main.operations)),
+ .inputIndexes = model.main.inputIndexes,
+ .outputIndexes = model.main.outputIndexes,
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+ };
+}
+
+nn::GeneralResult<Model::ExtensionNameAndPrefix> convert(
+ const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+ return Model::ExtensionNameAndPrefix{
+ .name = extensionNameAndPrefix.name,
+ .prefix = extensionNameAndPrefix.prefix,
+ };
+}
+
+nn::GeneralResult<OutputShape> convert(const nn::OutputShape& outputShape) {
+ return OutputShape{.dimensions = outputShape.dimensions,
+ .isSufficient = outputShape.isSufficient};
+}
+
+nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
+ return static_cast<MeasureTiming>(measureTiming);
+}
+
+nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
+ return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+}
+
+nn::GeneralResult<Extension> convert(const nn::Extension& extension) {
+ return Extension{
+ .name = extension.name,
+ .operandTypes = NN_TRY(convert(extension.operandTypes)),
+ };
+}
+
+nn::GeneralResult<Extension::OperandTypeInformation> convert(
+ const nn::Extension::OperandTypeInformation& operandTypeInformation) {
+ return Extension::OperandTypeInformation{
+ .type = operandTypeInformation.type,
+ .isTensor = operandTypeInformation.isTensor,
+ .byteSize = operandTypeInformation.byteSize,
+ };
+}
+
+nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle) {
+ return hal::utils::hidlHandleFromSharedHandle(handle);
+}
+
+nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
+ return convertVec(extensions);
+}
+
+nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
+ return convertVec(handles);
+}
+
+nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
+ return convertVec(outputShapes);
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
new file mode 100644
index 0000000..517d61f
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Device.h"
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<std::string> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const hidl_string& versionString) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getVersionString failed with " << toString(status);
+ } else {
+ result = versionString;
+ }
+ };
+
+ const auto ret = device->getVersionString(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::DeviceType> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, DeviceType deviceType) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getDeviceType failed with " << toString(status);
+ } else {
+ result = nn::convert(deviceType);
+ }
+ };
+
+ const auto ret = device->getType(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<std::vector<nn::Extension>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getExtensions failed with " << toString(status);
+ } else {
+ result = nn::convert(extensions);
+ }
+ };
+
+ const auto ret = device->getSupportedExtensions(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
+ } else {
+ result = validatedConvertToCanonical(capabilities);
+ }
+ };
+
+ const auto ret = device->getCapabilities_1_2(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
+ V1_2::IDevice* device) {
+ CHECK(device != nullptr);
+
+ nn::GeneralResult<std::pair<uint32_t, uint32_t>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, uint32_t numModelCache,
+ uint32_t numDataCache) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical)
+ << "getNumberOfCacheFilesNeeded failed with " << toString(status);
+ } else {
+ result = std::make_pair(numModelCache, numDataCache);
+ }
+ };
+
+ const auto ret = device->getNumberOfCacheFilesNeeded(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
+ sp<V1_2::IDevice> device) {
+ if (name.empty()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_2::utils::Device::create must have non-empty name";
+ }
+ if (device == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_2::utils::Device::create must have non-null device";
+ }
+
+ auto versionString = NN_TRY(initVersionString(device.get()));
+ const auto deviceType = NN_TRY(initDeviceType(device.get()));
+ auto extensions = NN_TRY(initExtensions(device.get()));
+ auto capabilities = NN_TRY(initCapabilities(device.get()));
+ const auto numberOfCacheFilesNeeded = NN_TRY(initNumberOfCacheFilesNeeded(device.get()));
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
+ return std::make_shared<const Device>(
+ PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
+ std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
+ std::move(device), std::move(deathHandler));
+}
+
+Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded, sp<V1_2::IDevice> device,
+ hal::utils::DeathHandler deathHandler)
+ : kName(std::move(name)),
+ kVersionString(std::move(versionString)),
+ kDeviceType(deviceType),
+ kExtensions(std::move(extensions)),
+ kCapabilities(std::move(capabilities)),
+ kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded),
+ kDevice(std::move(device)),
+ kDeathHandler(std::move(deathHandler)) {}
+
+const std::string& Device::getName() const {
+ return kName;
+}
+
+const std::string& Device::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version Device::getFeatureLevel() const {
+ return nn::Version::ANDROID_Q;
+}
+
+nn::DeviceType Device::getType() const {
+ return kDeviceType;
+}
+
+const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& Device::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> Device::getNumberOfCacheFilesNeeded() const {
+ return kNumberOfCacheFilesNeeded;
+}
+
+nn::GeneralResult<void> Device::wait() const {
+ const auto ret = kDevice->ping();
+ return hal::utils::handleTransportError(ret);
+}
+
+nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Model& model) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+
+ nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ auto cb = [&result, &model](V1_0::ErrorStatus status,
+ const hidl_vec<bool>& supportedOperations) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical)
+ << "getSupportedOperations_1_2 failed with " << toString(status);
+ } else if (supportedOperations.size() != model.main.operations.size()) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "getSupportedOperations_1_2 returned vector of size "
+ << supportedOperations.size() << " but expected "
+ << model.main.operations.size();
+ } else {
+ result = supportedOperations;
+ }
+ };
+
+ const auto ret = kDevice->getSupportedOperations_1_2(hidlModel, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/,
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+ const auto hidlPreference = NN_TRY(V1_1::utils::convert(preference));
+ const auto hidlModelCache = NN_TRY(convert(modelCache));
+ const auto hidlDataCache = NN_TRY(convert(dataCache));
+ const auto hidlToken = token;
+
+ const auto cb = sp<PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kDevice->prepareModel_1_2(hidlModel, hidlPreference, hidlModelCache,
+ hidlDataCache, hidlToken, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModel_1_2 failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache(
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ const auto hidlModelCache = NN_TRY(convert(modelCache));
+ const auto hidlDataCache = NN_TRY(convert(dataCache));
+ const auto hidlToken = token;
+
+ const auto cb = sp<PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kDevice->prepareModelFromCache(hidlModelCache, hidlDataCache, hidlToken, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModelFromCache failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedBuffer> Device::allocate(
+ const nn::BufferDesc& /*desc*/,
+ const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+ const std::vector<nn::BufferRole>& /*inputRoles*/,
+ const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::allocate not supported on 1.2 HAL service";
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
new file mode 100644
index 0000000..ff9db21
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PreparedModel.h"
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionResultsHelper(const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+ return std::make_pair(NN_TRY(validatedConvertToCanonical(outputShapes)),
+ NN_TRY(validatedConvertToCanonical(timing)));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> convertExecutionResults(
+ const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+ return hal::utils::makeExecutionFailure(convertExecutionResultsHelper(outputShapes, timing));
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
+ sp<V1_2::IPreparedModel> preparedModel) {
+ if (preparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_2::utils::PreparedModel::create must have non-null preparedModel";
+ }
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
+ std::move(deathHandler));
+}
+
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, sp<V1_2::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler)
+ : kPreparedModel(std::move(preparedModel)), kDeathHandler(std::move(deathHandler)) {}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeSynchronously(const V1_0::Request& request, MeasureTiming measure) const {
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const auto cb = [&result](V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+ const Timing& timing) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "executeSynchronously failed with " << toString(status);
+ } else {
+ result = convertExecutionResults(outputShapes, timing);
+ }
+ };
+
+ const auto ret = kPreparedModel->executeSynchronously(request, measure, cb);
+ NN_TRY(hal::utils::makeExecutionFailure(hal::utils::handleTransportError(ret)));
+
+ return result;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeAsynchronously(const V1_0::Request& request, MeasureTiming measure) const {
+ const auto cb = sp<ExecutionCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kPreparedModel->execute_1_2(request, measure, cb);
+ const auto status =
+ NN_TRY(hal::utils::makeExecutionFailure(hal::utils::handleTransportError(ret)));
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "execute failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared)));
+
+ const auto hidlRequest =
+ NN_TRY(hal::utils::makeExecutionFailure(V1_0::utils::convert(requestInShared)));
+ const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const bool preferSynchronous = true;
+
+ // Execute synchronously if allowed.
+ if (preferSynchronous) {
+ result = executeSynchronously(hidlRequest, hidlMeasure);
+ }
+
+ // Run asymchronous execution if execution has not already completed.
+ if (!result.has_value()) {
+ result = executeAsynchronously(hidlRequest, hidlMeasure);
+ }
+
+ // Flush output buffers if suxcessful execution.
+ if (result.has_value()) {
+ NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
+ }
+
+ return result;
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IPreparedModel::executeFenced is not supported on 1.2 HAL service";
+}
+
+std::any PreparedModel::getUnderlyingResource() const {
+ sp<V1_0::IPreparedModel> resource = kPreparedModel;
+ return resource;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Service.cpp b/neuralnetworks/1.2/utils/src/Service.cpp
new file mode 100644
index 0000000..110188f
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Service.h"
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/ResilientDevice.h>
+#include <string>
+#include "Device.h"
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+ hal::utils::ResilientDevice::Factory makeDevice =
+ [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ auto service = blocking ? IDevice::getService(name) : IDevice::tryGetService(name);
+ if (service == nullptr) {
+ return NN_ERROR() << (blocking ? "getService" : "tryGetService") << " returned nullptr";
+ }
+ return Device::create(name, std::move(service));
+ };
+
+ return hal::utils::ResilientDevice::create(std::move(makeDevice));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/vts/functional/AndroidTest.xml b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
index 3f91618..5396d85 100644
--- a/neuralnetworks/1.2/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
@@ -28,5 +28,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_2TargetTest" />
+ <option name="native-test-timeout" value="20m" />
</test>
</configuration>
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 449b8f3..ede1600 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -251,7 +251,7 @@
for (uint32_t i = 0; i < mNumDataCache; i++) {
mDataCache.push_back({mCacheDir + "data" + std::to_string(i)});
}
- // Dummy handles, use AccessMode::WRITE_ONLY for createCacheHandles to create files.
+ // Sample handles, use AccessMode::WRITE_ONLY for createCacheHandles to create files.
hidl_vec<hidl_handle> modelHandle, dataHandle, tmpHandle;
createCacheHandles(mModelCache, AccessMode::WRITE_ONLY, &modelHandle);
createCacheHandles(mDataCache, AccessMode::WRITE_ONLY, &dataHandle);
@@ -469,18 +469,18 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- uint8_t dummyBytes[] = {0, 0};
- // Write a dummy integer to the cache.
+ uint8_t sampleBytes[] = {0, 0};
+ // Write a sample integer to the cache.
// The driver should be able to handle non-empty cache and non-zero fd offset.
for (uint32_t i = 0; i < modelCache.size(); i++) {
- ASSERT_EQ(write(modelCache[i].getNativeHandle()->data[0], &dummyBytes,
- sizeof(dummyBytes)),
- sizeof(dummyBytes));
+ ASSERT_EQ(write(modelCache[i].getNativeHandle()->data[0], &sampleBytes,
+ sizeof(sampleBytes)),
+ sizeof(sampleBytes));
}
for (uint32_t i = 0; i < dataCache.size(); i++) {
ASSERT_EQ(
- write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)),
- sizeof(dummyBytes));
+ write(dataCache[i].getNativeHandle()->data[0], &sampleBytes, sizeof(sampleBytes)),
+ sizeof(sampleBytes));
}
saveModelToCache(model, modelCache, dataCache);
}
@@ -492,14 +492,14 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- uint8_t dummyByte = 0;
+ uint8_t sampleByte = 0;
// Advance the offset of each handle by one byte.
// The driver should be able to handle non-zero fd offset.
for (uint32_t i = 0; i < modelCache.size(); i++) {
- ASSERT_GE(read(modelCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0);
+ ASSERT_GE(read(modelCache[i].getNativeHandle()->data[0], &sampleByte, 1), 0);
}
for (uint32_t i = 0; i < dataCache.size(); i++) {
- ASSERT_GE(read(dataCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0);
+ ASSERT_GE(read(dataCache[i].getNativeHandle()->data[0], &sampleByte, 1), 0);
}
prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
if (!mIsCachingSupported) {
@@ -1209,9 +1209,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type);
}
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest,
- testing::Combine(kNamedDeviceChoices, kOperandTypeChoices),
- printCompilationCachingTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CompilationCachingTest);
+INSTANTIATE_TEST_SUITE_P(TestCompilationCaching, CompilationCachingTest,
+ testing::Combine(kNamedDeviceChoices, kOperandTypeChoices),
+ printCompilationCachingTest);
using CompilationCachingSecurityTestParam = std::tuple<NamedDevice, OperandType, uint32_t>;
@@ -1365,9 +1366,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type + "_" + std::to_string(seed));
}
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
- testing::Combine(kNamedDeviceChoices, kOperandTypeChoices,
- testing::Range(0U, 10U)),
- printCompilationCachingSecurityTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CompilationCachingSecurityTest);
+INSTANTIATE_TEST_SUITE_P(TestCompilationCaching, CompilationCachingSecurityTest,
+ testing::Combine(kNamedDeviceChoices, kOperandTypeChoices,
+ testing::Range(0U, 10U)),
+ printCompilationCachingSecurityTest);
} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
index 98295ff..b72df88 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
@@ -47,6 +47,7 @@
std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite, \
testing::Combine(testing::ValuesIn(getNamedDevices()), \
testing::ValuesIn(getNamedModels(filter))), \
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index c4e2b15..a364b30 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -42,6 +42,7 @@
const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
#define INSTANTIATE_DEVICE_TEST(TestSuite) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
printNeuralnetworksHidlTest)
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index 7b02cc5..3e02c90 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.neuralnetworks@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IBuffer.hal",
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 3b2b14c..5f5ee03 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -5103,8 +5103,8 @@
* signature of this operation. That is, if the operation has (3 + n) inputs
* and m outputs, both subgraphs must have n inputs and m outputs with the same
* types, ranks, dimensions, scales,
- * zeroPoints, and extraParams as the corresponding operation inputs and
- * outputs.
+ * zeroPoints, and extraParams as the corresponding operation
+ * inputs and outputs.
* All of the operands mentioned must have fully specified dimensions.
*
* Inputs:
@@ -5170,15 +5170,15 @@
* * 0: A {@link OperandType::SUBGRAPH} reference to the condition
* subgraph. The subgraph must have (m + k + n) inputs with
* the same types, ranks, dimensions,
- * scales, zeroPoints, and extraParams as the corresponding inputs of
- * the WHILE operation and exactly one output of
- * {@link OperandType::TENSOR_BOOL8} and shape [1].
+ * scales, zeroPoints, and extraParams as the
+ * corresponding inputs of the WHILE operation and exactly one output
+ * of {@link OperandType::TENSOR_BOOL8} and shape [1].
* All of the operands mentioned must have fully specified dimensions.
* * 1: A {@link OperandType::SUBGRAPH} reference to the body subgraph.
* The subgraph must have (m + k + n) inputs and (m + k) outputs with
* the same types, ranks, dimensions,
- * scales, zeroPoints, and extraParams as the corresponding inputs and
- * outputs of the WHILE operation.
+ * scales, zeroPoints, and extraParams as the
+ * corresponding inputs and outputs of the WHILE operation.
* All of the operands mentioned must have fully specified dimensions.
* * (m inputs): Initial values for input-output operands.
* * (k inputs): Initial values for state-only operands.
@@ -5538,15 +5538,18 @@
/**
* Quantized scale of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
- * TENSOR_INT32.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
float scale;
/**
* Quantized zero-point offset of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
int32_t zeroPoint;
@@ -5740,8 +5743,8 @@
* Input data and information to be used in the execution of a prepared
* model.
*
- * The index of the input corresponds to the index in Model.inputIndexes.
- * E.g., input[i] corresponds to Model.inputIndexes[i].
+ * The index of the input corresponds to the index in Model.main.inputIndexes.
+ * E.g., input[i] corresponds to Model.main.inputIndexes[i].
*/
vec<RequestArgument> inputs;
@@ -5749,8 +5752,8 @@
* Output data and information to be used in the execution of a prepared
* model.
*
- * The index of the output corresponds to the index in Model.outputIndexes.
- * E.g., output[i] corresponds to Model.outputIndexes[i].
+ * The index of the output corresponds to the index in Model.main.outputIndexes.
+ * E.g., output[i] corresponds to Model.main.outputIndexes[i].
*/
vec<RequestArgument> outputs;
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 7220e37..2901d18 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -303,15 +303,18 @@
/**
* Quantized scale of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
- * TENSOR_INT32.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
float scale;
/**
* Quantized zero-point offset of the operand.
*
- * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ * Must be 0 when not applicable to an operand type.
+ *
+ * See {@link OperandType}.
*/
int32_t zeroPoint;
@@ -505,8 +508,8 @@
* Input data and information to be used in the execution of a prepared
* model.
*
- * The index of the input corresponds to the index in Model.inputIndexes.
- * E.g., input[i] corresponds to Model.inputIndexes[i].
+ * The index of the input corresponds to the index in Model.main.inputIndexes.
+ * E.g., input[i] corresponds to Model.main.inputIndexes[i].
*/
vec<RequestArgument> inputs;
@@ -514,8 +517,8 @@
* Output data and information to be used in the execution of a prepared
* model.
*
- * The index of the output corresponds to the index in Model.outputIndexes.
- * E.g., output[i] corresponds to Model.outputIndexes[i].
+ * The index of the output corresponds to the index in Model.main.outputIndexes.
+ * E.g., output[i] corresponds to Model.main.outputIndexes[i].
*/
vec<RequestArgument> outputs;
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
new file mode 100644
index 0000000..d5d897d
--- /dev/null
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_1_3",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal/1.3/"],
+ export_include_dirs: ["include"],
+ cflags: ["-Wthread-safety"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_common",
+ "neuralnetworks_utils_hal_1_0",
+ "neuralnetworks_utils_hal_1_1",
+ "neuralnetworks_utils_hal_1_2",
+ ],
+ shared_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ ],
+ export_static_lib_headers: [
+ "neuralnetworks_utils_hal_common",
+ ],
+}
diff --git a/neuralnetworks/1.3/utils/OWNERS b/neuralnetworks/1.3/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/1.3/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h
new file mode 100644
index 0000000..637179d
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_BUFFER_H
+
+#include <android/hardware/neuralnetworks/1.3/IBuffer.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <memory>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+class Buffer final : public nn::IBuffer {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Buffer>> create(
+ sp<V1_3::IBuffer> buffer, nn::Request::MemoryDomainToken token);
+
+ Buffer(PrivateConstructorTag tag, sp<V1_3::IBuffer> buffer,
+ nn::Request::MemoryDomainToken token);
+
+ nn::Request::MemoryDomainToken getToken() const override;
+
+ nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
+ nn::GeneralResult<void> copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const override;
+
+ private:
+ const sp<V1_3::IBuffer> kBuffer;
+ const nn::Request::MemoryDomainToken kToken;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_BUFFER_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
new file mode 100644
index 0000000..d46b111
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_CALLBACKS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_CALLBACKS_H
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+class PreparedModelCallback final : public IPreparedModelCallback,
+ public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::GeneralResult<nn::SharedPreparedModel>;
+
+ Return<void> notify(V1_0::ErrorStatus status,
+ const sp<V1_0::IPreparedModel>& preparedModel) override;
+ Return<void> notify_1_2(V1_0::ErrorStatus status,
+ const sp<V1_2::IPreparedModel>& preparedModel) override;
+ Return<void> notify_1_3(ErrorStatus status, const sp<IPreparedModel>& preparedModel) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
+ public:
+ using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
+
+ Return<void> notify(V1_0::ErrorStatus status) override;
+ Return<void> notify_1_2(V1_0::ErrorStatus status,
+ const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) override;
+ Return<void> notify_1_3(ErrorStatus status, const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) override;
+
+ void notifyAsDeadObject() override;
+
+ Data get();
+
+ private:
+ void notifyInternal(Data result);
+
+ hal::utils::TransferValue<Data> mData;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_CALLBACKS_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
new file mode 100644
index 0000000..64aa96e
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
+
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+
+namespace android::nn {
+
+GeneralResult<OperandType> convert(const hal::V1_3::OperandType& operandType);
+GeneralResult<OperationType> convert(const hal::V1_3::OperationType& operationType);
+GeneralResult<Priority> convert(const hal::V1_3::Priority& priority);
+GeneralResult<Capabilities> convert(const hal::V1_3::Capabilities& capabilities);
+GeneralResult<Capabilities::OperandPerformance> convert(
+ const hal::V1_3::Capabilities::OperandPerformance& operandPerformance);
+GeneralResult<Operation> convert(const hal::V1_3::Operation& operation);
+GeneralResult<Operand::LifeTime> convert(const hal::V1_3::OperandLifeTime& operandLifeTime);
+GeneralResult<Operand> convert(const hal::V1_3::Operand& operand);
+GeneralResult<Model> convert(const hal::V1_3::Model& model);
+GeneralResult<Model::Subgraph> convert(const hal::V1_3::Subgraph& subgraph);
+GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc);
+GeneralResult<BufferRole> convert(const hal::V1_3::BufferRole& bufferRole);
+GeneralResult<Request> convert(const hal::V1_3::Request& request);
+GeneralResult<Request::MemoryPool> convert(const hal::V1_3::Request::MemoryPool& memoryPool);
+GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint);
+GeneralResult<OptionalTimeoutDuration> convert(
+ const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration);
+GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus);
+
+GeneralResult<std::vector<BufferRole>> convert(
+ const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles);
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType);
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType);
+nn::GeneralResult<Priority> convert(const nn::Priority& priority);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Capabilities::OperandPerformance> convert(
+ const nn::Capabilities::OperandPerformance& operandPerformance);
+nn::GeneralResult<Operation> convert(const nn::Operation& operation);
+nn::GeneralResult<OperandLifeTime> convert(const nn::Operand::LifeTime& operandLifeTime);
+nn::GeneralResult<Operand> convert(const nn::Operand& operand);
+nn::GeneralResult<Model> convert(const nn::Model& model);
+nn::GeneralResult<Subgraph> convert(const nn::Model::Subgraph& subgraph);
+nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc);
+nn::GeneralResult<BufferRole> convert(const nn::BufferRole& bufferRole);
+nn::GeneralResult<Request> convert(const nn::Request& request);
+nn::GeneralResult<Request::MemoryPool> convert(const nn::Request::MemoryPool& memoryPool);
+nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint);
+nn::GeneralResult<OptionalTimeoutDuration> convert(
+ const nn::OptionalTimeoutDuration& optionalTimeoutDuration);
+nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
+
+nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
new file mode 100644
index 0000000..0f5234b
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_DEVICE_H
+
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+class Device final : public nn::IDevice {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Device>> create(std::string name,
+ sp<V1_3::IDevice> device);
+
+ Device(PrivateConstructorTag tag, std::string name, std::string versionString,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities, std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
+ sp<V1_3::IDevice> device, hal::utils::DeathHandler deathHandler);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString;
+ const nn::DeviceType kDeviceType;
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
+ const sp<V1_3::IDevice> kDevice;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_DEVICE_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
new file mode 100644
index 0000000..e0d69dd
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_PREPARED_MODEL_H
+
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+class PreparedModel final : public nn::IPreparedModel {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
+ sp<V1_3::IPreparedModel> preparedModel);
+
+ PreparedModel(PrivateConstructorTag tag, sp<V1_3::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler);
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+
+ private:
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeSynchronously(
+ const Request& request, V1_2::MeasureTiming measure, const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration) const;
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeAsynchronously(
+ const Request& request, V1_2::MeasureTiming measure, const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration) const;
+
+ const sp<V1_3::IPreparedModel> kPreparedModel;
+ const hal::utils::DeathHandler kDeathHandler;
+};
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_PREPARED_MODEL_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Service.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Service.h
new file mode 100644
index 0000000..2bc3257
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Service.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_SERVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_SERVICE_H
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <string>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_SERVICE_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
new file mode 100644
index 0000000..e61859d
--- /dev/null
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_H
+
+#include "nnapi/hal/1.3/Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/1.2/Conversions.h>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+constexpr auto kDefaultPriority = Priority::MEDIUM;
+constexpr auto kVersion = nn::Version::ANDROID_R;
+
+template <typename Type>
+nn::Result<void> validate(const Type& halObject) {
+ const auto maybeCanonical = nn::convert(halObject);
+ if (!maybeCanonical.has_value()) {
+ return nn::error() << maybeCanonical.error().message;
+ }
+ const auto version = NN_TRY(nn::validate(maybeCanonical.value()));
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return {};
+}
+
+template <typename Type>
+bool valid(const Type& halObject) {
+ const auto result = utils::validate(halObject);
+ if (!result.has_value()) {
+ LOG(ERROR) << result.error();
+ }
+ return result.has_value();
+}
+
+template <typename Type>
+decltype(nn::convert(std::declval<Type>())) validatedConvertToCanonical(const Type& halObject) {
+ auto canonical = NN_TRY(nn::convert(halObject));
+ const auto maybeVersion = nn::validate(canonical);
+ if (!maybeVersion.has_value()) {
+ return nn::error() << maybeVersion.error();
+ }
+ const auto version = maybeVersion.value();
+ if (version > utils::kVersion) {
+ return NN_ERROR() << "Insufficient version: " << version << " vs required "
+ << utils::kVersion;
+ }
+ return canonical;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_UTILS_H
diff --git a/neuralnetworks/1.3/utils/src/Assertions.cpp b/neuralnetworks/1.3/utils/src/Assertions.cpp
new file mode 100644
index 0000000..96d647a
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Assertions.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Types.h>
+#include <type_traits>
+
+namespace {
+
+#define COMPARE_ENUMS_TYPES(lhsType, rhsType) \
+ static_assert( \
+ std::is_same_v< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_3::lhsType>, \
+ std::underlying_type_t<::android::nn::rhsType>>, \
+ "::android::hardware::neuralnetworks::V1_3::" #lhsType \
+ " does not have the same underlying type as ::android::nn::" #rhsType)
+
+COMPARE_ENUMS_TYPES(OperandType, OperandType);
+COMPARE_ENUMS_TYPES(OperationType, OperationType);
+COMPARE_ENUMS_TYPES(Priority, Priority);
+COMPARE_ENUMS_TYPES(OperandLifeTime, Operand::LifeTime);
+COMPARE_ENUMS_TYPES(ErrorStatus, ErrorStatus);
+
+#undef COMPARE_ENUMS_TYPES
+
+#define COMPARE_ENUMS_FULL(symbol, lhsType, rhsType) \
+ static_assert( \
+ static_cast< \
+ std::underlying_type_t<::android::hardware::neuralnetworks::V1_3::lhsType>>( \
+ ::android::hardware::neuralnetworks::V1_3::lhsType::symbol) == \
+ static_cast<std::underlying_type_t<::android::nn::rhsType>>( \
+ ::android::nn::rhsType::symbol), \
+ "::android::hardware::neuralnetworks::V1_3::" #lhsType "::" #symbol \
+ " does not match ::android::nn::" #rhsType "::" #symbol)
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandType, OperandType)
+
+COMPARE_ENUMS(FLOAT32);
+COMPARE_ENUMS(INT32);
+COMPARE_ENUMS(UINT32);
+COMPARE_ENUMS(TENSOR_FLOAT32);
+COMPARE_ENUMS(TENSOR_INT32);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM);
+COMPARE_ENUMS(BOOL);
+COMPARE_ENUMS(TENSOR_QUANT16_SYMM);
+COMPARE_ENUMS(TENSOR_FLOAT16);
+COMPARE_ENUMS(TENSOR_BOOL8);
+COMPARE_ENUMS(FLOAT16);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM_PER_CHANNEL);
+COMPARE_ENUMS(TENSOR_QUANT16_ASYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_SYMM);
+COMPARE_ENUMS(TENSOR_QUANT8_ASYMM_SIGNED);
+COMPARE_ENUMS(SUBGRAPH);
+COMPARE_ENUMS(OEM);
+COMPARE_ENUMS(TENSOR_OEM_BYTE);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperationType, OperationType)
+
+COMPARE_ENUMS(ADD);
+COMPARE_ENUMS(AVERAGE_POOL_2D);
+COMPARE_ENUMS(CONCATENATION);
+COMPARE_ENUMS(CONV_2D);
+COMPARE_ENUMS(DEPTHWISE_CONV_2D);
+COMPARE_ENUMS(DEPTH_TO_SPACE);
+COMPARE_ENUMS(DEQUANTIZE);
+COMPARE_ENUMS(EMBEDDING_LOOKUP);
+COMPARE_ENUMS(FLOOR);
+COMPARE_ENUMS(FULLY_CONNECTED);
+COMPARE_ENUMS(HASHTABLE_LOOKUP);
+COMPARE_ENUMS(L2_NORMALIZATION);
+COMPARE_ENUMS(L2_POOL_2D);
+COMPARE_ENUMS(LOCAL_RESPONSE_NORMALIZATION);
+COMPARE_ENUMS(LOGISTIC);
+COMPARE_ENUMS(LSH_PROJECTION);
+COMPARE_ENUMS(LSTM);
+COMPARE_ENUMS(MAX_POOL_2D);
+COMPARE_ENUMS(MUL);
+COMPARE_ENUMS(RELU);
+COMPARE_ENUMS(RELU1);
+COMPARE_ENUMS(RELU6);
+COMPARE_ENUMS(RESHAPE);
+COMPARE_ENUMS(RESIZE_BILINEAR);
+COMPARE_ENUMS(RNN);
+COMPARE_ENUMS(SOFTMAX);
+COMPARE_ENUMS(SPACE_TO_DEPTH);
+COMPARE_ENUMS(SVDF);
+COMPARE_ENUMS(TANH);
+COMPARE_ENUMS(BATCH_TO_SPACE_ND);
+COMPARE_ENUMS(DIV);
+COMPARE_ENUMS(MEAN);
+COMPARE_ENUMS(PAD);
+COMPARE_ENUMS(SPACE_TO_BATCH_ND);
+COMPARE_ENUMS(SQUEEZE);
+COMPARE_ENUMS(STRIDED_SLICE);
+COMPARE_ENUMS(SUB);
+COMPARE_ENUMS(TRANSPOSE);
+COMPARE_ENUMS(ABS);
+COMPARE_ENUMS(ARGMAX);
+COMPARE_ENUMS(ARGMIN);
+COMPARE_ENUMS(AXIS_ALIGNED_BBOX_TRANSFORM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(BIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(BOX_WITH_NMS_LIMIT);
+COMPARE_ENUMS(CAST);
+COMPARE_ENUMS(CHANNEL_SHUFFLE);
+COMPARE_ENUMS(DETECTION_POSTPROCESSING);
+COMPARE_ENUMS(EQUAL);
+COMPARE_ENUMS(EXP);
+COMPARE_ENUMS(EXPAND_DIMS);
+COMPARE_ENUMS(GATHER);
+COMPARE_ENUMS(GENERATE_PROPOSALS);
+COMPARE_ENUMS(GREATER);
+COMPARE_ENUMS(GREATER_EQUAL);
+COMPARE_ENUMS(GROUPED_CONV_2D);
+COMPARE_ENUMS(HEATMAP_MAX_KEYPOINT);
+COMPARE_ENUMS(INSTANCE_NORMALIZATION);
+COMPARE_ENUMS(LESS);
+COMPARE_ENUMS(LESS_EQUAL);
+COMPARE_ENUMS(LOG);
+COMPARE_ENUMS(LOGICAL_AND);
+COMPARE_ENUMS(LOGICAL_NOT);
+COMPARE_ENUMS(LOGICAL_OR);
+COMPARE_ENUMS(LOG_SOFTMAX);
+COMPARE_ENUMS(MAXIMUM);
+COMPARE_ENUMS(MINIMUM);
+COMPARE_ENUMS(NEG);
+COMPARE_ENUMS(NOT_EQUAL);
+COMPARE_ENUMS(PAD_V2);
+COMPARE_ENUMS(POW);
+COMPARE_ENUMS(PRELU);
+COMPARE_ENUMS(QUANTIZE);
+COMPARE_ENUMS(QUANTIZED_16BIT_LSTM);
+COMPARE_ENUMS(RANDOM_MULTINOMIAL);
+COMPARE_ENUMS(REDUCE_ALL);
+COMPARE_ENUMS(REDUCE_ANY);
+COMPARE_ENUMS(REDUCE_MAX);
+COMPARE_ENUMS(REDUCE_MIN);
+COMPARE_ENUMS(REDUCE_PROD);
+COMPARE_ENUMS(REDUCE_SUM);
+COMPARE_ENUMS(ROI_ALIGN);
+COMPARE_ENUMS(ROI_POOLING);
+COMPARE_ENUMS(RSQRT);
+COMPARE_ENUMS(SELECT);
+COMPARE_ENUMS(SIN);
+COMPARE_ENUMS(SLICE);
+COMPARE_ENUMS(SPLIT);
+COMPARE_ENUMS(SQRT);
+COMPARE_ENUMS(TILE);
+COMPARE_ENUMS(TOPK_V2);
+COMPARE_ENUMS(TRANSPOSE_CONV_2D);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_LSTM);
+COMPARE_ENUMS(UNIDIRECTIONAL_SEQUENCE_RNN);
+COMPARE_ENUMS(RESIZE_NEAREST_NEIGHBOR);
+COMPARE_ENUMS(QUANTIZED_LSTM);
+COMPARE_ENUMS(IF);
+COMPARE_ENUMS(WHILE);
+COMPARE_ENUMS(ELU);
+COMPARE_ENUMS(HARD_SWISH);
+COMPARE_ENUMS(FILL);
+COMPARE_ENUMS(RANK);
+COMPARE_ENUMS(OEM_OPERATION);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, Priority, Priority)
+
+COMPARE_ENUMS(LOW);
+COMPARE_ENUMS(MEDIUM);
+COMPARE_ENUMS(HIGH);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, OperandLifeTime, Operand::LifeTime)
+
+COMPARE_ENUMS(TEMPORARY_VARIABLE);
+COMPARE_ENUMS(SUBGRAPH_INPUT);
+COMPARE_ENUMS(SUBGRAPH_OUTPUT);
+COMPARE_ENUMS(CONSTANT_COPY);
+COMPARE_ENUMS(CONSTANT_REFERENCE);
+COMPARE_ENUMS(NO_VALUE);
+COMPARE_ENUMS(SUBGRAPH);
+
+#undef COMPARE_ENUMS
+
+#define COMPARE_ENUMS(symbol) COMPARE_ENUMS_FULL(symbol, ErrorStatus, ErrorStatus)
+
+COMPARE_ENUMS(NONE);
+COMPARE_ENUMS(DEVICE_UNAVAILABLE);
+COMPARE_ENUMS(GENERAL_FAILURE);
+COMPARE_ENUMS(OUTPUT_INSUFFICIENT_SIZE);
+COMPARE_ENUMS(INVALID_ARGUMENT);
+COMPARE_ENUMS(MISSED_DEADLINE_TRANSIENT);
+COMPARE_ENUMS(MISSED_DEADLINE_PERSISTENT);
+COMPARE_ENUMS(RESOURCE_EXHAUSTED_TRANSIENT);
+COMPARE_ENUMS(RESOURCE_EXHAUSTED_PERSISTENT);
+
+#undef COMPARE_ENUMS
+
+#undef COMPARE_ENUMS_FULL
+
+} // anonymous namespace
diff --git a/neuralnetworks/1.3/utils/src/Buffer.cpp b/neuralnetworks/1.3/utils/src/Buffer.cpp
new file mode 100644
index 0000000..f3fe9b5
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Buffer.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Buffer.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IBuffer.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/HandleError.h>
+
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <memory>
+#include <utility>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+nn::GeneralResult<std::shared_ptr<const Buffer>> Buffer::create(
+ sp<V1_3::IBuffer> buffer, nn::Request::MemoryDomainToken token) {
+ if (buffer == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_3::utils::Buffer::create must have non-null buffer";
+ }
+ if (token == static_cast<nn::Request::MemoryDomainToken>(0)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_3::utils::Buffer::create must have non-zero token";
+ }
+
+ return std::make_shared<const Buffer>(PrivateConstructorTag{}, std::move(buffer), token);
+}
+
+Buffer::Buffer(PrivateConstructorTag /*tag*/, sp<V1_3::IBuffer> buffer,
+ nn::Request::MemoryDomainToken token)
+ : kBuffer(std::move(buffer)), kToken(token) {
+ CHECK(kBuffer != nullptr);
+ CHECK(kToken != static_cast<nn::Request::MemoryDomainToken>(0));
+}
+
+nn::Request::MemoryDomainToken Buffer::getToken() const {
+ return kToken;
+}
+
+nn::GeneralResult<void> Buffer::copyTo(const nn::Memory& dst) const {
+ const auto hidlDst = NN_TRY(V1_0::utils::convert(dst));
+
+ const auto ret = kBuffer->copyTo(hidlDst);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "IBuffer::copyTo failed with " << toString(status);
+ }
+
+ return {};
+}
+
+nn::GeneralResult<void> Buffer::copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const {
+ const auto hidlSrc = NN_TRY(V1_0::utils::convert(src));
+ const auto hidlDimensions = hidl_vec<uint32_t>(dimensions);
+
+ const auto ret = kBuffer->copyFrom(hidlSrc, hidlDimensions);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "IBuffer::copyFrom failed with " << toString(status);
+ }
+
+ return {};
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Callbacks.cpp b/neuralnetworks/1.3/utils/src/Callbacks.cpp
new file mode 100644
index 0000000..ff81275
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Callbacks.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Callbacks.h"
+
+#include "Conversions.h"
+#include "PreparedModel.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/PreparedModel.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/1.2/PreparedModel.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <utility>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+namespace {
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<V1_0::IPreparedModel>& preparedModel) {
+ return NN_TRY(V1_0::utils::PreparedModel::create(preparedModel));
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<V1_2::IPreparedModel>& preparedModel) {
+ return NN_TRY(V1_2::utils::PreparedModel::create(preparedModel));
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
+ const sp<IPreparedModel>& preparedModel) {
+ return NN_TRY(utils::PreparedModel::create(preparedModel));
+}
+
+nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionGeneralResultsHelper(const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ return std::make_pair(NN_TRY(validatedConvertToCanonical(outputShapes)),
+ NN_TRY(validatedConvertToCanonical(timing)));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionGeneralResults(const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ return hal::utils::makeExecutionFailure(
+ convertExecutionGeneralResultsHelper(outputShapes, timing));
+}
+
+} // namespace
+
+Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
+ const sp<V1_0::IPreparedModel>& preparedModel) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_2(V1_0::ErrorStatus status,
+ const sp<V1_2::IPreparedModel>& preparedModel) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_3(ErrorStatus status,
+ const sp<IPreparedModel>& preparedModel) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
+ } else if (preparedModel == nullptr) {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Returned preparedModel is nullptr");
+ } else {
+ notifyInternal(convertPreparedModel(preparedModel));
+ }
+ return Void();
+}
+
+void PreparedModelCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+PreparedModelCallback::Data PreparedModelCallback::get() {
+ return mData.take();
+}
+
+void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+// ExecutionCallback methods begin here
+
+Return<void> ExecutionCallback::notify(V1_0::ErrorStatus status) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal({});
+ }
+ return Void();
+}
+
+Return<void> ExecutionCallback::notify_1_2(V1_0::ErrorStatus status,
+ const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ if (status != V1_0::ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
+ }
+ return Void();
+}
+
+Return<void> ExecutionCallback::notify_1_3(ErrorStatus status,
+ const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
+ } else {
+ notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
+ }
+ return Void();
+}
+
+void ExecutionCallback::notifyAsDeadObject() {
+ notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+}
+
+ExecutionCallback::Data ExecutionCallback::get() {
+ return mData.take();
+}
+
+void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
+ mData.put(std::move(result));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
new file mode 100644
index 0000000..0dc0785
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Conversions.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/OperationTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+
+#include <algorithm>
+#include <chrono>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <type_traits>
+#include <utility>
+
+namespace {
+
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+ return static_cast<std::underlying_type_t<Type>>(value);
+}
+
+} // namespace
+
+namespace android::nn {
+namespace {
+
+constexpr auto validOperandType(nn::OperandType operandType) {
+ switch (operandType) {
+ case nn::OperandType::FLOAT32:
+ case nn::OperandType::INT32:
+ case nn::OperandType::UINT32:
+ case nn::OperandType::TENSOR_FLOAT32:
+ case nn::OperandType::TENSOR_INT32:
+ case nn::OperandType::TENSOR_QUANT8_ASYMM:
+ case nn::OperandType::BOOL:
+ case nn::OperandType::TENSOR_QUANT16_SYMM:
+ case nn::OperandType::TENSOR_FLOAT16:
+ case nn::OperandType::TENSOR_BOOL8:
+ case nn::OperandType::FLOAT16:
+ case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+ case nn::OperandType::TENSOR_QUANT16_ASYMM:
+ case nn::OperandType::TENSOR_QUANT8_SYMM:
+ case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
+ case nn::OperandType::SUBGRAPH:
+ case nn::OperandType::OEM:
+ case nn::OperandType::TENSOR_OEM_BYTE:
+ return true;
+ }
+ return nn::isExtension(operandType);
+}
+
+using hardware::hidl_vec;
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+GeneralResult<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
+ std::vector<ConvertOutput<Type>> canonical;
+ canonical.reserve(arguments.size());
+ for (const auto& argument : arguments) {
+ canonical.push_back(NN_TRY(nn::convert(argument)));
+ }
+ return canonical;
+}
+
+template <typename Type>
+GeneralResult<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
+ return convertVec(arguments);
+}
+
+} // anonymous namespace
+
+GeneralResult<OperandType> convert(const hal::V1_3::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+GeneralResult<OperationType> convert(const hal::V1_3::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+GeneralResult<Priority> convert(const hal::V1_3::Priority& priority) {
+ return static_cast<Priority>(priority);
+}
+
+GeneralResult<Capabilities> convert(const hal::V1_3::Capabilities& capabilities) {
+ const bool validOperandTypes = std::all_of(
+ capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
+ [](const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
+ const auto maybeType = convert(operandPerformance.type);
+ return !maybeType.has_value() ? false : validOperandType(maybeType.value());
+ });
+ if (!validOperandTypes) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid OperandType when converting OperandPerformance in Capabilities";
+ }
+
+ auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
+ auto table = NN_TRY(hal::utils::makeGeneralFailure(
+ Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
+ nn::ErrorStatus::GENERAL_FAILURE));
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+ .relaxedFloat32toFloat16PerformanceTensor =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+ .operandPerformance = std::move(table),
+ .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
+ .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
+ };
+}
+
+GeneralResult<Capabilities::OperandPerformance> convert(
+ const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
+ return Capabilities::OperandPerformance{
+ .type = NN_TRY(convert(operandPerformance.type)),
+ .info = NN_TRY(convert(operandPerformance.info)),
+ };
+}
+
+GeneralResult<Operation> convert(const hal::V1_3::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+GeneralResult<Operand::LifeTime> convert(const hal::V1_3::OperandLifeTime& operandLifeTime) {
+ return static_cast<Operand::LifeTime>(operandLifeTime);
+}
+
+GeneralResult<Operand> convert(const hal::V1_3::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ .extraParams = NN_TRY(convert(operand.extraParams)),
+ };
+}
+
+GeneralResult<Model> convert(const hal::V1_3::Model& model) {
+ return Model{
+ .main = NN_TRY(convert(model.main)),
+ .referenced = NN_TRY(convert(model.referenced)),
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+ };
+}
+
+GeneralResult<Model::Subgraph> convert(const hal::V1_3::Subgraph& subgraph) {
+ auto operations = NN_TRY(convert(subgraph.operations));
+
+ // Verify number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations);
+ CHECK(subgraph.operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < subgraph.operands.size(); ++i) {
+ if (subgraph.operands[i].numberOfConsumers != numberOfConsumers[i]) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid numberOfConsumers for operand " << i << ", expected "
+ << numberOfConsumers[i] << " but found "
+ << subgraph.operands[i].numberOfConsumers;
+ }
+ }
+
+ return Model::Subgraph{
+ .operands = NN_TRY(convert(subgraph.operands)),
+ .operations = std::move(operations),
+ .inputIndexes = subgraph.inputIndexes,
+ .outputIndexes = subgraph.outputIndexes,
+ };
+}
+
+GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc) {
+ return BufferDesc{.dimensions = bufferDesc.dimensions};
+}
+
+GeneralResult<BufferRole> convert(const hal::V1_3::BufferRole& bufferRole) {
+ return BufferRole{
+ .modelIndex = bufferRole.modelIndex,
+ .ioIndex = bufferRole.ioIndex,
+ .frequency = bufferRole.frequency,
+ };
+}
+
+GeneralResult<Request> convert(const hal::V1_3::Request& request) {
+ return Request{
+ .inputs = NN_TRY(convert(request.inputs)),
+ .outputs = NN_TRY(convert(request.outputs)),
+ .pools = NN_TRY(convert(request.pools)),
+ };
+}
+
+GeneralResult<Request::MemoryPool> convert(const hal::V1_3::Request::MemoryPool& memoryPool) {
+ using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
+ switch (memoryPool.getDiscriminator()) {
+ case Discriminator::hidlMemory:
+ return createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
+ case Discriminator::token:
+ return static_cast<Request::MemoryDomainToken>(memoryPool.token());
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid Request::MemoryPool discriminator "
+ << underlyingType(memoryPool.getDiscriminator());
+}
+
+GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
+ constexpr auto kTimePointMaxCount = TimePoint::max().time_since_epoch().count();
+ const auto makeTimePoint = [](uint64_t count) -> GeneralResult<OptionalTimePoint> {
+ if (count > kTimePointMaxCount) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Unable to convert OptionalTimePoint because the count exceeds the max";
+ }
+ const auto nanoseconds = std::chrono::nanoseconds{count};
+ return TimePoint{nanoseconds};
+ };
+
+ using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
+ switch (optionalTimePoint.getDiscriminator()) {
+ case Discriminator::none:
+ return std::nullopt;
+ case Discriminator::nanosecondsSinceEpoch:
+ return makeTimePoint(optionalTimePoint.nanosecondsSinceEpoch());
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid OptionalTimePoint discriminator "
+ << underlyingType(optionalTimePoint.getDiscriminator());
+}
+
+GeneralResult<OptionalTimeoutDuration> convert(
+ const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
+ constexpr auto kTimeoutDurationMaxCount = TimeoutDuration::max().count();
+ const auto makeTimeoutDuration = [](uint64_t count) -> GeneralResult<OptionalTimeoutDuration> {
+ if (count > kTimeoutDurationMaxCount) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Unable to convert OptionalTimeoutDuration because the count exceeds the max";
+ }
+ return TimeoutDuration{count};
+ };
+
+ using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
+ switch (optionalTimeoutDuration.getDiscriminator()) {
+ case Discriminator::none:
+ return std::nullopt;
+ case Discriminator::nanoseconds:
+ return makeTimeoutDuration(optionalTimeoutDuration.nanoseconds());
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid OptionalTimeoutDuration discriminator "
+ << underlyingType(optionalTimeoutDuration.getDiscriminator());
+}
+
+GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& status) {
+ switch (status) {
+ case hal::V1_3::ErrorStatus::NONE:
+ case hal::V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
+ case hal::V1_3::ErrorStatus::GENERAL_FAILURE:
+ case hal::V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ case hal::V1_3::ErrorStatus::INVALID_ARGUMENT:
+ case hal::V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+ case hal::V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+ case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+ case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+ return static_cast<ErrorStatus>(status);
+ }
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Invalid ErrorStatus " << underlyingType(status);
+}
+
+GeneralResult<std::vector<BufferRole>> convert(
+ const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
+ return convertVec(bufferRoles);
+}
+
+} // namespace android::nn
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+namespace {
+
+using utils::convert;
+
+nn::GeneralResult<V1_0::PerformanceInfo> convert(
+ const nn::Capabilities::PerformanceInfo& performanceInfo) {
+ return V1_0::utils::convert(performanceInfo);
+}
+
+nn::GeneralResult<V1_0::DataLocation> convert(const nn::DataLocation& dataLocation) {
+ return V1_0::utils::convert(dataLocation);
+}
+
+nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
+ return V1_0::utils::convert(operandValues);
+}
+
+nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
+ return V1_0::utils::convert(memory);
+}
+
+nn::GeneralResult<V1_0::RequestArgument> convert(const nn::Request::Argument& argument) {
+ return V1_0::utils::convert(argument);
+}
+
+nn::GeneralResult<V1_2::Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
+ return V1_2::utils::convert(extraParams);
+}
+
+nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> convert(
+ const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+ return V1_2::utils::convert(extensionNameAndPrefix);
+}
+
+template <typename Input>
+using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
+ hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ halObject[i] = NN_TRY(convert(arguments[i]));
+ }
+ return halObject;
+}
+
+template <typename Type>
+nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
+ return convertVec(arguments);
+}
+
+nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
+ Request::MemoryPool ret;
+ ret.hidlMemory(NN_TRY(convert(memory)));
+ return ret;
+}
+
+nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
+ Request::MemoryPool ret;
+ ret.token(underlyingType(token));
+ return ret;
+}
+
+nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedBuffer& /*buffer*/) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Unable to make memory pool from IBuffer";
+}
+
+} // anonymous namespace
+
+nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType) {
+ return static_cast<OperandType>(operandType);
+}
+
+nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
+ return static_cast<OperationType>(operationType);
+}
+
+nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
+ return static_cast<Priority>(priority);
+}
+
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+ std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
+ operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+ std::copy_if(capabilities.operandPerformance.asVector().begin(),
+ capabilities.operandPerformance.asVector().end(),
+ std::back_inserter(operandPerformance),
+ [](const nn::Capabilities::OperandPerformance& operandPerformance) {
+ return nn::validOperandType(operandPerformance.type);
+ });
+
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceScalar =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+ .relaxedFloat32toFloat16PerformanceTensor =
+ NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+ .operandPerformance = NN_TRY(convert(operandPerformance)),
+ .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
+ .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
+ };
+}
+
+nn::GeneralResult<Capabilities::OperandPerformance> convert(
+ const nn::Capabilities::OperandPerformance& operandPerformance) {
+ return Capabilities::OperandPerformance{
+ .type = NN_TRY(convert(operandPerformance.type)),
+ .info = NN_TRY(convert(operandPerformance.info)),
+ };
+}
+
+nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
+ return Operation{
+ .type = NN_TRY(convert(operation.type)),
+ .inputs = operation.inputs,
+ .outputs = operation.outputs,
+ };
+}
+
+nn::GeneralResult<OperandLifeTime> convert(const nn::Operand::LifeTime& operandLifeTime) {
+ if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Model cannot be converted because it contains pointer-based memory";
+ }
+ return static_cast<OperandLifeTime>(operandLifeTime);
+}
+
+nn::GeneralResult<Operand> convert(const nn::Operand& operand) {
+ return Operand{
+ .type = NN_TRY(convert(operand.type)),
+ .dimensions = operand.dimensions,
+ .numberOfConsumers = 0,
+ .scale = operand.scale,
+ .zeroPoint = operand.zeroPoint,
+ .lifetime = NN_TRY(convert(operand.lifetime)),
+ .location = NN_TRY(convert(operand.location)),
+ .extraParams = NN_TRY(convert(operand.extraParams)),
+ };
+}
+
+nn::GeneralResult<Model> convert(const nn::Model& model) {
+ if (!hal::utils::hasNoPointerData(model)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Model cannot be converted because it contains pointer-based memory";
+ }
+
+ return Model{
+ .main = NN_TRY(convert(model.main)),
+ .referenced = NN_TRY(convert(model.referenced)),
+ .operandValues = NN_TRY(convert(model.operandValues)),
+ .pools = NN_TRY(convert(model.pools)),
+ .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
+ .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
+ };
+}
+
+nn::GeneralResult<Subgraph> convert(const nn::Model::Subgraph& subgraph) {
+ auto operands = NN_TRY(convert(subgraph.operands));
+
+ // Update number of consumers.
+ const auto numberOfConsumers =
+ hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations);
+ CHECK(operands.size() == numberOfConsumers.size());
+ for (size_t i = 0; i < operands.size(); ++i) {
+ operands[i].numberOfConsumers = numberOfConsumers[i];
+ }
+
+ return Subgraph{
+ .operands = std::move(operands),
+ .operations = NN_TRY(convert(subgraph.operations)),
+ .inputIndexes = subgraph.inputIndexes,
+ .outputIndexes = subgraph.outputIndexes,
+ };
+}
+
+nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
+ return BufferDesc{.dimensions = bufferDesc.dimensions};
+}
+
+nn::GeneralResult<BufferRole> convert(const nn::BufferRole& bufferRole) {
+ return BufferRole{
+ .modelIndex = bufferRole.modelIndex,
+ .ioIndex = bufferRole.ioIndex,
+ .frequency = bufferRole.frequency,
+ };
+}
+
+nn::GeneralResult<Request> convert(const nn::Request& request) {
+ if (!hal::utils::hasNoPointerData(request)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Request cannot be converted because it contains pointer-based memory";
+ }
+
+ return Request{
+ .inputs = NN_TRY(convert(request.inputs)),
+ .outputs = NN_TRY(convert(request.outputs)),
+ .pools = NN_TRY(convert(request.pools)),
+ };
+}
+
+nn::GeneralResult<Request::MemoryPool> convert(const nn::Request::MemoryPool& memoryPool) {
+ return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
+}
+
+nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
+ OptionalTimePoint ret;
+ if (optionalTimePoint.has_value()) {
+ const auto count = optionalTimePoint.value().time_since_epoch().count();
+ if (count < 0) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Unable to convert OptionalTimePoint because time since epoch count is "
+ "negative";
+ }
+ ret.nanosecondsSinceEpoch(count);
+ }
+ return ret;
+}
+
+nn::GeneralResult<OptionalTimeoutDuration> convert(
+ const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
+ OptionalTimeoutDuration ret;
+ if (optionalTimeoutDuration.has_value()) {
+ const auto count = optionalTimeoutDuration.value().count();
+ if (count < 0) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Unable to convert OptionalTimeoutDuration because count is negative";
+ }
+ ret.nanoseconds(count);
+ }
+ return ret;
+}
+
+nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
+ switch (errorStatus) {
+ case nn::ErrorStatus::NONE:
+ case nn::ErrorStatus::DEVICE_UNAVAILABLE:
+ case nn::ErrorStatus::GENERAL_FAILURE:
+ case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ case nn::ErrorStatus::INVALID_ARGUMENT:
+ case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+ case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+ case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+ case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+ return static_cast<ErrorStatus>(errorStatus);
+ default:
+ return ErrorStatus::GENERAL_FAILURE;
+ }
+}
+
+nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
+ return convertVec(bufferRoles);
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
new file mode 100644
index 0000000..5e3d5c2
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Device.h"
+
+#include "Buffer.h"
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "PreparedModel.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/OperandTypes.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/1.2/Device.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <any>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+namespace {
+
+nn::GeneralResult<hidl_vec<sp<IPreparedModel>>> convert(
+ const std::vector<nn::SharedPreparedModel>& preparedModels) {
+ hidl_vec<sp<IPreparedModel>> hidlPreparedModels(preparedModels.size());
+ for (size_t i = 0; i < preparedModels.size(); ++i) {
+ std::any underlyingResource = preparedModels[i]->getUnderlyingResource();
+ if (const auto* hidlPreparedModel =
+ std::any_cast<sp<IPreparedModel>>(&underlyingResource)) {
+ hidlPreparedModels[i] = *hidlPreparedModel;
+ } else {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Unable to convert from nn::IPreparedModel to V1_3::IPreparedModel";
+ }
+ }
+ return hidlPreparedModels;
+}
+
+nn::GeneralResult<nn::SharedBuffer> convert(
+ nn::GeneralResult<std::shared_ptr<const Buffer>> result) {
+ return NN_TRY(std::move(result));
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
+ sp<V1_3::IDevice> device) {
+ if (name.empty()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_3::utils::Device::create must have non-empty name";
+ }
+ if (device == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_3::utils::Device::create must have non-null device";
+ }
+
+ auto versionString = NN_TRY(V1_2::utils::initVersionString(device.get()));
+ const auto deviceType = NN_TRY(V1_2::utils::initDeviceType(device.get()));
+ auto extensions = NN_TRY(V1_2::utils::initExtensions(device.get()));
+ auto capabilities = NN_TRY(V1_2::utils::initCapabilities(device.get()));
+ const auto numberOfCacheFilesNeeded =
+ NN_TRY(V1_2::utils::initNumberOfCacheFilesNeeded(device.get()));
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
+ return std::make_shared<const Device>(
+ PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
+ std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
+ std::move(device), std::move(deathHandler));
+}
+
+Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded, sp<V1_3::IDevice> device,
+ hal::utils::DeathHandler deathHandler)
+ : kName(std::move(name)),
+ kVersionString(std::move(versionString)),
+ kDeviceType(deviceType),
+ kExtensions(std::move(extensions)),
+ kCapabilities(std::move(capabilities)),
+ kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded),
+ kDevice(std::move(device)),
+ kDeathHandler(std::move(deathHandler)) {}
+
+const std::string& Device::getName() const {
+ return kName;
+}
+
+const std::string& Device::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version Device::getFeatureLevel() const {
+ return nn::Version::ANDROID_R;
+}
+
+nn::DeviceType Device::getType() const {
+ return kDeviceType;
+}
+
+const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& Device::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> Device::getNumberOfCacheFilesNeeded() const {
+ return kNumberOfCacheFilesNeeded;
+}
+
+nn::GeneralResult<void> Device::wait() const {
+ const auto ret = kDevice->ping();
+ return hal::utils::handleTransportError(ret);
+}
+
+nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Model& model) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+
+ nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ auto cb = [&result, &model](ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical)
+ << "IDevice::getSupportedOperations_1_3 failed with " << toString(status);
+ } else if (supportedOperations.size() != model.main.operations.size()) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "IDevice::getSupportedOperations_1_3 returned vector of size "
+ << supportedOperations.size() << " but expected "
+ << model.main.operations.size();
+ } else {
+ result = supportedOperations;
+ }
+ };
+
+ const auto ret = kDevice->getSupportedOperations_1_3(hidlModel, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ // Ensure that model is ready for IPC.
+ std::optional<nn::Model> maybeModelInShared;
+ const nn::Model& modelInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
+
+ const auto hidlModel = NN_TRY(convert(modelInShared));
+ const auto hidlPreference = NN_TRY(V1_1::utils::convert(preference));
+ const auto hidlPriority = NN_TRY(convert(priority));
+ const auto hidlDeadline = NN_TRY(convert(deadline));
+ const auto hidlModelCache = NN_TRY(V1_2::utils::convert(modelCache));
+ const auto hidlDataCache = NN_TRY(V1_2::utils::convert(dataCache));
+ const auto hidlToken = token;
+
+ const auto cb = sp<PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret =
+ kDevice->prepareModel_1_3(hidlModel, hidlPreference, hidlPriority, hidlDeadline,
+ hidlModelCache, hidlDataCache, hidlToken, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModel_1_3 failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ const auto hidlDeadline = NN_TRY(convert(deadline));
+ const auto hidlModelCache = NN_TRY(V1_2::utils::convert(modelCache));
+ const auto hidlDataCache = NN_TRY(V1_2::utils::convert(dataCache));
+ const auto hidlToken = token;
+
+ const auto cb = sp<PreparedModelCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret = kDevice->prepareModelFromCache_1_3(hidlDeadline, hidlModelCache, hidlDataCache,
+ hidlToken, cb);
+ const auto status = NN_TRY(hal::utils::handleTransportError(ret));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "prepareModelFromCache_1_3 failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::GeneralResult<nn::SharedBuffer> Device::allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const {
+ const auto hidlDesc = NN_TRY(convert(desc));
+ const auto hidlPreparedModels = NN_TRY(convert(preparedModels));
+ const auto hidlInputRoles = NN_TRY(convert(inputRoles));
+ const auto hidlOutputRoles = NN_TRY(convert(outputRoles));
+
+ nn::GeneralResult<nn::SharedBuffer> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "uninitialized";
+ auto cb = [&result](ErrorStatus status, const sp<IBuffer>& buffer, uint32_t token) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "IDevice::allocate failed with " << toString(status);
+ } else if (buffer == nullptr) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Returned buffer is nullptr";
+ } else if (token == 0) {
+ result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Returned token is invalid (0)";
+ } else {
+ result = convert(
+ Buffer::create(buffer, static_cast<nn::Request::MemoryDomainToken>(token)));
+ }
+ };
+
+ const auto ret =
+ kDevice->allocate(hidlDesc, hidlPreparedModels, hidlInputRoles, hidlOutputRoles, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
new file mode 100644
index 0000000..2781053
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PreparedModel.h"
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/ProtectCallback.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+namespace {
+
+nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+convertExecutionResultsHelper(const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ return std::make_pair(NN_TRY(validatedConvertToCanonical(outputShapes)),
+ NN_TRY(validatedConvertToCanonical(timing)));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> convertExecutionResults(
+ const hidl_vec<V1_2::OutputShape>& outputShapes, const V1_2::Timing& timing) {
+ return hal::utils::makeExecutionFailure(convertExecutionResultsHelper(outputShapes, timing));
+}
+
+nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> convertFencedExecutionCallbackResults(
+ const V1_2::Timing& timingLaunched, const V1_2::Timing& timingFenced) {
+ return std::make_pair(NN_TRY(validatedConvertToCanonical(timingLaunched)),
+ NN_TRY(validatedConvertToCanonical(timingFenced)));
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+convertExecuteFencedResults(const hidl_handle& syncFence,
+ const sp<IFencedExecutionCallback>& callback) {
+ auto resultSyncFence = nn::SyncFence::createAsSignaled();
+ if (syncFence.getNativeHandle() != nullptr) {
+ auto nativeHandle = NN_TRY(validatedConvertToCanonical(syncFence));
+ resultSyncFence = NN_TRY(hal::utils::makeGeneralFailure(
+ nn::SyncFence::create(std::move(nativeHandle)), nn::ErrorStatus::GENERAL_FAILURE));
+ }
+
+ if (callback == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "callback is null";
+ }
+
+ // Create callback which can be used to retrieve the execution error status and timings.
+ nn::ExecuteFencedInfoCallback resultCallback =
+ [callback]() -> nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> {
+ nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ auto cb = [&result](ErrorStatus status, const V1_2::Timing& timingLaunched,
+ const V1_2::Timing& timingFenced) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical = validatedConvertToCanonical(status).value_or(
+ nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "getExecutionInfo failed with " << toString(status);
+ } else {
+ result = convertFencedExecutionCallbackResults(timingLaunched, timingFenced);
+ }
+ };
+
+ const auto ret = callback->getExecutionInfo(cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+
+ return result;
+ };
+
+ return std::make_pair(std::move(resultSyncFence), std::move(resultCallback));
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
+ sp<V1_3::IPreparedModel> preparedModel) {
+ if (preparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "V1_3::utils::PreparedModel::create must have non-null preparedModel";
+ }
+
+ auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
+ std::move(deathHandler));
+}
+
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, sp<V1_3::IPreparedModel> preparedModel,
+ hal::utils::DeathHandler deathHandler)
+ : kPreparedModel(std::move(preparedModel)), kDeathHandler(std::move(deathHandler)) {}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeSynchronously(const Request& request, V1_2::MeasureTiming measure,
+ const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration) const {
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const auto cb = [&result](ErrorStatus status, const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "executeSynchronously failed with " << toString(status);
+ } else {
+ result = convertExecutionResults(outputShapes, timing);
+ }
+ };
+
+ const auto ret = kPreparedModel->executeSynchronously_1_3(request, measure, deadline,
+ loopTimeoutDuration, cb);
+ NN_TRY(hal::utils::makeExecutionFailure(hal::utils::handleTransportError(ret)));
+
+ return result;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeAsynchronously(const Request& request, V1_2::MeasureTiming measure,
+ const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration) const {
+ const auto cb = sp<ExecutionCallback>::make();
+ const auto scoped = kDeathHandler.protectCallback(cb.get());
+
+ const auto ret =
+ kPreparedModel->execute_1_3(request, measure, deadline, loopTimeoutDuration, cb);
+ const auto status =
+ NN_TRY(hal::utils::makeExecutionFailure(hal::utils::handleTransportError(ret)));
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ return NN_ERROR(canonical) << "executeAsynchronously failed with " << toString(status);
+ }
+
+ return cb->get();
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared)));
+
+ const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
+ const auto hidlMeasure =
+ NN_TRY(hal::utils::makeExecutionFailure(V1_2::utils::convert(measure)));
+ const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+ const auto hidlLoopTimeoutDuration =
+ NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ const bool preferSynchronous = true;
+
+ // Execute synchronously if allowed.
+ if (preferSynchronous) {
+ result = executeSynchronously(hidlRequest, hidlMeasure, hidlDeadline,
+ hidlLoopTimeoutDuration);
+ }
+
+ // Run asymchronous execution if execution has not already completed.
+ if (!result.has_value()) {
+ result = executeAsynchronously(hidlRequest, hidlMeasure, hidlDeadline,
+ hidlLoopTimeoutDuration);
+ }
+
+ // Flush output buffers if suxcessful execution.
+ if (result.has_value()) {
+ NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
+ }
+
+ return result;
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFenced(const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ const nn::Request& requestInShared =
+ NN_TRY(hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared));
+
+ const auto hidlRequest = NN_TRY(convert(requestInShared));
+ const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
+ const auto hidlMeasure = NN_TRY(V1_2::utils::convert(measure));
+ const auto hidlDeadline = NN_TRY(convert(deadline));
+ const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
+ const auto hidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> result =
+ NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
+ auto cb = [&result](ErrorStatus status, const hidl_handle& syncFence,
+ const sp<IFencedExecutionCallback>& callback) {
+ if (status != ErrorStatus::NONE) {
+ const auto canonical =
+ validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+ result = NN_ERROR(canonical) << "executeFenced failed with " << toString(status);
+ } else {
+ result = convertExecuteFencedResults(syncFence, callback);
+ }
+ };
+
+ const auto ret = kPreparedModel->executeFenced(hidlRequest, hidlWaitFor, hidlMeasure,
+ hidlDeadline, hidlLoopTimeoutDuration,
+ hidlTimeoutDurationAfterFence, cb);
+ NN_TRY(hal::utils::handleTransportError(ret));
+ auto [syncFence, callback] = NN_TRY(std::move(result));
+
+ // If executeFenced required the request memory to be moved into shared memory, block here until
+ // the fenced execution has completed and flush the memory back.
+ if (maybeRequestInShared.has_value()) {
+ const auto state = syncFence.syncWait({});
+ if (state != nn::SyncFence::FenceState::SIGNALED) {
+ return NN_ERROR() << "syncWait failed with " << state;
+ }
+ NN_TRY(hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared));
+ }
+
+ return std::make_pair(std::move(syncFence), std::move(callback));
+}
+
+std::any PreparedModel::getUnderlyingResource() const {
+ sp<V1_3::IPreparedModel> resource = kPreparedModel;
+ return resource;
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Service.cpp b/neuralnetworks/1.3/utils/src/Service.cpp
new file mode 100644
index 0000000..62887fb
--- /dev/null
+++ b/neuralnetworks/1.3/utils/src/Service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Service.h"
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/ResilientDevice.h>
+#include <string>
+#include "Device.h"
+
+namespace android::hardware::neuralnetworks::V1_3::utils {
+
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+ hal::utils::ResilientDevice::Factory makeDevice =
+ [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ auto service = blocking ? IDevice::getService(name) : IDevice::tryGetService(name);
+ if (service == nullptr) {
+ return NN_ERROR() << (blocking ? "getService" : "tryGetService") << " returned nullptr";
+ }
+ return Device::create(name, std::move(service));
+ };
+
+ return hal::utils::ResilientDevice::create(std::move(makeDevice));
+}
+
+} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/vts/functional/AndroidTest.xml b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
index e5acd90..c418aaa 100644
--- a/neuralnetworks/1.3/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
@@ -28,5 +28,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_3TargetTest" />
+ <option name="native-test-timeout" value="20m" />
</test>
</configuration>
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index ac18c8f..edffa22 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -1200,9 +1200,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type);
}
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest,
- testing::Combine(kNamedDeviceChoices, kOperandTypeChoices),
- printCompilationCachingTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CompilationCachingTest);
+INSTANTIATE_TEST_SUITE_P(TestCompilationCaching, CompilationCachingTest,
+ testing::Combine(kNamedDeviceChoices, kOperandTypeChoices),
+ printCompilationCachingTest);
using CompilationCachingSecurityTestParam = std::tuple<NamedDevice, OperandType, uint32_t>;
@@ -1356,9 +1357,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type + "_" + std::to_string(seed));
}
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
- testing::Combine(kNamedDeviceChoices, kOperandTypeChoices,
- testing::Range(0U, 10U)),
- printCompilationCachingSecurityTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CompilationCachingSecurityTest);
+INSTANTIATE_TEST_SUITE_P(TestCompilationCaching, CompilationCachingSecurityTest,
+ testing::Combine(kNamedDeviceChoices, kOperandTypeChoices,
+ testing::Range(0U, 10U)),
+ printCompilationCachingSecurityTest);
} // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 914a01a..0a95695 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -644,7 +644,7 @@
int n;
std::tie(n, outputShapes, timing, std::ignore) =
controller->compute(request10, testConfig.measureTiming, keys);
- executionStatus = nn::convertResultCodeToErrorStatus(n);
+ executionStatus = nn::convertToV1_3(nn::convertResultCodeToErrorStatus(n));
break;
}
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
index 4f05c48..834b108 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
@@ -47,6 +47,7 @@
std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite, \
testing::Combine(testing::ValuesIn(getNamedDevices()), \
testing::ValuesIn(getNamedModels(filter))), \
diff --git a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
index 3c0c885..5facc5e 100644
--- a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -605,9 +605,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type);
}
-INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainAllocateTest,
- testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
- printMemoryDomainAllocateTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryDomainAllocateTest);
+INSTANTIATE_TEST_SUITE_P(TestMemoryDomain, MemoryDomainAllocateTest,
+ testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
+ printMemoryDomainAllocateTest);
class MemoryDomainCopyTestBase : public MemoryDomainTestBase {
protected:
@@ -829,9 +830,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type);
}
-INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainCopyTest,
- testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
- printMemoryDomainCopyTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryDomainCopyTest);
+INSTANTIATE_TEST_SUITE_P(TestMemoryDomain, MemoryDomainCopyTest,
+ testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
+ printMemoryDomainCopyTest);
using MemoryDomainExecutionTestParam = std::tuple<NamedDevice, TestOperandType, Executor>;
class MemoryDomainExecutionTest
@@ -1195,9 +1197,10 @@
return gtestCompliantName(getName(namedDevice) + "_" + type + "_" + executorStr);
}
-INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainExecutionTest,
- testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices,
- kExecutorChoices),
- printMemoryDomainExecutionTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryDomainExecutionTest);
+INSTANTIATE_TEST_SUITE_P(TestMemoryDomain, MemoryDomainExecutionTest,
+ testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices,
+ kExecutorChoices),
+ printMemoryDomainExecutionTest);
} // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/TestAssertions.cpp b/neuralnetworks/1.3/vts/functional/TestAssertions.cpp
index a7569e6..1a40721 100644
--- a/neuralnetworks/1.3/vts/functional/TestAssertions.cpp
+++ b/neuralnetworks/1.3/vts/functional/TestAssertions.cpp
@@ -15,10 +15,16 @@
*/
#include <android/hardware/neuralnetworks/1.3/types.h>
+#include "ControlFlow.h"
#include "TestHarness.h"
namespace android::hardware::neuralnetworks::V1_3 {
+static_assert(static_cast<uint64_t>(LoopTimeoutDurationNs::DEFAULT) ==
+ nn::operation_while::kTimeoutNsDefault);
+static_assert(static_cast<uint64_t>(LoopTimeoutDurationNs::MAXIMUM) ==
+ nn::operation_while::kTimeoutNsMaximum);
+
// Make sure that the HIDL enums are compatible with the values defined in
// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
using namespace test_helper;
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 1ae8b3f..3b441fb 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -116,7 +116,7 @@
// execute and verify
const auto [n, outputShapes, timing, fallback] = burst->compute(request10, measure, keys);
- const ErrorStatus status = nn::convertResultCodeToErrorStatus(n);
+ const ErrorStatus status = nn::convertToV1_3(nn::convertResultCodeToErrorStatus(n));
EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
EXPECT_EQ(outputShapes.size(), 0);
EXPECT_TRUE(badTiming(timing));
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
index a2e5071..7afb05f 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
@@ -42,6 +42,7 @@
const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
#define INSTANTIATE_DEVICE_TEST(TestSuite) \
+ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestSuite); \
INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
printNeuralnetworksHidlTest)
diff --git a/neuralnetworks/utils/OWNERS b/neuralnetworks/utils/OWNERS
new file mode 100644
index 0000000..e4feee3
--- /dev/null
+++ b/neuralnetworks/utils/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+galarragas@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+pszczepaniak@google.com
+slavash@google.com
+vddang@google.com
+xusongw@google.com
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
new file mode 100644
index 0000000..21562cf
--- /dev/null
+++ b/neuralnetworks/utils/common/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_common",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal"],
+ export_include_dirs: ["include"],
+ cflags: ["-Wthread-safety"],
+ static_libs: [
+ "neuralnetworks_types",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ ],
+}
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
new file mode 100644
index 0000000..43bb0c6
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
+
+#include <cutils/native_handle.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <functional>
+#include <vector>
+
+// Shorthand
+namespace android::hardware::neuralnetworks {
+namespace hal = ::android::hardware::neuralnetworks;
+} // namespace android::hardware::neuralnetworks
+
+// Shorthand
+namespace android::nn {
+namespace hal = ::android::hardware::neuralnetworks;
+}
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
+ const nn::Capabilities::PerformanceInfo& float32Performance,
+ const nn::Capabilities::PerformanceInfo& quantized8Performance);
+
+// Indicates if the object contains no pointer-based data that could be relocated to shared memory.
+bool hasNoPointerData(const nn::Model& model);
+bool hasNoPointerData(const nn::Request& request);
+
+// Relocate pointer-based data to shared memory.
+nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
+ const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut);
+nn::GeneralResult<std::reference_wrapper<const nn::Request>> flushDataFromPointerToShared(
+ const nn::Request* request, std::optional<nn::Request>* maybeRequestInSharedOut);
+
+// Undoes `flushDataFromPointerToShared` on a Request object. More specifically,
+// `unflushDataFromSharedToPointer` copies the output shared memory data from the transformed
+// Request object back to the output pointer-based memory in the original Request object.
+nn::GeneralResult<void> unflushDataFromSharedToPointer(
+ const nn::Request& request, const std::optional<nn::Request>& maybeRequestInShared);
+
+std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
+ const std::vector<nn::Operation>& operations);
+
+nn::GeneralResult<nn::Memory> createSharedMemoryFromHidlMemory(const hidl_memory& memory);
+
+nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::SharedHandle& handle);
+nn::GeneralResult<nn::SharedHandle> sharedHandleFromNativeHandle(const native_handle_t* handle);
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+ const std::vector<nn::SyncFence>& fences);
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
new file mode 100644
index 0000000..e4046b5
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+namespace android::hardware::neuralnetworks::utils {
+
+template <typename Type>
+nn::GeneralResult<Type> handleTransportError(const hardware::Return<Type>& ret) {
+ if (ret.isDeadObject()) {
+ return NN_ERROR(nn::ErrorStatus::DEAD_OBJECT)
+ << "Return<>::isDeadObject returned true: " << ret.description();
+ }
+ if (!ret.isOk()) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Return<>::isOk returned false: " << ret.description();
+ }
+ return ret;
+}
+
+template <>
+inline nn::GeneralResult<void> handleTransportError(const hardware::Return<void>& ret) {
+ if (ret.isDeadObject()) {
+ return NN_ERROR(nn::ErrorStatus::DEAD_OBJECT)
+ << "Return<>::isDeadObject returned true: " << ret.description();
+ }
+ if (!ret.isOk()) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Return<>::isOk returned false: " << ret.description();
+ }
+ return {};
+}
+
+template <typename Type>
+nn::GeneralResult<Type> makeGeneralFailure(nn::Result<Type> result, nn::ErrorStatus status) {
+ if (!result.has_value()) {
+ return nn::error(status) << std::move(result).error();
+ }
+ return std::move(result).value();
+}
+
+template <>
+inline nn::GeneralResult<void> makeGeneralFailure(nn::Result<void> result, nn::ErrorStatus status) {
+ if (!result.has_value()) {
+ return nn::error(status) << std::move(result).error();
+ }
+ return {};
+}
+
+template <typename Type>
+nn::ExecutionResult<Type> makeExecutionFailure(nn::Result<Type> result, nn::ErrorStatus status) {
+ if (!result.has_value()) {
+ return nn::error(status) << std::move(result).error();
+ }
+ return std::move(result).value();
+}
+
+template <>
+inline nn::ExecutionResult<void> makeExecutionFailure(nn::Result<void> result,
+ nn::ErrorStatus status) {
+ if (!result.has_value()) {
+ return nn::error(status) << std::move(result).error();
+ }
+ return {};
+}
+
+template <typename Type>
+nn::ExecutionResult<Type> makeExecutionFailure(nn::GeneralResult<Type> result) {
+ if (!result.has_value()) {
+ const auto [message, status] = std::move(result).error();
+ return nn::error(status) << message;
+ }
+ return std::move(result).value();
+}
+
+template <>
+inline nn::ExecutionResult<void> makeExecutionFailure(nn::GeneralResult<void> result) {
+ if (!result.has_value()) {
+ const auto [message, status] = std::move(result).error();
+ return nn::error(status) << message;
+ }
+ return {};
+}
+
+} // namespace android::hardware::neuralnetworks::utils
\ No newline at end of file
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
new file mode 100644
index 0000000..8c04b88
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBuffer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidBuffer final : public nn::IBuffer {
+ public:
+ nn::Request::MemoryDomainToken getToken() const override;
+
+ nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
+
+ nn::GeneralResult<void> copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const override;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_BUFFER_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
new file mode 100644
index 0000000..5e62b9a
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidDevice final : public nn::IDevice {
+ public:
+ InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ const std::string kName;
+ const std::string kVersionString;
+ const nn::Version kFeatureLevel;
+ const nn::DeviceType kType;
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ const std::pair<uint32_t, uint32_t> kNumberOfCacheFilesNeeded;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_DEVICE_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
new file mode 100644
index 0000000..4b32b4e
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class InvalidPreparedModel final : public nn::IPreparedModel {
+ public:
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_INVALID_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h b/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
new file mode 100644
index 0000000..85bd613
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
+
+#include <android-base/scopeguard.h>
+#include <android-base/thread_annotations.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <mutex>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class IProtectedCallback {
+ public:
+ /**
+ * Marks this object as a dead object.
+ */
+ virtual void notifyAsDeadObject() = 0;
+
+ // Public virtual destructor to allow objects to be stored (and destroyed) as smart pointers.
+ // E.g., std::unique_ptr<IProtectedCallback>.
+ virtual ~IProtectedCallback() = default;
+
+ protected:
+ // Protect the non-destructor special member functions to prevent object slicing.
+ IProtectedCallback() = default;
+ IProtectedCallback(const IProtectedCallback&) = default;
+ IProtectedCallback(IProtectedCallback&&) noexcept = default;
+ IProtectedCallback& operator=(const IProtectedCallback&) = default;
+ IProtectedCallback& operator=(IProtectedCallback&&) noexcept = default;
+};
+
+// Thread safe class
+class DeathRecipient final : public hidl_death_recipient {
+ public:
+ void serviceDied(uint64_t /*cookie*/, const wp<hidl::base::V1_0::IBase>& /*who*/) override;
+ // Precondition: `killable` must be non-null.
+ void add(IProtectedCallback* killable) const;
+ // Precondition: `killable` must be non-null.
+ void remove(IProtectedCallback* killable) const;
+
+ private:
+ mutable std::mutex mMutex;
+ mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
+};
+
+class DeathHandler final {
+ public:
+ static nn::GeneralResult<DeathHandler> create(sp<hidl::base::V1_0::IBase> object);
+
+ DeathHandler(const DeathHandler&) = delete;
+ DeathHandler(DeathHandler&&) noexcept = default;
+ DeathHandler& operator=(const DeathHandler&) = delete;
+ DeathHandler& operator=(DeathHandler&&) noexcept = delete;
+ ~DeathHandler();
+
+ using Cleanup = std::function<void()>;
+ // Precondition: `killable` must be non-null.
+ [[nodiscard]] base::ScopeGuard<Cleanup> protectCallback(IProtectedCallback* killable) const;
+
+ private:
+ DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient);
+
+ sp<hidl::base::V1_0::IBase> kObject;
+ sp<DeathRecipient> kDeathRecipient;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h
new file mode 100644
index 0000000..996ec1e
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BUFFER_H
+
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class ResilientBuffer final : public nn::IBuffer {
+ struct PrivateConstructorTag {};
+
+ public:
+ using Factory = std::function<nn::GeneralResult<nn::SharedBuffer>(bool blocking)>;
+
+ static nn::GeneralResult<std::shared_ptr<const ResilientBuffer>> create(Factory makeBuffer);
+
+ explicit ResilientBuffer(PrivateConstructorTag tag, Factory makeBuffer,
+ nn::SharedBuffer buffer);
+
+ nn::SharedBuffer getBuffer() const;
+ nn::SharedBuffer recover(const nn::IBuffer* failingBuffer, bool blocking) const;
+
+ nn::Request::MemoryDomainToken getToken() const override;
+
+ nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
+
+ nn::GeneralResult<void> copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const override;
+
+ private:
+ const Factory kMakeBuffer;
+ mutable std::mutex mMutex;
+ mutable nn::SharedBuffer mBuffer GUARDED_BY(mMutex);
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_BUFFER_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
new file mode 100644
index 0000000..4bfed6c
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_DEVICE_H
+
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class ResilientDevice final : public nn::IDevice,
+ public std::enable_shared_from_this<ResilientDevice> {
+ struct PrivateConstructorTag {};
+
+ public:
+ using Factory = std::function<nn::GeneralResult<nn::SharedDevice>(bool blocking)>;
+
+ static nn::GeneralResult<std::shared_ptr<const ResilientDevice>> create(Factory makeDevice);
+
+ explicit ResilientDevice(PrivateConstructorTag tag, Factory makeDevice, std::string name,
+ std::string versionString, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities, nn::SharedDevice device);
+
+ nn::SharedDevice getDevice() const EXCLUDES(mMutex);
+ nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const
+ EXCLUDES(mMutex);
+
+ const std::string& getName() const override;
+ const std::string& getVersionString() const override;
+ nn::Version getFeatureLevel() const override;
+ nn::DeviceType getType() const override;
+ const std::vector<nn::Extension>& getSupportedExtensions() const override;
+ const nn::Capabilities& getCapabilities() const override;
+ std::pair<uint32_t, uint32_t> getNumberOfCacheFilesNeeded() const override;
+
+ nn::GeneralResult<void> wait() const override;
+
+ nn::GeneralResult<std::vector<bool>> getSupportedOperations(
+ const nn::Model& model) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache,
+ const nn::CacheToken& token) const override;
+
+ nn::GeneralResult<nn::SharedBuffer> allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const override;
+
+ private:
+ bool isValidInternal() const EXCLUDES(mMutex);
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
+ bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
+ nn::Priority priority, nn::OptionalTimePoint deadline,
+ const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
+ nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCacheInternal(
+ bool blocking, nn::OptionalTimePoint deadline,
+ const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
+ nn::GeneralResult<nn::SharedBuffer> allocateInternal(
+ bool blocking, const nn::BufferDesc& desc,
+ const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const;
+
+ const Factory kMakeDevice;
+ const std::string kName;
+ const std::string kVersionString;
+ const std::vector<nn::Extension> kExtensions;
+ const nn::Capabilities kCapabilities;
+ mutable std::mutex mMutex;
+ mutable nn::SharedDevice mDevice GUARDED_BY(mMutex);
+ mutable bool mIsValid GUARDED_BY(mMutex) = true;
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_DEVICE_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
new file mode 100644
index 0000000..c2940d1
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_PREPARED_MODEL_H
+
+#include <android-base/thread_annotations.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+class ResilientPreparedModel final : public nn::IPreparedModel {
+ struct PrivateConstructorTag {};
+
+ public:
+ using Factory = std::function<nn::GeneralResult<nn::SharedPreparedModel>(bool blocking)>;
+
+ static nn::GeneralResult<std::shared_ptr<const ResilientPreparedModel>> create(
+ Factory makePreparedModel);
+
+ explicit ResilientPreparedModel(PrivateConstructorTag tag, Factory makePreparedModel,
+ nn::SharedPreparedModel preparedModel);
+
+ nn::SharedPreparedModel getPreparedModel() const;
+ nn::SharedPreparedModel recover(const nn::IPreparedModel* failingPreparedModel,
+ bool blocking) const;
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+
+ std::any getUnderlyingResource() const override;
+
+ private:
+ const Factory kMakePreparedModel;
+ mutable std::mutex mMutex;
+ mutable nn::SharedPreparedModel mPreparedModel GUARDED_BY(mMutex);
+};
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_RESILIENT_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h b/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h
new file mode 100644
index 0000000..7103c6b
--- /dev/null
+++ b/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_TRANSFER_VALUE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_TRANSFER_VALUE_H
+
+#include <android-base/thread_annotations.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <optional>
+
+namespace android::hardware::neuralnetworks::utils {
+
+// This class is thread safe.
+template <typename Type>
+class TransferValue final {
+ public:
+ void put(Type object) const;
+ [[nodiscard]] Type take() const;
+
+ private:
+ mutable std::mutex mMutex;
+ mutable std::condition_variable mCondition;
+ mutable std::optional<Type> mObject GUARDED_BY(mMutex);
+};
+
+// template implementation
+
+template <typename Type>
+void TransferValue<Type>::put(Type object) const {
+ {
+ std::lock_guard guard(mMutex);
+ // Immediately return if value already exists.
+ if (mObject.has_value()) return;
+ mObject.emplace(std::move(object));
+ }
+ mCondition.notify_all();
+}
+
+template <typename Type>
+Type TransferValue<Type>::take() const {
+ std::unique_lock lock(mMutex);
+ base::ScopedLockAssertion lockAssertion(mMutex);
+ mCondition.wait(lock, [this]() REQUIRES(mMutex) { return mObject.has_value(); });
+ std::optional<Type> object;
+ std::swap(object, mObject);
+ return std::move(object).value();
+}
+
+} // namespace android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_TRANSFER_VALUE_H
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
new file mode 100644
index 0000000..c04c8df
--- /dev/null
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CommonUtils.h"
+
+#include "HandleError.h"
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+
+#include <algorithm>
+#include <any>
+#include <functional>
+#include <optional>
+#include <variant>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+namespace {
+
+bool hasNoPointerData(const nn::Operand& operand);
+bool hasNoPointerData(const nn::Model::Subgraph& subgraph);
+bool hasNoPointerData(const nn::Request::Argument& argument);
+
+template <typename Type>
+bool hasNoPointerData(const std::vector<Type>& objects) {
+ return std::all_of(objects.begin(), objects.end(),
+ [](const auto& object) { return hasNoPointerData(object); });
+}
+
+bool hasNoPointerData(const nn::DataLocation& location) {
+ return std::visit([](auto ptr) { return ptr == nullptr; }, location.pointer);
+}
+
+bool hasNoPointerData(const nn::Operand& operand) {
+ return hasNoPointerData(operand.location);
+}
+
+bool hasNoPointerData(const nn::Model::Subgraph& subgraph) {
+ return hasNoPointerData(subgraph.operands);
+}
+
+bool hasNoPointerData(const nn::Request::Argument& argument) {
+ return hasNoPointerData(argument.location);
+}
+
+void copyPointersToSharedMemory(nn::Operand* operand, nn::ConstantMemoryBuilder* memoryBuilder) {
+ CHECK(operand != nullptr);
+ CHECK(memoryBuilder != nullptr);
+
+ if (operand->lifetime != nn::Operand::LifeTime::POINTER) {
+ return;
+ }
+
+ const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
+ operand->location.pointer);
+ CHECK(data != nullptr);
+ operand->lifetime = nn::Operand::LifeTime::CONSTANT_REFERENCE;
+ operand->location = memoryBuilder->append(data, operand->location.length);
+}
+
+void copyPointersToSharedMemory(nn::Model::Subgraph* subgraph,
+ nn::ConstantMemoryBuilder* memoryBuilder) {
+ CHECK(subgraph != nullptr);
+ std::for_each(subgraph->operands.begin(), subgraph->operands.end(),
+ [memoryBuilder](auto& operand) {
+ copyPointersToSharedMemory(&operand, memoryBuilder);
+ });
+}
+
+} // anonymous namespace
+
+nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
+ const nn::Capabilities::PerformanceInfo& float32Performance,
+ const nn::Capabilities::PerformanceInfo& quantized8Performance) {
+ // In Android P, most data types are treated as having the same performance as
+ // TENSOR_QUANT8_ASYMM. This collection must be in sorted order.
+ std::vector<nn::Capabilities::OperandPerformance> operandPerformances = {
+ {.type = nn::OperandType::FLOAT32, .info = float32Performance},
+ {.type = nn::OperandType::INT32, .info = quantized8Performance},
+ {.type = nn::OperandType::UINT32, .info = quantized8Performance},
+ {.type = nn::OperandType::TENSOR_FLOAT32, .info = float32Performance},
+ {.type = nn::OperandType::TENSOR_INT32, .info = quantized8Performance},
+ {.type = nn::OperandType::TENSOR_QUANT8_ASYMM, .info = quantized8Performance},
+ {.type = nn::OperandType::OEM, .info = quantized8Performance},
+ {.type = nn::OperandType::TENSOR_OEM_BYTE, .info = quantized8Performance},
+ };
+ return nn::Capabilities::OperandPerformanceTable::create(std::move(operandPerformances))
+ .value();
+}
+
+bool hasNoPointerData(const nn::Model& model) {
+ return hasNoPointerData(model.main) && hasNoPointerData(model.referenced);
+}
+
+bool hasNoPointerData(const nn::Request& request) {
+ return hasNoPointerData(request.inputs) && hasNoPointerData(request.outputs);
+}
+
+nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
+ const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut) {
+ CHECK(model != nullptr);
+ CHECK(maybeModelInSharedOut != nullptr);
+
+ if (hasNoPointerData(*model)) {
+ return *model;
+ }
+
+ // Make a copy of the model in order to make modifications. The modified model is returned to
+ // the caller through `maybeModelInSharedOut` if the function succeeds.
+ nn::Model modelInShared = *model;
+
+ nn::ConstantMemoryBuilder memoryBuilder(modelInShared.pools.size());
+ copyPointersToSharedMemory(&modelInShared.main, &memoryBuilder);
+ std::for_each(modelInShared.referenced.begin(), modelInShared.referenced.end(),
+ [&memoryBuilder](auto& subgraph) {
+ copyPointersToSharedMemory(&subgraph, &memoryBuilder);
+ });
+
+ if (!memoryBuilder.empty()) {
+ auto memory = NN_TRY(memoryBuilder.finish());
+ modelInShared.pools.push_back(std::move(memory));
+ }
+
+ *maybeModelInSharedOut = modelInShared;
+ return **maybeModelInSharedOut;
+}
+
+nn::GeneralResult<std::reference_wrapper<const nn::Request>> flushDataFromPointerToShared(
+ const nn::Request* request, std::optional<nn::Request>* maybeRequestInSharedOut) {
+ CHECK(request != nullptr);
+ CHECK(maybeRequestInSharedOut != nullptr);
+
+ if (hasNoPointerData(*request)) {
+ return *request;
+ }
+
+ // Make a copy of the request in order to make modifications. The modified request is returned
+ // to the caller through `maybeRequestInSharedOut` if the function succeeds.
+ nn::Request requestInShared = *request;
+
+ // Change input pointers to shared memory.
+ nn::ConstantMemoryBuilder inputBuilder(requestInShared.pools.size());
+ for (auto& input : requestInShared.inputs) {
+ const auto& location = input.location;
+ if (input.lifetime != nn::Request::Argument::LifeTime::POINTER) {
+ continue;
+ }
+
+ input.lifetime = nn::Request::Argument::LifeTime::POOL;
+ const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
+ location.pointer);
+ CHECK(data != nullptr);
+ input.location = inputBuilder.append(data, location.length);
+ }
+
+ // Allocate input memory.
+ if (!inputBuilder.empty()) {
+ auto memory = NN_TRY(inputBuilder.finish());
+ requestInShared.pools.push_back(std::move(memory));
+ }
+
+ // Change output pointers to shared memory.
+ nn::MutableMemoryBuilder outputBuilder(requestInShared.pools.size());
+ for (auto& output : requestInShared.outputs) {
+ const auto& location = output.location;
+ if (output.lifetime != nn::Request::Argument::LifeTime::POINTER) {
+ continue;
+ }
+
+ output.lifetime = nn::Request::Argument::LifeTime::POOL;
+ output.location = outputBuilder.append(location.length);
+ }
+
+ // Allocate output memory.
+ if (!outputBuilder.empty()) {
+ auto memory = NN_TRY(outputBuilder.finish());
+ requestInShared.pools.push_back(std::move(memory));
+ }
+
+ *maybeRequestInSharedOut = requestInShared;
+ return **maybeRequestInSharedOut;
+}
+
+nn::GeneralResult<void> unflushDataFromSharedToPointer(
+ const nn::Request& request, const std::optional<nn::Request>& maybeRequestInShared) {
+ if (!maybeRequestInShared.has_value() || maybeRequestInShared->pools.empty() ||
+ !std::holds_alternative<nn::Memory>(maybeRequestInShared->pools.back())) {
+ return {};
+ }
+ const auto& requestInShared = *maybeRequestInShared;
+
+ // Map the memory.
+ const auto& outputMemory = std::get<nn::Memory>(requestInShared.pools.back());
+ const auto [pointer, size, context] = NN_TRY(map(outputMemory));
+ const uint8_t* constantPointer =
+ std::visit([](const auto& o) { return static_cast<const uint8_t*>(o); }, pointer);
+
+ // Flush each output pointer.
+ CHECK_EQ(request.outputs.size(), requestInShared.outputs.size());
+ for (size_t i = 0; i < request.outputs.size(); ++i) {
+ const auto& location = request.outputs[i].location;
+ const auto& locationInShared = requestInShared.outputs[i].location;
+ if (!std::holds_alternative<void*>(location.pointer)) {
+ continue;
+ }
+
+ // Get output pointer and size.
+ void* data = std::get<void*>(location.pointer);
+ CHECK(data != nullptr);
+ const size_t length = location.length;
+
+ // Get output pool location.
+ CHECK(requestInShared.outputs[i].lifetime == nn::Request::Argument::LifeTime::POOL);
+ const size_t index = locationInShared.poolIndex;
+ const size_t offset = locationInShared.offset;
+ const size_t outputPoolIndex = requestInShared.pools.size() - 1;
+ CHECK(locationInShared.length == length);
+ CHECK(index == outputPoolIndex);
+
+ // Flush memory.
+ std::memcpy(data, constantPointer + offset, length);
+ }
+
+ return {};
+}
+
+std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
+ const std::vector<nn::Operation>& operations) {
+ return nn::countNumberOfConsumers(numberOfOperands, operations);
+}
+
+nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::SharedHandle& handle) {
+ if (handle == nullptr) {
+ return {};
+ }
+
+ std::vector<base::unique_fd> fds;
+ fds.reserve(handle->fds.size());
+ for (const auto& fd : handle->fds) {
+ int dupFd = dup(fd);
+ if (dupFd == -1) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
+ }
+ fds.emplace_back(dupFd);
+ }
+
+ native_handle_t* nativeHandle = native_handle_create(handle->fds.size(), handle->ints.size());
+ if (nativeHandle == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to create native_handle";
+ }
+ for (size_t i = 0; i < fds.size(); ++i) {
+ nativeHandle->data[i] = fds[i].release();
+ }
+ std::copy(handle->ints.begin(), handle->ints.end(), &nativeHandle->data[nativeHandle->numFds]);
+
+ hidl_handle hidlHandle;
+ hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
+ return hidlHandle;
+}
+
+nn::GeneralResult<nn::SharedHandle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
+ if (handle == nullptr) {
+ return nullptr;
+ }
+
+ std::vector<base::unique_fd> fds;
+ fds.reserve(handle->numFds);
+ for (int i = 0; i < handle->numFds; ++i) {
+ int dupFd = dup(handle->data[i]);
+ if (dupFd == -1) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
+ }
+ fds.emplace_back(dupFd);
+ }
+
+ std::vector<int> ints(&handle->data[handle->numFds],
+ &handle->data[handle->numFds + handle->numInts]);
+
+ return std::make_shared<const nn::Handle>(nn::Handle{
+ .fds = std::move(fds),
+ .ints = std::move(ints),
+ });
+}
+
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+ const std::vector<nn::SyncFence>& syncFences) {
+ hidl_vec<hidl_handle> handles(syncFences.size());
+ for (size_t i = 0; i < syncFences.size(); ++i) {
+ handles[i] =
+ NN_TRY(hal::utils::hidlHandleFromSharedHandle(syncFences[i].getSharedHandle()));
+ }
+ return handles;
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidBuffer.cpp b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
new file mode 100644
index 0000000..c6f75d7
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidBuffer.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidBuffer.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::Request::MemoryDomainToken InvalidBuffer::getToken() const {
+ return nn::Request::MemoryDomainToken{};
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyTo(const nn::Memory& /*dst*/) const {
+ return NN_ERROR() << "InvalidBuffer";
+}
+
+nn::GeneralResult<void> InvalidBuffer::copyFrom(const nn::Memory& /*src*/,
+ const nn::Dimensions& /*dimensions*/) const {
+ return NN_ERROR() << "InvalidBuffer";
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
new file mode 100644
index 0000000..535ccb4
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidDevice.h"
+
+#include "InvalidBuffer.h"
+#include "InvalidPreparedModel.h"
+
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+InvalidDevice::InvalidDevice(std::string name, std::string versionString, nn::Version featureLevel,
+ nn::DeviceType type, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
+ std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded)
+ : kName(std::move(name)),
+ kVersionString(std::move(versionString)),
+ kFeatureLevel(featureLevel),
+ kType(type),
+ kExtensions(std::move(extensions)),
+ kCapabilities(std::move(capabilities)),
+ kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded) {}
+
+const std::string& InvalidDevice::getName() const {
+ return kName;
+}
+
+const std::string& InvalidDevice::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version InvalidDevice::getFeatureLevel() const {
+ return kFeatureLevel;
+}
+
+nn::DeviceType InvalidDevice::getType() const {
+ return kType;
+}
+
+const std::vector<nn::Extension>& InvalidDevice::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& InvalidDevice::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> InvalidDevice::getNumberOfCacheFilesNeeded() const {
+ return kNumberOfCacheFilesNeeded;
+}
+
+nn::GeneralResult<void> InvalidDevice::wait() const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<std::vector<bool>> InvalidDevice::getSupportedOperations(
+ const nn::Model& /*model*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModel(
+ const nn::Model& /*model*/, nn::ExecutionPreference /*preference*/,
+ nn::Priority /*priority*/, nn::OptionalTimePoint /*deadline*/,
+ const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> InvalidDevice::prepareModelFromCache(
+ nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+nn::GeneralResult<nn::SharedBuffer> InvalidDevice::allocate(
+ const nn::BufferDesc& /*desc*/,
+ const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
+ const std::vector<nn::BufferRole>& /*inputRoles*/,
+ const std::vector<nn::BufferRole>& /*outputRoles*/) const {
+ return NN_ERROR() << "InvalidDevice";
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
new file mode 100644
index 0000000..9ae7a63
--- /dev/null
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InvalidPreparedModel.h"
+
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+InvalidPreparedModel::execute(const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
+ const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+ return NN_ERROR() << "InvalidPreparedModel";
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+InvalidPreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+ return NN_ERROR() << "InvalidPreparedModel";
+}
+
+std::any InvalidPreparedModel::getUnderlyingResource() const {
+ return {};
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ProtectCallback.cpp b/neuralnetworks/utils/common/src/ProtectCallback.cpp
new file mode 100644
index 0000000..1d9a307
--- /dev/null
+++ b/neuralnetworks/utils/common/src/ProtectCallback.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ProtectCallback.h"
+
+#include <android-base/logging.h>
+#include <android-base/scopeguard.h>
+#include <android-base/thread_annotations.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/hal/HandleError.h>
+
+#include <algorithm>
+#include <functional>
+#include <mutex>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+void DeathRecipient::serviceDied(uint64_t /*cookie*/, const wp<hidl::base::V1_0::IBase>& /*who*/) {
+ std::lock_guard guard(mMutex);
+ std::for_each(mObjects.begin(), mObjects.end(),
+ [](IProtectedCallback* killable) { killable->notifyAsDeadObject(); });
+}
+
+void DeathRecipient::add(IProtectedCallback* killable) const {
+ CHECK(killable != nullptr);
+ std::lock_guard guard(mMutex);
+ mObjects.push_back(killable);
+}
+
+void DeathRecipient::remove(IProtectedCallback* killable) const {
+ CHECK(killable != nullptr);
+ std::lock_guard guard(mMutex);
+ const auto removedIter = std::remove(mObjects.begin(), mObjects.end(), killable);
+ mObjects.erase(removedIter);
+}
+
+nn::GeneralResult<DeathHandler> DeathHandler::create(sp<hidl::base::V1_0::IBase> object) {
+ if (object == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "utils::DeathHandler::create must have non-null object";
+ }
+ auto deathRecipient = sp<DeathRecipient>::make();
+
+ const auto ret = object->linkToDeath(deathRecipient, /*cookie=*/0);
+ const bool success = NN_TRY(handleTransportError(ret));
+ if (!success) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "IBase::linkToDeath returned false";
+ }
+
+ return DeathHandler(std::move(object), std::move(deathRecipient));
+}
+
+DeathHandler::DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient)
+ : kObject(std::move(object)), kDeathRecipient(std::move(deathRecipient)) {
+ CHECK(kObject != nullptr);
+ CHECK(kDeathRecipient != nullptr);
+}
+
+DeathHandler::~DeathHandler() {
+ if (kObject != nullptr && kDeathRecipient != nullptr) {
+ const auto ret = kObject->unlinkToDeath(kDeathRecipient);
+ const auto maybeSuccess = handleTransportError(ret);
+ if (!maybeSuccess.has_value()) {
+ LOG(ERROR) << maybeSuccess.error().message;
+ } else if (!maybeSuccess.value()) {
+ LOG(ERROR) << "IBase::linkToDeath returned false";
+ }
+ }
+}
+
+[[nodiscard]] base::ScopeGuard<DeathHandler::Cleanup> DeathHandler::protectCallback(
+ IProtectedCallback* killable) const {
+ CHECK(killable != nullptr);
+ kDeathRecipient->add(killable);
+ return base::make_scope_guard(
+ [deathRecipient = kDeathRecipient, killable] { deathRecipient->remove(killable); });
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientBuffer.cpp b/neuralnetworks/utils/common/src/ResilientBuffer.cpp
new file mode 100644
index 0000000..984295b
--- /dev/null
+++ b/neuralnetworks/utils/common/src/ResilientBuffer.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ResilientBuffer.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::GeneralResult<std::shared_ptr<const ResilientBuffer>> ResilientBuffer::create(
+ Factory makeBuffer) {
+ if (makeBuffer == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "utils::ResilientBuffer::create must have non-empty makeBuffer";
+ }
+ auto buffer = NN_TRY(makeBuffer(/*blocking=*/true));
+ CHECK(buffer != nullptr);
+ return std::make_shared<const ResilientBuffer>(PrivateConstructorTag{}, std::move(makeBuffer),
+ std::move(buffer));
+}
+
+ResilientBuffer::ResilientBuffer(PrivateConstructorTag /*tag*/, Factory makeBuffer,
+ nn::SharedBuffer buffer)
+ : kMakeBuffer(std::move(makeBuffer)), mBuffer(std::move(buffer)) {
+ CHECK(kMakeBuffer != nullptr);
+ CHECK(mBuffer != nullptr);
+}
+
+nn::SharedBuffer ResilientBuffer::getBuffer() const {
+ std::lock_guard guard(mMutex);
+ return mBuffer;
+}
+nn::SharedBuffer ResilientBuffer::recover(const nn::IBuffer* /*failingBuffer*/,
+ bool /*blocking*/) const {
+ std::lock_guard guard(mMutex);
+ return mBuffer;
+}
+
+nn::Request::MemoryDomainToken ResilientBuffer::getToken() const {
+ return getBuffer()->getToken();
+}
+
+nn::GeneralResult<void> ResilientBuffer::copyTo(const nn::Memory& dst) const {
+ return getBuffer()->copyTo(dst);
+}
+
+nn::GeneralResult<void> ResilientBuffer::copyFrom(const nn::Memory& src,
+ const nn::Dimensions& dimensions) const {
+ return getBuffer()->copyFrom(src, dimensions);
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
new file mode 100644
index 0000000..2f83c5c
--- /dev/null
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ResilientDevice.h"
+
+#include "InvalidBuffer.h"
+#include "InvalidDevice.h"
+#include "InvalidPreparedModel.h"
+#include "ResilientBuffer.h"
+#include "ResilientPreparedModel.h"
+
+#include <android-base/logging.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+namespace {
+
+template <typename FnType>
+auto protect(const ResilientDevice& resilientDevice, const FnType& fn, bool blocking)
+ -> decltype(fn(*resilientDevice.getDevice())) {
+ auto device = resilientDevice.getDevice();
+ auto result = fn(*device);
+
+ // Immediately return if device is not dead.
+ if (result.has_value() || result.error().code != nn::ErrorStatus::DEAD_OBJECT) {
+ return result;
+ }
+
+ device = resilientDevice.recover(device.get(), blocking);
+ return fn(*device);
+}
+
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const ResilientDevice>> ResilientDevice::create(
+ Factory makeDevice) {
+ if (makeDevice == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "utils::ResilientDevice::create must have non-empty makeDevice";
+ }
+ auto device = NN_TRY(makeDevice(/*blocking=*/true));
+ CHECK(device != nullptr);
+
+ auto name = device->getName();
+ auto versionString = device->getVersionString();
+ auto extensions = device->getSupportedExtensions();
+ auto capabilities = device->getCapabilities();
+
+ return std::make_shared<ResilientDevice>(PrivateConstructorTag{}, std::move(makeDevice),
+ std::move(name), std::move(versionString),
+ std::move(extensions), std::move(capabilities),
+ std::move(device));
+}
+
+ResilientDevice::ResilientDevice(PrivateConstructorTag /*tag*/, Factory makeDevice,
+ std::string name, std::string versionString,
+ std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities, nn::SharedDevice device)
+ : kMakeDevice(std::move(makeDevice)),
+ kName(std::move(name)),
+ kVersionString(std::move(versionString)),
+ kExtensions(std::move(extensions)),
+ kCapabilities(std::move(capabilities)),
+ mDevice(std::move(device)) {
+ CHECK(kMakeDevice != nullptr);
+ CHECK(mDevice != nullptr);
+}
+
+nn::SharedDevice ResilientDevice::getDevice() const {
+ std::lock_guard guard(mMutex);
+ return mDevice;
+}
+
+nn::SharedDevice ResilientDevice::recover(const nn::IDevice* failingDevice, bool blocking) const {
+ std::lock_guard guard(mMutex);
+
+ // Another caller updated the failing device.
+ if (mDevice.get() != failingDevice) {
+ return mDevice;
+ }
+
+ auto maybeDevice = kMakeDevice(blocking);
+ if (!maybeDevice.has_value()) {
+ const auto& [message, code] = maybeDevice.error();
+ LOG(ERROR) << "Failed to recover dead device with error " << code << ": " << message;
+ return mDevice;
+ }
+ auto device = std::move(maybeDevice).value();
+
+ // If recovered device has different metadata than what is cached (i.e., because it was
+ // updated), mark the device as invalid and preserve the cached data.
+ auto compare = [this, &device](auto fn) REQUIRES(mMutex) {
+ return std::invoke(fn, mDevice) != std::invoke(fn, device);
+ };
+ if (compare(&IDevice::getName) || compare(&IDevice::getVersionString) ||
+ compare(&IDevice::getFeatureLevel) || compare(&IDevice::getType) ||
+ compare(&IDevice::getSupportedExtensions) || compare(&IDevice::getCapabilities)) {
+ LOG(ERROR) << "Recovered device has different metadata than what is cached. Marking "
+ "IDevice object as invalid.";
+ device = std::make_shared<const InvalidDevice>(
+ kName, kVersionString, mDevice->getFeatureLevel(), mDevice->getType(), kExtensions,
+ kCapabilities, mDevice->getNumberOfCacheFilesNeeded());
+ mIsValid = false;
+ }
+
+ mDevice = std::move(device);
+ return mDevice;
+}
+
+const std::string& ResilientDevice::getName() const {
+ return kName;
+}
+
+const std::string& ResilientDevice::getVersionString() const {
+ return kVersionString;
+}
+
+nn::Version ResilientDevice::getFeatureLevel() const {
+ return getDevice()->getFeatureLevel();
+}
+
+nn::DeviceType ResilientDevice::getType() const {
+ return getDevice()->getType();
+}
+
+const std::vector<nn::Extension>& ResilientDevice::getSupportedExtensions() const {
+ return kExtensions;
+}
+
+const nn::Capabilities& ResilientDevice::getCapabilities() const {
+ return kCapabilities;
+}
+
+std::pair<uint32_t, uint32_t> ResilientDevice::getNumberOfCacheFilesNeeded() const {
+ return getDevice()->getNumberOfCacheFilesNeeded();
+}
+
+nn::GeneralResult<void> ResilientDevice::wait() const {
+ const auto fn = [](const nn::IDevice& device) { return device.wait(); };
+ return protect(*this, fn, /*blocking=*/true);
+}
+
+nn::GeneralResult<std::vector<bool>> ResilientDevice::getSupportedOperations(
+ const nn::Model& model) const {
+ const auto fn = [&model](const nn::IDevice& device) {
+ return device.getSupportedOperations(model);
+ };
+ return protect(*this, fn, /*blocking=*/false);
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModel(
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ auto self = shared_from_this();
+ ResilientPreparedModel::Factory makePreparedModel =
+ [device = std::move(self), model, preference, priority, deadline, modelCache, dataCache,
+ token](bool blocking) -> nn::GeneralResult<nn::SharedPreparedModel> {
+ return device->prepareModelInternal(blocking, model, preference, priority, deadline,
+ modelCache, dataCache, token);
+ };
+ return ResilientPreparedModel::create(std::move(makePreparedModel));
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelFromCache(
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ auto self = shared_from_this();
+ ResilientPreparedModel::Factory makePreparedModel =
+ [device = std::move(self), deadline, modelCache, dataCache,
+ token](bool blocking) -> nn::GeneralResult<nn::SharedPreparedModel> {
+ return device->prepareModelFromCacheInternal(blocking, deadline, modelCache, dataCache,
+ token);
+ };
+ return ResilientPreparedModel::create(std::move(makePreparedModel));
+}
+
+nn::GeneralResult<nn::SharedBuffer> ResilientDevice::allocate(
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const {
+ auto self = shared_from_this();
+ ResilientBuffer::Factory makeBuffer =
+ [device = std::move(self), desc, preparedModels, inputRoles,
+ outputRoles](bool blocking) -> nn::GeneralResult<nn::SharedBuffer> {
+ return device->allocateInternal(blocking, desc, preparedModels, inputRoles, outputRoles);
+ };
+ return ResilientBuffer::create(std::move(makeBuffer));
+}
+
+bool ResilientDevice::isValidInternal() const {
+ std::lock_guard hold(mMutex);
+ return mIsValid;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
+ bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
+ nn::Priority priority, nn::OptionalTimePoint deadline,
+ const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidPreparedModel>();
+ }
+ const auto fn = [&model, preference, priority, deadline, &modelCache, &dataCache,
+ token](const nn::IDevice& device) {
+ return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
+ token);
+ };
+ return protect(*this, fn, blocking);
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelFromCacheInternal(
+ bool blocking, nn::OptionalTimePoint deadline,
+ const std::vector<nn::SharedHandle>& modelCache,
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidPreparedModel>();
+ }
+ const auto fn = [deadline, &modelCache, &dataCache, token](const nn::IDevice& device) {
+ return device.prepareModelFromCache(deadline, modelCache, dataCache, token);
+ };
+ return protect(*this, fn, blocking);
+}
+
+nn::GeneralResult<nn::SharedBuffer> ResilientDevice::allocateInternal(
+ bool blocking, const nn::BufferDesc& desc,
+ const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const std::vector<nn::BufferRole>& inputRoles,
+ const std::vector<nn::BufferRole>& outputRoles) const {
+ if (!isValidInternal()) {
+ return std::make_shared<const InvalidBuffer>();
+ }
+ const auto fn = [&desc, &preparedModels, &inputRoles, &outputRoles](const nn::IDevice& device) {
+ return device.allocate(desc, preparedModels, inputRoles, outputRoles);
+ };
+ return protect(*this, fn, blocking);
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
new file mode 100644
index 0000000..1c9ecba
--- /dev/null
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ResilientPreparedModel.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+nn::GeneralResult<std::shared_ptr<const ResilientPreparedModel>> ResilientPreparedModel::create(
+ Factory makePreparedModel) {
+ if (makePreparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "utils::ResilientPreparedModel::create must have non-empty makePreparedModel";
+ }
+ auto preparedModel = NN_TRY(makePreparedModel(/*blocking=*/true));
+ CHECK(preparedModel != nullptr);
+ return std::make_shared<ResilientPreparedModel>(
+ PrivateConstructorTag{}, std::move(makePreparedModel), std::move(preparedModel));
+}
+
+ResilientPreparedModel::ResilientPreparedModel(PrivateConstructorTag /*tag*/,
+ Factory makePreparedModel,
+ nn::SharedPreparedModel preparedModel)
+ : kMakePreparedModel(std::move(makePreparedModel)), mPreparedModel(std::move(preparedModel)) {
+ CHECK(kMakePreparedModel != nullptr);
+ CHECK(mPreparedModel != nullptr);
+}
+
+nn::SharedPreparedModel ResilientPreparedModel::getPreparedModel() const {
+ std::lock_guard guard(mMutex);
+ return mPreparedModel;
+}
+
+nn::SharedPreparedModel ResilientPreparedModel::recover(
+ const nn::IPreparedModel* /*failingPreparedModel*/, bool /*blocking*/) const {
+ std::lock_guard guard(mMutex);
+ return mPreparedModel;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+ResilientPreparedModel::execute(const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration) const {
+ return getPreparedModel()->execute(request, measure, deadline, loopTimeoutDuration);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+ResilientPreparedModel::executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalTimeoutDuration& loopTimeoutDuration,
+ const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const {
+ return getPreparedModel()->executeFenced(request, waitFor, measure, deadline,
+ loopTimeoutDuration, timeoutDurationAfterFence);
+}
+
+std::any ResilientPreparedModel::getUnderlyingResource() const {
+ return getPreparedModel()->getUnderlyingResource();
+}
+
+} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
new file mode 100644
index 0000000..402598c
--- /dev/null
+++ b/neuralnetworks/utils/service/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_service",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal"],
+ export_include_dirs: ["include"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_1_0",
+ "neuralnetworks_utils_hal_1_1",
+ "neuralnetworks_utils_hal_1_2",
+ "neuralnetworks_utils_hal_1_3",
+ "neuralnetworks_utils_hal_common",
+ ],
+ shared_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ ],
+}
diff --git a/neuralnetworks/utils/service/include/nnapi/hal/Service.h b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
new file mode 100644
index 0000000..e339627
--- /dev/null
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_SERVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_SERVICE_H
+
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+#include <memory>
+#include <vector>
+
+namespace android::nn::hal {
+
+std::vector<nn::SharedDevice> getDevices();
+
+} // namespace android::nn::hal
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_SERVICE_H
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
new file mode 100644
index 0000000..a59549d
--- /dev/null
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Service.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Service.h>
+#include <nnapi/hal/1.1/Service.h>
+#include <nnapi/hal/1.2/Service.h>
+#include <nnapi/hal/1.3/Service.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::service {
+namespace {
+
+using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
+
+void getDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
+ std::vector<nn::SharedDevice>* devices,
+ std::unordered_set<std::string>* registeredDevices) {
+ CHECK(devices != nullptr);
+ CHECK(registeredDevices != nullptr);
+
+ const auto names = getAllHalInstanceNames(descriptor);
+ for (const auto& name : names) {
+ if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
+ auto maybeDevice = getDevice(name);
+ if (maybeDevice.has_value()) {
+ auto device = std::move(maybeDevice).value();
+ CHECK(device != nullptr);
+ devices->push_back(std::move(device));
+ } else {
+ LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
+ << ": " << maybeDevice.error().message;
+ }
+ }
+ }
+}
+
+std::vector<nn::SharedDevice> getDevices() {
+ std::vector<nn::SharedDevice> devices;
+ std::unordered_set<std::string> registeredDevices;
+
+ getDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
+ ®isteredDevices);
+ getDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
+ ®isteredDevices);
+ getDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
+ ®isteredDevices);
+ getDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
+ ®isteredDevices);
+
+ return devices;
+}
+
+} // namespace
+} // namespace android::hardware::neuralnetworks::service
+
+namespace android::nn::hal {
+
+std::vector<nn::SharedDevice> getDevices() {
+ return hardware::neuralnetworks::service::getDevices();
+}
+
+} // namespace android::nn::hal
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index bd64907..667922a 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.nfc@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"INfc.hal",
diff --git a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
index 1feae9d..4d997e6 100644
--- a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
+++ b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
@@ -578,6 +578,7 @@
EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, NfcHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(INfc::descriptor)),
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index 1f8789f..a8976b0 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.nfc@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"INfc.hal",
diff --git a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
index 13537e4..1c4c78a 100644
--- a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
+++ b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
@@ -211,6 +211,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, NfcHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(INfc::descriptor)),
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
index aa68d2f..514d531 100644
--- a/nfc/1.2/Android.bp
+++ b/nfc/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.nfc@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"INfc.hal",
diff --git a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
index 3ec088d..e4cb12b 100644
--- a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
+++ b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
@@ -155,6 +155,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, NfcHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(INfc::descriptor)),
diff --git a/oemlock/1.0/Android.bp b/oemlock/1.0/Android.bp
index e784be0..8ab2911 100644
--- a/oemlock/1.0/Android.bp
+++ b/oemlock/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.oemlock@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IOemLock.hal",
diff --git a/oemlock/1.0/vts/functional/VtsHalOemLockV1_0TargetTest.cpp b/oemlock/1.0/vts/functional/VtsHalOemLockV1_0TargetTest.cpp
index bafe87d..76c6440 100644
--- a/oemlock/1.0/vts/functional/VtsHalOemLockV1_0TargetTest.cpp
+++ b/oemlock/1.0/vts/functional/VtsHalOemLockV1_0TargetTest.cpp
@@ -188,6 +188,7 @@
ASSERT_EQ(allowed, originallyAllowed);
};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OemLockHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, OemLockHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IOemLock::descriptor)),
diff --git a/power/1.0/Android.bp b/power/1.0/Android.bp
index 6ba1d78..7381c70 100644
--- a/power/1.0/Android.bp
+++ b/power/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.power@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IPower.hal",
diff --git a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
index 7e0ae9c..d011c30 100644
--- a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
+++ b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
@@ -59,7 +59,7 @@
sp<IPower> power;
};
-// Sanity check Power::setInteractive.
+// Validate Power::setInteractive.
TEST_P(PowerHidlTest, SetInteractive) {
Return<void> ret;
@@ -101,7 +101,7 @@
ASSERT_TRUE(android::base::WriteStringToFile(old_governor, CPU_GOVERNOR_PATH));
}
-// Sanity check Power::powerHint on good and bad inputs.
+// Validate Power::powerHint on good and bad inputs.
TEST_P(PowerHidlTest, PowerHint) {
PowerHint badHint = static_cast<PowerHint>(0xA);
auto hints = {PowerHint::VSYNC, PowerHint::INTERACTION,
@@ -139,7 +139,7 @@
} while (std::next_permutation(hints2.begin(), hints2.end(), compareHints));
}
-// Sanity check Power::setFeature() on good and bad inputs.
+// Validate Power::setFeature() on good and bad inputs.
TEST_P(PowerHidlTest, SetFeature) {
Return<void> ret;
ret = power->setFeature(Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, true);
@@ -154,7 +154,7 @@
ASSERT_TRUE(ret.isOk());
}
-// Sanity check Power::getPlatformLowPowerStats().
+// Validate Power::getPlatformLowPowerStats().
TEST_P(PowerHidlTest, GetPlatformLowPowerStats) {
hidl_vec<PowerStatePlatformSleepState> vec;
Status s;
@@ -168,6 +168,7 @@
ASSERT_TRUE(s == Status::SUCCESS || s == Status::FILESYSTEM_ERROR);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, PowerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPower::descriptor)),
diff --git a/power/1.1/Android.bp b/power/1.1/Android.bp
index 6b133cc..e026e70 100644
--- a/power/1.1/Android.bp
+++ b/power/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.power@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IPower.hal",
diff --git a/power/1.1/vts/functional/VtsHalPowerV1_1TargetTest.cpp b/power/1.1/vts/functional/VtsHalPowerV1_1TargetTest.cpp
index e9a722c..2904a0d 100644
--- a/power/1.1/vts/functional/VtsHalPowerV1_1TargetTest.cpp
+++ b/power/1.1/vts/functional/VtsHalPowerV1_1TargetTest.cpp
@@ -41,7 +41,7 @@
sp<IPower> power;
};
-// Sanity check Power::getSubsystemLowPowerStats().
+// Validate Power::getSubsystemLowPowerStats().
TEST_P(PowerHidlTest, GetSubsystemLowPowerStats) {
hidl_vec<PowerStateSubsystem> vec;
Status s;
@@ -56,7 +56,7 @@
ASSERT_TRUE(s == Status::SUCCESS || s == Status::FILESYSTEM_ERROR);
}
-// Sanity check Power::powerHintAsync on good and bad inputs.
+// Validate Power::powerHintAsync on good and bad inputs.
TEST_P(PowerHidlTest, PowerHintAsync) {
PowerHint badHint = static_cast<PowerHint>(0xA);
auto hints = {PowerHint::VSYNC, PowerHint::INTERACTION, PowerHint::VIDEO_ENCODE,
@@ -91,6 +91,7 @@
} while (std::next_permutation(hints2.begin(), hints2.end(), compareHints));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, PowerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPower::descriptor)),
diff --git a/power/1.2/Android.bp b/power/1.2/Android.bp
index 296965b..ccf66dc 100644
--- a/power/1.2/Android.bp
+++ b/power/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.power@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IPower.hal",
diff --git a/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp b/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp
index a5ecf5d..1c6eba4 100644
--- a/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp
+++ b/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp
@@ -37,7 +37,7 @@
sp<IPower> power;
};
-// Sanity check Power::PowerHintAsync_1_2 on good and bad inputs.
+// Validate Power::PowerHintAsync_1_2 on good and bad inputs.
TEST_P(PowerHidlTest, PowerHintAsync_1_2) {
std::vector<PowerHint> hints;
for (uint32_t i = static_cast<uint32_t>(PowerHint::VSYNC);
@@ -76,6 +76,7 @@
} while (std::next_permutation(hints2.begin(), hints2.end(), compareHints));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, PowerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPower::descriptor)),
diff --git a/power/1.3/Android.bp b/power/1.3/Android.bp
index 00ca750..15955e5 100644
--- a/power/1.3/Android.bp
+++ b/power/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.power@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IPower.hal",
diff --git a/power/1.3/vts/functional/VtsHalPowerV1_3TargetTest.cpp b/power/1.3/vts/functional/VtsHalPowerV1_3TargetTest.cpp
index 3cf2adc..38f4cf5 100644
--- a/power/1.3/vts/functional/VtsHalPowerV1_3TargetTest.cpp
+++ b/power/1.3/vts/functional/VtsHalPowerV1_3TargetTest.cpp
@@ -41,6 +41,7 @@
ASSERT_TRUE(power->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, 0).isOk());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, PowerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPower::descriptor)),
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 25a385e..d036c90 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -126,6 +126,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
INSTANTIATE_TEST_SUITE_P(Power, PowerAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(IPower::descriptor)),
android::PrintInstanceNameToString);
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
index c592006..2a71490 100644
--- a/power/stats/1.0/Android.bp
+++ b/power/stats/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.power.stats@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IPowerStats.hal",
diff --git a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
index 3359669..c7d8091 100644
--- a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
+++ b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
@@ -556,6 +556,7 @@
thread1.join();
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerStatsHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, PowerStatsHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPowerStats::descriptor)),
diff --git a/prebuilt_hashes/26.txt b/prebuilt_hashes/26.txt
deleted file mode 100644
index f2feb4c..0000000
--- a/prebuilt_hashes/26.txt
+++ /dev/null
@@ -1,186 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-# android.hardware.automotive.* are unfrozen
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs released in Android O
-
-78589343d8ee2e1b155acad3fbdc7fcbb6af94491aee968b2383c21627264f8b android.hardware.radio@1.0::IRadioResponse
-c2c50ec74c87a583c683b4493f8f9f2e454a8d41c57af5b3eb88823a999f0ea4 android.hardware.radio@1.0::IRadioResponse
diff --git a/prebuilt_hashes/27.txt b/prebuilt_hashes/27.txt
deleted file mode 100644
index 23f2004..0000000
--- a/prebuilt_hashes/27.txt
+++ /dev/null
@@ -1,249 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-# android.hardware.automotive.* are unfrozen
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs during Android O MR1 (Initial Set)
-
-# android.hardware.automotive.* are unfrozen
-150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
-dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
-760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
-e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
-6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
-28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
-df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
-
-# HALs released in Android O MR1 (Initial Set)
-
-4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
-e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
-224f9d22a367a0016f09b6dc676f53f1446697d9dc747163032329e5da552de5 android.hardware.power@1.1::IPower
-574fd9758b7cab4922c72cc5a9f36d1cd48ffd3425fdd776426653280d3d4138 android.hardware.power@1.1::types
-f79edf50a378a9c9bb737f93f205dab91b4c63ea49723afc6f856c138203ea81 android.hardware.radio@1.1::IRadio
-fcc5c8c88b85a9f63fba67d9e674da466c72a98ca287f343fb5721d098713f86 android.hardware.radio@1.1::IRadioIndication
-50f27e8c7ec009d5d4418b2ce8392b940bbf052ecc1d7251285f332485a5ba4e android.hardware.radio@1.1::IRadioResponse
-be981148c95c0089f3ae92854f0e7ae999d308e927db3e065f12a4fabe07852f android.hardware.radio@1.1::ISap
-d8d6bf7b4d36c04ce587df75953c3f723cfbe71c896c1aa8ab6478eae126723d android.hardware.radio@1.1::types
-d8aae01606bfd34bf2fb9a59cadc016f46f318e56cddb8f15a945c5b3c1222bc android.hardware.tetheroffload.config@1.0::IOffloadConfig
-447b00306bc95a7aafec1d660f6f3e9f76ac8bc0353193435e5579ab833da619 android.hardware.tetheroffload.control@1.0::IOffloadControl
-07658829339d75962016e00ed81b005ad29fca7ac12ad3bc3ccd86b08d94c2d3 android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
-0df5b0178af15c53cdce8fcf8ca14035e8e08db4fa76fdc12009ddbe0b53626b android.hardware.tetheroffload.control@1.0::types
-b30ef02ef26ff804e2f6acf1201bc141b59e134e6a0338562284491102cb13e3 android.hardware.usb@1.1::IUsb
-13a580e35af01270a1e9774177c51db51d8672e6139ba00851e654e68a4d7dff android.hardware.usb@1.1::IUsbCallback
-f0ed667288908c08fced570bd1f3c4a0f236aa927938e805f0d9fece525da81e android.hardware.usb@1.1::types
-f95a1e85612f2d0d616eacd2eb63c52d10dfa889f165df57697c30e1f47b4785 android.hardware.vibrator@1.1::IVibrator
-246fb9d9e2b4800aeb0adc3cdbaa15d0321ebab54b7bd1ab87da5b67c7b0b064 android.hardware.vibrator@1.1::types
-9bc43413b80cd0c59a022e93da1448dcb82dd10c6dd31932df4659e4bdcb1368 android.hardware.weaver@1.0::IWeaver
-7728b0393a2ed9796537d4165c7d95407e9d8cb447a647b545fdfe06a28689e7 android.hardware.weaver@1.0::types
-bb7c96762d0aa3ddb874c8815bacdd3cbc8fb87ea2f82b928bc29e24a3593055 android.hardware.wifi.offload@1.0::IOffload
-c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardware.wifi.offload@1.0::IOffloadCallback
-b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
-c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
-b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
-
-# ABI preserving changes to HALs during Android O MR1 (Final Set)
-2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
-05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
-
-# HALs released in Android O MR1 (Final Set)
-044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
-c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
-b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
-bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
-e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
-63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
-bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
-4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
-0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
-b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
-a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
-86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
-503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
-619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
-0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
-09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
-246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
-93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
-f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
-953607822954435874f4b81686440a604e2a88cdd2d9164c6293f3d5772510d7 android.hardware.neuralnetworks@1.0::IPreparedModel
-73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
-f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
-c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
diff --git a/prebuilt_hashes/28.txt b/prebuilt_hashes/28.txt
deleted file mode 100644
index 8a45ca5..0000000
--- a/prebuilt_hashes/28.txt
+++ /dev/null
@@ -1,384 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs during Android O MR1 (Initial Set)
-
-150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
-dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
-760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
-78589343d8ee2e1b155acad3fbdc7fcbb6af94491aee968b2383c21627264f8b android.hardware.radio@1.0::IRadioResponse # Available in Android O, b/68061860
-e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
-6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
-c2c50ec74c87a583c683b4493f8f9f2e454a8d41c57af5b3eb88823a999f0ea4 android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O
-4922dd58e89a03181ed1c48a6e118e47633b73b11090bdfed5aa920d25a7592b android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O DR
-28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
-df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
-
-# HALs released in Android O MR1 (Initial Set)
-
-4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
-e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
-224f9d22a367a0016f09b6dc676f53f1446697d9dc747163032329e5da552de5 android.hardware.power@1.1::IPower
-574fd9758b7cab4922c72cc5a9f36d1cd48ffd3425fdd776426653280d3d4138 android.hardware.power@1.1::types
-f79edf50a378a9c9bb737f93f205dab91b4c63ea49723afc6f856c138203ea81 android.hardware.radio@1.1::IRadio
-fcc5c8c88b85a9f63fba67d9e674da466c72a98ca287f343fb5721d098713f86 android.hardware.radio@1.1::IRadioIndication
-50f27e8c7ec009d5d4418b2ce8392b940bbf052ecc1d7251285f332485a5ba4e android.hardware.radio@1.1::IRadioResponse
-be981148c95c0089f3ae92854f0e7ae999d308e927db3e065f12a4fabe07852f android.hardware.radio@1.1::ISap
-d8d6bf7b4d36c04ce587df75953c3f723cfbe71c896c1aa8ab6478eae126723d android.hardware.radio@1.1::types
-d8aae01606bfd34bf2fb9a59cadc016f46f318e56cddb8f15a945c5b3c1222bc android.hardware.tetheroffload.config@1.0::IOffloadConfig
-447b00306bc95a7aafec1d660f6f3e9f76ac8bc0353193435e5579ab833da619 android.hardware.tetheroffload.control@1.0::IOffloadControl
-07658829339d75962016e00ed81b005ad29fca7ac12ad3bc3ccd86b08d94c2d3 android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
-0df5b0178af15c53cdce8fcf8ca14035e8e08db4fa76fdc12009ddbe0b53626b android.hardware.tetheroffload.control@1.0::types
-b30ef02ef26ff804e2f6acf1201bc141b59e134e6a0338562284491102cb13e3 android.hardware.usb@1.1::IUsb
-13a580e35af01270a1e9774177c51db51d8672e6139ba00851e654e68a4d7dff android.hardware.usb@1.1::IUsbCallback
-f0ed667288908c08fced570bd1f3c4a0f236aa927938e805f0d9fece525da81e android.hardware.usb@1.1::types
-f95a1e85612f2d0d616eacd2eb63c52d10dfa889f165df57697c30e1f47b4785 android.hardware.vibrator@1.1::IVibrator
-246fb9d9e2b4800aeb0adc3cdbaa15d0321ebab54b7bd1ab87da5b67c7b0b064 android.hardware.vibrator@1.1::types
-9bc43413b80cd0c59a022e93da1448dcb82dd10c6dd31932df4659e4bdcb1368 android.hardware.weaver@1.0::IWeaver
-7728b0393a2ed9796537d4165c7d95407e9d8cb447a647b545fdfe06a28689e7 android.hardware.weaver@1.0::types
-bb7c96762d0aa3ddb874c8815bacdd3cbc8fb87ea2f82b928bc29e24a3593055 android.hardware.wifi.offload@1.0::IOffload
-c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardware.wifi.offload@1.0::IOffloadCallback
-b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
-c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
-b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
-
-# ABI preserving changes to HALs during Android O MR1 (Final Set)
-09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
-2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
-0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
-05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
-
-# HALs released in Android O MR1 (Final Set)
-044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
-c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
-b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
-bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
-e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
-63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
-bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
-4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
-0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
-b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
-a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
-86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
-503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
-619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
-93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
-f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
-953607822954435874f4b81686440a604e2a88cdd2d9164c6293f3d5772510d7 android.hardware.neuralnetworks@1.0::IPreparedModel
-73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
-246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
-f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
-c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
-
-# ABI preserving changes to HALs during Android P
-9e7a0b650d0e461ece2cfec0e1072abf8676f592b41a7fb48f01e88fc3c8f780 android.hardware.broadcastradio@1.0::types
-cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
-3902efc42097cba55f0655aa389e052ea70164e99ced1a6d1ef53dafc13f7650 android.hardware.camera.provider@2.4::ICameraProvider
-6fa9804a17a8bb7923a56bd10493a5483c20007e4c9026fd04287bee7c945a8c android.hardware.gnss@1.0::IGnssCallback
-fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
-251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
-4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-190ea4898809de6cf379afe318f5fa9564686157b24d9a2d7f5698b0c977d8b2 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-25892789b50eb673506b6c5a2cdab5d9aa428d41608aab10280cc898538b524a android.hardware.graphics.composer@2.1::IComposerClient
-e205dd30f5ff99445b706a901de8ebc46c379e9d7c1921d6a327ed2082cfa83d android.hardware.graphics.composer@2.1::types
-a46251718abfada458dc64c41ce94915757bf6c87cfa2d9e99cfb01fa8e32331 android.hardware.graphics.mapper@2.0::IMapper
-bd33ac23c57b4a07632691d2191bc2c93930f57e62f4ccf459748fdaa5c0f480 android.hardware.graphics.mapper@2.0::types
-ad8a28ca3a5549fb9bc24cf5f80ac8f660cc27be885210d76266780aa52ddb8d android.hardware.keymaster@3.0::types
-5804ca86611d72e5481f022b3a0c1b334217f2e4988dad25730c42af2d1f4d1c android.hardware.neuralnetworks@1.0::IDevice
-12e8dca4ab7d8aadd0ef8f1b438021938e2396139e85db2ed65783b08800aa52 android.hardware.neuralnetworks@1.0::IExecutionCallback
-86b77e06da756a76aa3685be88765852dd982a86d8c90b8b4fc1130ed4184c8f android.hardware.neuralnetworks@1.0::types
-d4840db8efabdf1e4b344fc981cd36e5fe81a39aff6e199f6d06c1c8da413efd android.hardware.radio@1.0::types
-f96cbc59dfe16c8d0c2a7e06db24d8738a6328b6e90f7b8e1640ea2b4600debd android.hardware.radio@1.1::ISap
-2d86929794795e5c70f4fdb5073485fd05835c9c6f496116687c3d9f32e6df3e android.hardware.radio@1.2::ISap
-905a4af79c8329b39d8b11b08f015137216bb078b427b6986f32884a04bc1bec android.hardware.tv.cec@1.0::types
-aebcd9ff2da05c9d4c439916f40dfd219ba7629919007cb981ebf150064b4f82 android.hardware.usb@1.1::IUsb
-e29fb1941b40a990676f8e9c676a38761defd890b81a9c034608eb7ba6496023 android.hardware.wifi@1.0::IWifiP2pIface
-b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
-
-# HALs released in Android P
-5860cf040a3d5d771967ecf648b00d06876a7120da985ee2b3e95d01f634dd20 android.hardware.audio@4.0::IDevice
-cf82a0249e918fdc657e189895e92d60af0491868477e82cdc30f6cab0ca2c65 android.hardware.audio@4.0::IDevicesFactory
-be3dc9baed45a0d330152eca3ca24fa419b375b20a41644c88d4fb46b72784d2 android.hardware.audio@4.0::IPrimaryDevice
-3e3acb70c4e6c7d578f511f4a44ee764ab9126f887a3bf65d523c42e40012bf6 android.hardware.audio@4.0::IStream
-d5de64e66b95f135dd42492250a309134b8227203ef3524440798c66b6f5a392 android.hardware.audio@4.0::IStreamIn
-888ac906461327fa0bd93854d5109be8c292a33afdb467164826970a8bd5b789 android.hardware.audio@4.0::IStreamOut
-15f6ae78e73344c8e7d68847ef03caec64fcd9f951bbcf59957d1712c247fcff android.hardware.audio@4.0::IStreamOutCallback
-61f0eaa4d08547d039e9b1dd7c82abe2c004286d1b9b8153c2491ff46a8a63ca android.hardware.audio@4.0::types
-5d47a2ad2c136b8aba067dd45bb10d0ad390dd76340764154f580658f98f4fe6 android.hardware.audio.common@4.0::types
-b04b6b364938b80008e61fa2e318bc299622433e57c2e1f6cfba332a3f6e3f15 android.hardware.audio.effect@4.0::IAcousticEchoCancelerEffect
-1c17d4ece5c8ba3f7a646a305ee0dd109b0d51372e1bd585812e513cd40e1852 android.hardware.audio.effect@4.0::IAutomaticGainControlEffect
-34174259fe6fbb1bb14e7103e097f2f25529271a676687845b2f55d6d0d9d617 android.hardware.audio.effect@4.0::IBassBoostEffect
-7a18e9bd0163f3784448f6e24be0db75f877e2f0f9bd0d7ec427f1c34b382c0b android.hardware.audio.effect@4.0::IDownmixEffect
-bac81bffbe2661d5b6839087d2dd3a27eded66e60c6c76d35c68d54014cd5c06 android.hardware.audio.effect@4.0::IEffect
-65f0bcf9e498b26f3266ad10cf513a6c2b5906cc49f9db4bc5c7d3ba11a72e05 android.hardware.audio.effect@4.0::IEffectBufferProviderCallback
-5a746e81175489eb2371b88864c36c9bb63bc64ef799fae74cd96003b013c0d1 android.hardware.audio.effect@4.0::IEffectsFactory
-839980c7c5be79da6b95fdb9354a62b04407b4b084749b7a21d2c340773d7638 android.hardware.audio.effect@4.0::IEnvironmentalReverbEffect
-2805fbdac7cff050a1c095b9276bb41ac02a3b7b354336817487eb9a4b6bb462 android.hardware.audio.effect@4.0::IEqualizerEffect
-a91b547f5922f39fe4231d97fac1c3825c1c1b0c8ef7a5136689ceed37e8bfe9 android.hardware.audio.effect@4.0::ILoudnessEnhancerEffect
-1145f5b921ddec184fda5bdc87487b46f2a89cd9f42cc882bbb3a54f4ac80466 android.hardware.audio.effect@4.0::INoiseSuppressionEffect
-3661fa0623056922fdc4235ac5a9c91a2d066ab6f1ab4297e3b240fe302ba500 android.hardware.audio.effect@4.0::IPresetReverbEffect
-e88e520f8c98a62fccd8d5316c6687808f775de145d1405a7a9a66587ee6a001 android.hardware.audio.effect@4.0::IVirtualizerEffect
-fe28829dab10d171783b79ac9cc45412739f8ff275e90228d7c6370ef189b859 android.hardware.audio.effect@4.0::IVisualizerEffect
-21c8a702579356480236c6851b5b2c16b9bd369ce12bdd6ffdc4626a89f34f73 android.hardware.audio.effect@4.0::types
-42a06dc288f61b0690580f3d37b30b663c31d74d50bb58d0772386b550d5faab android.hardware.authsecret@1.0::IAuthSecret
-32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
-ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
-27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
-3d8ed67d807e9f15d0708390a416bee00920f6a22196c104cc9e443c8d217df8 android.hardware.broadcastradio@2.0::IAnnouncementListener
-44017c42e6f4d8cb30f07eb1da04540a98736a336ac28c7e0ed2e69e1589f8d1 android.hardware.broadcastradio@2.0::IBroadcastRadio
-e5f4960290b4f3089163dd43251e1a032c81e9bdb796e75a87fc7c5810c262b3 android.hardware.broadcastradio@2.0::ICloseHandle
-af24b87ca8b8f02fcde205e47db6a9609fc7e9d77d73e694ec8f9c508ca19575 android.hardware.broadcastradio@2.0::ITunerCallback
-d70464c517a4a1b5167730843775a97f455102919e945b04f717b9da390c0f39 android.hardware.broadcastradio@2.0::ITunerSession
-2afa59ebf8145e7fbc090cf49605c27280c07d4178d47cd7f9d82b3b95a47af0 android.hardware.broadcastradio@2.0::types
-4fb0725c36ed4f77a42b42e3f18d8b5f7919cb62b90098b23143a555aa7dd96d android.hardware.camera.device@3.4::ICameraDeviceCallback
-812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
-cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
-f9278c8beb9d42d96e26d73ecabe1dff1d7e2fb301ab7f737d93e5ffae8d3312 android.hardware.camera.metadata@3.3::types
-f858091b10f7d5927be60573c06df4805275d37226bbb41a732190bfb81457ec android.hardware.configstore@1.1::ISurfaceFlingerConfigs
-5b0fb9842f8b0eb3730b93c30a7925290ab44763ab86bb493bfa58d0f2eeb369 android.hardware.configstore@1.1::types
-1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
-6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
-a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
-1fbf2d7e383632216aaaa1d972a21a618f55659263d2e6f0b309e3cb323b4b63 android.hardware.drm@1.1::ICryptoFactory
-7877ff8e4c1e48b825e6e5e66d050288e5656ed535c61cc7830a92ed4a9e1990 android.hardware.drm@1.1::IDrmFactory
-fef2f0ebde7704548fb203df46673ceb342272fc4fa9d0af25a980d2584a36e7 android.hardware.drm@1.1::IDrmPlugin
-5047a346ecce239404b9020959f60dd467318e9c17b290a6386bc3894df62c3c android.hardware.drm@1.1::types
-a830336ac8627d6432cfafb1b884343ad9f885dee0a5323e380e6d3c519156b8 android.hardware.gnss@1.1::IGnss
-8ad55bc35bb3a83e65c018bdfde7ae5ebc749ff2bf6b79412ded0bc6c89b97d8 android.hardware.gnss@1.1::IGnssCallback
-3c5183d7506010be57e0f748e3640fc2ded1ba955784b6256ba427f4c399591c android.hardware.gnss@1.1::IGnssConfiguration
-1a07d1383e847c3deb696ec7a2c9e33b9683772945660448a010b18063da67a4 android.hardware.gnss@1.1::IGnssMeasurement
-83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback
-0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types
-7d2cef99c838fb58038de8bbfd3cdb76ff4797241987077721715297f8d45e34 android.hardware.graphics.common@1.1::types # b/78135149
-d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer
-a2f183f7fcc79aabedaef11095ab223aac0ed5ef984d850893872515e7f560c7 android.hardware.graphics.composer@2.2::IComposerClient
-dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper
-675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth
-434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback
-c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types
-201f9723353fdbd40bf3705537fb7e015e4c399879425e68688fe0f43606ea4d android.hardware.keymaster@4.0::IKeymasterDevice
-1b7d2090c0a28b229d37c4b96160796b1f0d703950ac6ccc163fccd280830503 android.hardware.keymaster@4.0::types
-6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor
-b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager
-4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection
-6aef1218e5949f867b0104752ac536c1b707222a403341720de90141df129e3e android.hardware.media.bufferpool@1.0::types
-7698dc2382a2eeb43541840e3ee624f34108efdfb976b2bfa7c13ef15fb8c4c4 android.hardware.neuralnetworks@1.1::IDevice
-72cc6126632456e8fbb8776fe50150c3c4dd5d09145653193affb70785211dfa android.hardware.neuralnetworks@1.1::types
-8d3d86da0bfa4bf070970d8303c659f67f35d670c287d45a3f542e4fedadd578 android.hardware.nfc@1.1::INfc
-e85f566698d2a2c28100e264fcf2c691a066756ddf8dd341d009ff50cfe10614 android.hardware.nfc@1.1::INfcClientCallback
-5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types
-163e115e833fc1d77cdd4a8cf0c833bb8b8d74fe35c880fe693101d17774926f android.hardware.power@1.2::IPower
-7899b9305587b2d5cd74a3cc87e9090f58bf4ae74256ce3ee36e7ec011822840 android.hardware.power@1.2::types
-5a464e6db53fad223986d655028a18185b73db8e2bfa9663f9042c9623eb0aa0 android.hardware.power@1.3::IPower
-a54a28d39b892d27a3cb06829181c038edcdd9e8eef359543b01e4313ae59aa0 android.hardware.power@1.3::types
-ab132c990a62f0aca35871c092c22fb9c85d478e22124ef6a4d0a2302da76a9f android.hardware.radio@1.2::IRadio
-cda752aeabaabc20486a82ac57a3dd107785c006094a349bc5e224e8aa22a17c android.hardware.radio@1.2::IRadioIndication
-da8c6ae991c6a4b284cc6e445332e064e28ee8a09482ed5afff9d159ec6694b7 android.hardware.radio@1.2::IRadioResponse
-b65332996eb39ba63300a1011404141fa59ce5c252bc17afae637be6eeca5f55 android.hardware.radio@1.2::ISap
-a9361522cc97ef66209d39ba324095b2f08344054bb4d3481e803eee0480623a android.hardware.radio@1.2::types
-87385469cf4409f0f33b01508e7a477cf71f2a11e466dd7e3ab5971a1baaa72b android.hardware.radio.config@1.0::IRadioConfig
-228b2ee3c8c276c9f0afad2dc313ca3d6bbd9e482ddf313c7204c60ad9b636ab android.hardware.radio.config@1.0::IRadioConfigIndication
-a2e9b7aa09f79426f765838174e04b6f9a3e6c8b76b923fc1705632207bad44b android.hardware.radio.config@1.0::IRadioConfigResponse
-4307696b64ded9bd8de06887f9dfc533e875c4e0d83b8008df4d705164bde0b1 android.hardware.radio.config@1.0::types
-bd7699f07ba5392310fefd33ea964e01f4f4a66015146845c85055004823cc81 android.hardware.secure_element@1.0::ISecureElement
-a65aa82bbe48d81a9ae9e86247bb1b89fd2d3138d4053d7a5b716c71149b7dee android.hardware.secure_element@1.0::ISecureElementHalCallback
-2984c069f48ba35cd1bf49b0e17daad0d418fef52cb7a4a84dba0043114063d4 android.hardware.secure_element@1.0::types
-b4f507b4dc9b5cd5f0e4445926acb7d94525ae60dc307b3951142283632207b6 android.hardware.soundtrigger@2.1::ISoundTriggerHw
-92c2cc0f06ef744c5bda21f1d660258f7937203109b493eee22c3f3e2dbb0d3e android.hardware.soundtrigger@2.1::ISoundTriggerHwCallback
-8ddfa7542772cc7bca19972b2d856264efa31914bfd098aeb7c2079d950194cb android.hardware.usb.gadget@1.0::IUsbGadget
-ad0a620cda08f01b151c30cb7afa23b0637cc84340cf8dec00ac8e32cf54a8db android.hardware.usb.gadget@1.0::IUsbGadgetCallback
-51fc20f223561ac3a32ace3217837ef3860265bd91c8b7ae3859532caef9bc39 android.hardware.usb.gadget@1.0::types
-1bfc9fd9536ed09f04bcaf222a332bc919f1565d4d08bddccdebe1bfca8f01b5 android.hardware.vibrator@1.2::IVibrator
-a0aefa29881235c21e4761d15c55edc35ef85c2e0d9e01d0966176d1dbf5f811 android.hardware.vibrator@1.2::types
-8bc75a0dfac15c6f87ffec950b76c7d7de30d516b54e8e0b1f3c0ff9c7c6873b android.hardware.wifi@1.2::IWifi
-780c16fdeda13b779d993953a67f7ca578c938a172a9424c1c715ae81bc40fd7 android.hardware.wifi@1.2::IWifiChip
-167af870fdb87e1cbbaa0fa62ef35e1031caad20dd1ba695983dedb1e9993486 android.hardware.wifi@1.2::IWifiChipEventCallback
-8c7ef32fc78d5ec6e6956de3784cc2c6f42614b5272d2e461f6d60534ba38ec2 android.hardware.wifi@1.2::IWifiNanIface
-1e6074efad9da333803fb7c1acdb719d51c30b2e1e92087b0420341631c30b60 android.hardware.wifi@1.2::IWifiNanIfaceEventCallback
-f5682dbf19f712bef9cc3faa5fe3dc670b6ffbcb62a147a1d86b9d43574cd83f android.hardware.wifi@1.2::IWifiStaIface
-6db2e7d274be2dca9bf3087afd1f774a68c99d2b4dc7eeaf41690e5cebcbef7a android.hardware.wifi@1.2::types
-ee08280de21cb41e3ec26d6ed636c701b7f70516e71fb22f4fe60a13e603f406 android.hardware.wifi.hostapd@1.0::IHostapd
-b2479cd7a417a1cf4f3a22db4e4579e21bac38fdcaf381e2bf10176d05397e01 android.hardware.wifi.hostapd@1.0::types
-e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardware.wifi.supplicant@1.1::ISupplicant
-21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface
-cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
-10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
diff --git a/prebuilt_hashes/dump_hals_for_release.py b/prebuilt_hashes/dump_hals_for_release.py
deleted file mode 100755
index e9ed4c2..0000000
--- a/prebuilt_hashes/dump_hals_for_release.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 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.
-#
-
-"""
-Dump new HIDL types that are introduced in each dessert release.
-"""
-
-from __future__ import print_function
-
-import argparse
-import collections
-import json
-import os
-import re
-
-class Globals:
- pass
-
-class Constants:
- CURRENT = 'current'
- HAL_PATH_PATTERN = r'/((?:[a-zA-Z_][a-zA-Z0-9_]*/)*)(\d+\.\d+)/([a-zA-Z_][a-zA-Z0-9_]*).hal'
- CURRENT_TXT_PATTERN = r'(?:.*/)?([0-9]+|current).txt'
-
-def trim_trailing_comments(line):
- idx = line.find('#')
- if idx < 0: return line
- return line[0:idx]
-
-def strip_begin(s, prefix):
- if s.startswith(prefix):
- return strip_begin(s[len(prefix):], prefix)
- return s
-
-def strip_end(s, suffix):
- if s.endswith(suffix):
- return strip_end(s[0:-len(suffix)], suffix)
- return s
-
-def get_interfaces(file_name):
- with open(file_name) as file:
- for line in file:
- line_tokens = trim_trailing_comments(line).strip().split()
- if not line_tokens:
- continue
- assert len(line_tokens) == 2, \
- "Unrecognized line in file {}:\n{}".format(file_name, line)
- yield line_tokens[1]
-
-def api_level_to_int(api_level):
- try:
- if api_level == Constants.CURRENT: return float('inf')
- return int(api_level)
- except ValueError:
- return None
-
-def get_interfaces_from_package_root(package, root):
- root = strip_end(root, '/')
- for dirpath, _, filenames in os.walk(root, topdown=False):
- dirpath = strip_begin(dirpath, root)
- for filename in filenames:
- filepath = os.path.join(dirpath, filename)
- mo = re.match(Constants.HAL_PATH_PATTERN, filepath)
- if not mo:
- continue
- yield '{}.{}@{}::{}'.format(
- package, mo.group(1).strip('/').replace('/', '.'), mo.group(2), mo.group(3))
-
-def filter_out(iterable):
- return iterable if not Globals.filter_out else filter(
- lambda s: all(re.search(pattern, s) is None for pattern in Globals.filter_out),
- iterable)
-
-def main():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument('--pretty', help='Print pretty JSON', action='store_true')
- parser.add_argument('--package-root', metavar='PACKAGE:PATH', nargs='*',
- help='package root of current directory, e.g. android.hardware:hardware/interfaces')
- parser.add_argument('--filter-out', metavar='REGEX', nargs='*',
- help='A regular expression that filters out interfaces.')
- parser.add_argument('hashes', metavar='FILE', nargs='*',
- help='Locations of current.txt for each release.')
- parser.parse_args(namespace=Globals)
-
- interfaces_for_level = dict()
-
- for filename in Globals.hashes or tuple():
- mo = re.match(Constants.CURRENT_TXT_PATTERN, filename)
- assert mo is not None, \
- 'Input hash file names must have the format {} but is {}'.format(Constants.CURRENT_TXT_PATTERN, filename)
-
- api_level = mo.group(1)
- assert api_level_to_int(api_level) is not None
-
- if api_level not in interfaces_for_level:
- interfaces_for_level[api_level] = set()
- interfaces_for_level[api_level].update(filter_out(get_interfaces(filename)))
-
- for package_root in Globals.package_root or tuple():
- tup = package_root.split(':')
- assert len(tup) == 2, \
- '--package-root must have the format PACKAGE:PATH, but is {}'.format(package_root)
- if Constants.CURRENT not in interfaces_for_level:
- interfaces_for_level[Constants.CURRENT] = set()
- interfaces_for_level[Constants.CURRENT].update(filter_out(get_interfaces_from_package_root(*tup)))
-
- seen_interfaces = set()
- new_interfaces_for_level = collections.OrderedDict()
- for level, interfaces in sorted(interfaces_for_level.items(), key=lambda tup: api_level_to_int(tup[0])):
- if level != Constants.CURRENT:
- removed_interfaces = seen_interfaces - interfaces
- assert not removed_interfaces, \
- "The following interfaces are removed from API level {}:\n{}".format(
- level, removed_interfaces)
- new_interfaces_for_level[level] = sorted(interfaces - seen_interfaces)
- seen_interfaces.update(interfaces)
-
- print(json.dumps(new_interfaces_for_level,
- separators=None if Globals.pretty else (',',':'),
- indent=4 if Globals.pretty else None))
-
-if __name__ == '__main__':
- main()
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index 6765b4d..f3cc2e0 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index 8393cf5..cafa5a6 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -166,11 +166,15 @@
};
enum CardState : int32_t {
+ /* card is physically absent from device. (Some old modems use CardState.ABSENT when the SIM
+ is powered off. This is no longer correct, however the platform will still support this
+ legacy behavior.) */
ABSENT,
+ /* card is inserted in the device */
PRESENT,
ERROR,
- RESTRICTED, // card is present but not usable due to carrier
- // restrictions
+ /* card is present but not usable due to carrier restrictions */
+ RESTRICTED,
};
enum PinState : int32_t {
@@ -1890,8 +1894,8 @@
};
struct CarrierRestrictions {
- vec<Carrier> allowedCarriers; // whitelist for allowed carriers
- vec<Carrier> excludedCarriers; // blacklist for explicitly excluded carriers
+ vec<Carrier> allowedCarriers; // Allowed carriers
+ vec<Carrier> excludedCarriers; // Explicitly excluded carriers
// which match allowed_carriers. Eg. allowedCarriers
// match mcc/mnc, excludedCarriers has same mcc/mnc and
// gid1 is ABCD. It means except the carrier whose gid1
diff --git a/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp b/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
index 9d61b52..2d0fe4b 100644
--- a/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
+++ b/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <radio_hidl_hal_utils_v1_0.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_0::IRadio::descriptor)),
diff --git a/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp b/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
index b80b971..c7ffa90 100644
--- a/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
+++ b/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <sap_hidl_hal_utils.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SapHidlTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, SapHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_0::ISap::descriptor)),
diff --git a/radio/1.1/Android.bp b/radio/1.1/Android.bp
index 28388b0..b325015 100644
--- a/radio/1.1/Android.bp
+++ b/radio/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
diff --git a/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp b/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
index 98dbf62..53d4d21 100644
--- a/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
+++ b/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <radio_hidl_hal_utils_v1_1.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_1);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_1,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_1::IRadio::descriptor)),
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index 28e6b26..0a4caf1 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
diff --git a/radio/1.2/default/Radio.cpp b/radio/1.2/default/Radio.cpp
index 73512e4..28a815f 100644
--- a/radio/1.2/default/Radio.cpp
+++ b/radio/1.2/default/Radio.cpp
@@ -52,16 +52,16 @@
/**
* IRadio-defined request is called from the client and talk to the radio to get
* IRadioResponse-defined response or/and IRadioIndication-defined indication back to the
- * client. This dummy implementation omits and replaces the design and implementation of vendor
+ * client. This implementation omits and replaces the design and implementation of vendor
* codes that needs to handle the receipt of the request and the return of the response from the
- * radio; this just directly returns a dummy response back to the client.
+ * radio; this just directly returns a fake response back to the client.
*/
ALOGD("Radio Request: getIccCardStatus is entering");
if (mRadioResponse != nullptr || mRadioResponseV1_1 != nullptr ||
mRadioResponseV1_2 != nullptr) {
- // Dummy RadioResponseInfo as part of response to return in 1.0, 1.1 and 1.2
+ // Fake RadioResponseInfo as part of response to return in 1.0, 1.1 and 1.2
::android::hardware::radio::V1_0::RadioResponseInfo info;
info.serial = serial;
info.type = ::android::hardware::radio::V1_0::RadioResponseType::SOLICITED;
@@ -72,7 +72,7 @@
* return getIccCardStatusResponse.
*/
if (mRadioResponseV1_2 != nullptr) {
- // Dummy CardStatus as part of getIccCardStatusResponse_1_2 response to return
+ // Fake CardStatus as part of getIccCardStatusResponse_1_2 response to return
::android::hardware::radio::V1_2::CardStatus card_status;
card_status.base.cardState = ::android::hardware::radio::V1_0::CardState::ABSENT;
card_status.base.gsmUmtsSubscriptionAppIndex = 0;
@@ -80,7 +80,7 @@
mRadioResponseV1_2->getIccCardStatusResponse_1_2(info, card_status);
ALOGD("Radio Response: getIccCardStatusResponse_1_2 is sent");
} else if (mRadioResponseV1_1 != nullptr) {
- // Dummy CardStatus as part of getIccCardStatusResponse response to return
+ // Fake CardStatus as part of getIccCardStatusResponse response to return
::android::hardware::radio::V1_0::CardStatus card_status_V1_0;
card_status_V1_0.cardState = ::android::hardware::radio::V1_0::CardState::ABSENT;
card_status_V1_0.gsmUmtsSubscriptionAppIndex = 0;
@@ -88,7 +88,7 @@
mRadioResponseV1_1->getIccCardStatusResponse(info, card_status_V1_0);
ALOGD("Radio Response: getIccCardStatusResponse is sent");
} else {
- // Dummy CardStatus as part of getIccCardStatusResponse response to return
+ // Fake CardStatus as part of getIccCardStatusResponse response to return
::android::hardware::radio::V1_0::CardStatus card_status_V1_0;
card_status_V1_0.cardState = ::android::hardware::radio::V1_0::CardState::ABSENT;
card_status_V1_0.gsmUmtsSubscriptionAppIndex = 0;
diff --git a/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp b/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
index 400e394..1840c3e 100644
--- a/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
+++ b/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <radio_hidl_hal_utils_v1_2.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_2);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_2,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_2::IRadio::descriptor)),
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index b6af874..1c8e6c2 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
diff --git a/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp b/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
index 2622bbc..e6fd9f9 100644
--- a/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
+++ b/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <radio_hidl_hal_utils_v1_3.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_3);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_3,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_3::IRadio::descriptor)),
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index ff2e0d6..6c3a7d2 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
diff --git a/radio/1.4/vts/functional/AndroidTest.xml b/radio/1.4/vts/functional/AndroidTest.xml
index 9df8f9c..469e103 100644
--- a/radio/1.4/vts/functional/AndroidTest.xml
+++ b/radio/1.4/vts/functional/AndroidTest.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs VtsHalRadioV1_3TargetTest.">
+<configuration description="Runs VtsHalRadioV1_4TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
@@ -24,11 +24,11 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="VtsHalRadioV1_3TargetTest->/data/local/tmp/VtsHalRadioV1_3TargetTest" />
+ <option name="push" value="VtsHalRadioV1_4TargetTest->/data/local/tmp/VtsHalRadioV1_4TargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsHalRadioV1_3TargetTest" />
+ <option name="module-name" value="VtsHalRadioV1_4TargetTest" />
</test>
</configuration>
diff --git a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
index 23ec011..eadd6c7 100644
--- a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
+++ b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
@@ -19,6 +19,7 @@
#include <hidl/ServiceManagement.h>
#include <radio_hidl_hal_utils_v1_4.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_4);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_4,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::radio::V1_4::IRadio::descriptor)),
diff --git a/tests/bar/1.0/.hidl_for_test b/radio/1.5/.hidl_for_system_ext
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to radio/1.5/.hidl_for_system_ext
diff --git a/radio/1.5/Android.bp b/radio/1.5/Android.bp
index 06a2a6e..74de0fd 100644
--- a/radio/1.5/Android.bp
+++ b/radio/1.5/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio@1.5",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadio.hal",
@@ -22,4 +19,5 @@
"android.hidl.safe_union@1.0",
],
gen_java: true,
+ system_ext_specific: true,
}
diff --git a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
index 31466c5..d1461e3 100644
--- a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
+++ b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
@@ -16,6 +16,7 @@
#include <radio_hidl_hal_utils_v1_5.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_5);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_5,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
android::hardware::radio::V1_5::IRadio::descriptor)),
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 24b7fd5..7166654 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -437,6 +437,7 @@
TEST_P(RadioHidlTest_v1_5, togglingUiccApplicationsSimPresent) {
// This test case only test SIM ABSENT case.
if (cardStatus.base.base.base.cardState != CardState::PRESENT) return;
+ if (cardStatus.applications.size() == 0) return;
// Disable Uicc applications.
serial = GetRandomSerialNumber();
@@ -1265,7 +1266,7 @@
info.serviceType <= BarringInfo::ServiceType::OPERATOR_32));
reportedServices.insert(info.serviceType);
- // Any type that is "conditional" must have sane values for conditional barring
+ // Any type that is "conditional" must have valid values for conditional barring
// factor and time.
switch (info.barringType) {
case BarringInfo::BarringType::NONE: // fall through
@@ -1284,7 +1285,7 @@
// Certain types of barring are relevant for certain RANs. Ensure that only the right
// types are reported. Note that no types are required, simply that for a given technology
- // only certain types are valid. This is one way to sanity check that implementations are
+ // only certain types are valid. This is one way to check that implementations are
// not providing information that they don't have.
static const std::set<BarringInfo::ServiceType> UTRA_SERVICES{
BarringInfo::ServiceType::CS_SERVICE, BarringInfo::ServiceType::PS_SERVICE,
diff --git a/radio/1.6/Android.bp b/radio/1.6/Android.bp
new file mode 100644
index 0000000..fc3191f
--- /dev/null
+++ b/radio/1.6/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.radio@1.6",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IRadio.hal",
+ "IRadioIndication.hal",
+ "IRadioResponse.hal",
+ ],
+ interfaces: [
+ "android.hardware.radio@1.0",
+ "android.hardware.radio@1.1",
+ "android.hardware.radio@1.2",
+ "android.hardware.radio@1.3",
+ "android.hardware.radio@1.4",
+ "android.hardware.radio@1.5",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
new file mode 100644
index 0000000..8afbf22
--- /dev/null
+++ b/radio/1.6/IRadio.hal
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio@1.6;
+
+
+import @1.0::CdmaSmsMessage;
+import @1.0::GsmSmsMessage;
+import @1.1::CardPowerState;
+import @1.2::DataRequestReason;
+import @1.4::RadioAccessFamily;
+import @1.5::IRadio;
+import @1.5::AccessNetwork;
+import @1.5::DataProfileInfo;
+import @1.5::LinkAddress;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with @1.6::IRadioResponse and @1.6::IRadioIndication.
+ */
+interface IRadio extends @1.5::IRadio {
+ /**
+ * Toggle radio on and off (for "airplane" mode)
+ * If the radio is turned off/on the radio modem subsystem
+ * is expected return to an initialized state. For instance,
+ * any voice and data calls must be terminated and all associated
+ * lists emptied.
+ *
+ * When setting radio power on to exit from airplane mode to place an emergency call on this
+ * logical modem, powerOn, forEmergencyCall and preferredForEmergencyCall must be true. In
+ * this case, this modem is optimized to scan only emergency call bands, until:
+ * 1) Emergency call is completed; or
+ * 2) Another setRadioPower_1_5 is issued with forEmergencyCall being false or
+ * preferredForEmergencyCall being false; or
+ * 3) Timeout after 30 seconds if dial or emergencyDial is not called.
+ * Once one of these conditions is reached, the modem should move into normal operation.
+ *
+ * @param serial Serial number of request.
+ * @param powerOn To turn on radio -> on = true, to turn off radio -> on = false.
+ * @param forEmergencyCall To indication to radio if this request is due to emergency call.
+ * No effect if powerOn is false.
+ * @param preferredForEmergencyCall indicate whether the following emergency call will be sent
+ * on this modem or not. No effect if forEmergencyCall is false, or powerOn is false.
+ *
+ * Response callback is IRadioConfigResponse. setRadioPowerResponse_1_6.
+
+ * Note this API is the same as the 1.5
+ */
+ oneway setRadioPower_1_6(int32_t serial, bool powerOn, bool forEmergencyCall,
+ bool preferredForEmergencyCall);
+
+ /**
+ * Returns the data call list. An entry is added when a setupDataCall() is issued and removed
+ * on a deactivateDataCall(). The list is emptied when setRadioPower() off/on issued or when
+ * the vendor HAL or modem crashes.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioResponse.getDataCallListResponse_1_6()
+ */
+ oneway getDataCallList_1_6(int32_t serial);
+
+ /**
+ * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
+ * the data connection must be added to data calls and a unsolDataCallListChanged() must be
+ * sent. The call remains until removed by subsequent unsolDataCallIstChanged(). It may be
+ * lost due to many factors, including deactivateDataCall() being issued, the radio powered
+ * off, reception lost or even transient factors like congestion. This data call list is
+ * returned by getDataCallList() and dataCallListChanged().
+ *
+ * The Radio is expected to:
+ * - Create one data call context.
+ * - Create and configure a dedicated interface for the context.
+ * - The interface must be point to point.
+ * - The interface is configured with one or more addresses and is capable of sending and
+ * receiving packets. The format is IP address with optional "/" prefix length
+ * (The format is defined in RFC-4291 section 2.3). For example, "192.0.1.3",
+ * "192.0.1.11/16", or "2001:db8::1/64". Typically one IPv4 or one IPv6 or one of each. If
+ * the prefix length is absent, then the addresses are assumed to be point to point with
+ * IPv4 with prefix length 32 or IPv6 with prefix length 128.
+ * - Must not modify routing configuration related to this interface; routing management is
+ * exclusively within the purview of the Android OS.
+ * - Support simultaneous data call contexts up to DataRegStateResult.maxDataCalls specified
+ * in the response of getDataRegistrationState.
+ *
+ * @param serial Serial number of request.
+ * @param accessNetwork The access network to setup the data call. If the data connection cannot
+ * be established on the specified access network then it should be responded with an error.
+ * @param dataProfileInfo Data profile info.
+ * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
+ * @param reason The request reason. Must be DataRequestReason:NORMAL or
+ * DataRequestReason:HANDOVER.
+ * @param addresses If the reason is DataRequestReason:HANDOVER, this indicates the list of link
+ * addresses of the existing data connection. This parameter must be ignored unless reason
+ * is DataRequestReason:HANDOVER.
+ * @param dnses If the reason is DataRequestReason:HANDOVER, this indicates the list of DNS
+ * addresses of the existing data connection. The format is defined in RFC-4291 section 2.2.
+ * For example, "192.0.1.3" or "2001:db8::1". This parameter must be ignored unless reason
+ * is DataRequestReason:HANDOVER.
+ * @param pduSessionId The pdu session id to be used for this data call. A value of 0 means
+ * no pdu session id was attached to this call.
+ * Reference: 3GPP TS 24.007 section 11.2.3.1b
+ *
+ * Response function is IRadioResponse.setupDataCallResponse_1_6()
+ *
+ * Note this API is the same as the 1.5
+ */
+ oneway setupDataCall_1_6(int32_t serial, AccessNetwork accessNetwork,
+ DataProfileInfo dataProfileInfo, bool roamingAllowed,
+ DataRequestReason reason, vec<LinkAddress> addresses, vec<string> dnses,
+ int32_t pduSessionId);
+
+ /**
+ * Send an SMS message
+ *
+ * @param serial Serial number of request.
+ * @param message GsmSmsMessage as defined in types.hal
+ *
+ * Response function is IRadioResponse.sendSmsResponse_1_6()
+ *
+ * Note this API is the same as the 1.0
+ *
+ * Based on the return error, caller decides to resend if sending sms
+ * fails. RadioError:SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332)
+ * and RadioError:GENERIC_FAILURE means no retry (i.e. error cause is 500)
+ */
+ oneway sendSms_1_6(int32_t serial, GsmSmsMessage message);
+
+ /**
+ * Send an SMS message. Identical to sendSms_1_6,
+ * except that more messages are expected to be sent soon. If possible,
+ * keep SMS relay protocol link open (eg TS 27.005 AT+CMMS command)
+ *
+ * @param serial Serial number of request.
+ * @param message GsmSmsMessage as defined in types.hal
+ *
+ * Response function is IRadioResponse.sendSMSExpectMoreResponse_1_6()
+ *
+ * Note this API is the same as the 1.0
+ *
+ * Based on the return error, caller decides to resend if sending sms
+ * fails. RadioError:SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332)
+ * and RadioError:GENERIC_FAILURE means no retry (i.e. error cause is 500)
+ */
+ oneway sendSMSExpectMore_1_6(int32_t serial, GsmSmsMessage message);
+
+ /**
+ * Send a CDMA SMS message
+ *
+ * @param serial Serial number of request.
+ * @param sms Cdma Sms to be sent described by CdmaSmsMessage in types.hal
+ *
+ * Response callback is IRadioResponse.sendCdmaSmsResponse_1_6()
+ *
+ * Note this API is the same as the 1.0
+ *
+ */
+ oneway sendCdmaSms_1_6(int32_t serial, CdmaSmsMessage sms);
+
+ /**
+ * Send an SMS message. Identical to sendCdmaSms_1_6,
+ * except that more messages are expected to be sent soon.
+ *
+ * @param serial Serial number of request.
+ * @param sms Cdma Sms to be sent described by CdmaSmsMessage in types.hal
+ *
+ * Response callback is IRadioResponse.sendCdmaSMSExpectMoreResponse_1_6()
+ *
+ * Note this API is the same as the 1.5
+ *
+ */
+ oneway sendCdmaSmsExpectMore_1_6(int32_t serial, CdmaSmsMessage sms);
+
+ /**
+ * Set SIM card power state.
+ * Request is used to power off or power on the card. It should not generate
+ * a CardState.CARDSTATE_ABSENT indication, since the SIM is still physically
+ * inserted.
+ *
+ * @param serial Serial number of request
+ * @param powerUp POWER_DOWN if powering down the SIM card,
+ * POWER_UP if powering up the SIM card,
+ * POWER_UP_PASS_THROUGH if powering up the SIM card in
+ * pass through mode.
+ *
+ * When SIM card is in POWER_UP_PASS_THROUGH, the modem does not send
+ * any command to it (for example SELECT of MF, or TERMINAL
+ * CAPABILITY), and the SIM card is controlled completely by Telephony
+ * sending APDUs directly. The SIM card state must be
+ * RIL_CARDSTATE_PRESENT and the number of card apps will be 0.
+ * No new error code is generated. Emergency calls are supported in
+ * the same way as if the SIM card is absent.
+ * Pass-through mode is valid only for the specific card session where
+ * it is activated, and normal behavior occurs at the next SIM
+ * initialization, unless POWER_UP_PASS_THROUGH is requested again.
+ *
+ * The device is required to power down the SIM card before it can
+ * switch the mode between POWER_UP and POWER_UP_PASS_THROUGH.
+ * At device power up, the SIM interface is powered up automatically.
+ * Each subsequent request to this method is processed only after the
+ * completion of the previous one.
+ *
+ * Response callback is IRadioResponse.setSimCardPowerResponse_1_6().
+ * Note that this differs from setSimCardPower_1_1 in that the response
+ * callback should only be sent once the device has finished executing
+ * the request (the SIM has finished powering on or off).
+ */
+ oneway setSimCardPower_1_6(int32_t serial, CardPowerState powerUp);
+
+ /**
+ * Enable or disable E-UTRA-NR dual connectivity. If disabled then UE will not connect
+ * to secondary carrier.
+ *
+ * @param serial Serial number of request.
+ * @param nrDualConnectivityState expected NR dual connectivity state.
+ * 1. Enable NR dual connectivity {NrDualConnectivityState:ENABLE}
+ * 2. Disable NR dual connectivity {NrDualConnectivityState:DISABLE}
+ * 3. Disable NR dual connectivity and force secondary cell to be released
+ * {NrDualConnectivityState:DISABLE_IMMEDIATE}
+
+ * Response callback is IRadioResponse.setNRDualConnectivityStateResponse()
+ */
+ oneway setNrDualConnectivityState(int32_t serial,
+ NrDualConnectivityState nrDualConnectivityState);
+
+ /**
+ * Is E-UTRA-NR Dual Connectivity enabled
+ *
+ * @param serial Serial number of request.
+ * Response callback is IRadioResponse.isNRDualConnectivityEnabledResponse()
+ */
+ oneway isNrDualConnectivityEnabled(int32_t serial);
+
+ /**
+ * Reserves an unallocated pdu session id from the pool of ids.
+ *
+ * The allocated id is returned in the response.
+ *
+ * When the id is no longer needed, call releasePduSessionId to
+ * return it to the pool.
+ *
+ * Reference: 3GPP TS 24.007 section 11.2.3.1b
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioResponse.allocatePduSessionIdResponse()
+ */
+ oneway allocatePduSessionId(int32_t serial);
+
+ /**
+ * Releases a pdu session id that was previously allocated using
+ * allocatePduSessionId.
+ *
+ * Reference: 3GPP TS 24.007 section 11.2.3.1b
+ * @param serial Serial number of request.
+ * @param id Pdu session id to release.
+ *
+ * Response function is IRadioResponse.releasePduSessionIdResponse()
+ */
+ oneway releasePduSessionId(int32_t serial, int32_t id);
+
+ /**
+ * Indicates that a handover to the IWLAN transport has begun.
+ *
+ * Any resources being transferred to the IWlan transport cannot be released while a
+ * handover is underway. For example, if a pdu session id needs to be
+ * transferred to IWlan, then, the modem should not release the id while
+ * the handover is in progress.
+ *
+ * If a handover was unsuccessful, then the framework calls IRadio::cancelHandover.
+ * The modem retains ownership over any of the resources being transferred to IWlan.
+ *
+ * If a handover was successful, the framework calls IRadio::deactivateDataCall with reason
+ * HANDOVER. The IWlan transport now owns the transferred resources and is responsible for
+ * releasing them.
+ *
+ * @param serial Serial number of request.
+ * @param id callId The identifier of the data call which is provided in SetupDataCallResult
+ *
+ * Response function is IRadioResponse.startHandoverResponse()
+ */
+ oneway startHandover(int32_t serial, int32_t callId);
+
+ /**
+ * Indicates that a handover was cancelled after a call to IRadio::startHandover.
+ *
+ * Since the handover was unsuccessful, the modem retains ownership over any of the resources
+ * being transferred and is still responsible for releasing them.
+ *
+ * @param serial Serial number of request.
+ * @param id callId The identifier of the data call which is provided in SetupDataCallResult
+ *
+ * Response function is IRadioResponse.cancelHandoverResponse()
+ */
+ oneway cancelHandover(int32_t serial, int32_t callId);
+
+ /**
+ * Requests to set the network type for searching and registering.
+ *
+ * Instruct the radio to *only* accept the types of network provided. This
+ * is stronger than setPreferredNetworkType which is a suggestion.
+ *
+ * @param serial Serial number of request.
+ * @param networkTypeBitmap a 32-bit bearer bitmap of RadioAccessFamily
+ *
+ * Response callbask is IRadioResponse.setNetworkTypeBitmapResponse()
+ */
+ oneway setAllowedNetworkTypeBitmap(
+ uint32_t serial, bitfield<RadioAccessFamily> networkTypeBitmap);
+
+ /**
+ * Control data throttling at modem.
+ * - DataThrottlingAction:NO_DATA_THROTTLING should clear any existing
+ * data throttling within the requested completion window.
+ * - DataThrottlingAction:THROTTLE_SECONDARY_CARRIER: Remove any existing
+ * throttling on anchor carrier and achieve maximum data throttling on
+ * secondary carrier within the requested completion window.
+ * - DataThrottlingAction:THROTTLE_ANCHOR_CARRIER: disable secondary
+ * carrier and achieve maximum data throttling on anchor carrier by
+ * requested completion window.
+ * - DataThrottlingAction:HOLD: Immediately hold on to current level of
+ * throttling.
+ *
+ * @param serial Serial number of request.
+ * @param dataThrottlingAction DataThrottlingAction as defined in types.hal
+ * @param completionWindowSecs window, in seconds, in which the requested
+ * throttling action has to be achieved. This must be 0 when
+ * dataThrottlingAction is DataThrottlingAction:HOLD.
+ *
+ * Response function is IRadioResponse.setDataThrottlingResponse()
+ */
+ oneway setDataThrottling(int32_t serial,
+ DataThrottlingAction dataThrottlingAction,
+ int32_t completionWindowSecs);
+};
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
new file mode 100644
index 0000000..f195c0e
--- /dev/null
+++ b/radio/1.6/IRadioIndication.hal
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio@1.6;
+
+import @1.0::RadioIndicationType;
+import @1.5::IRadioIndication;
+import @1.6::SetupDataCallResult;
+import @1.6::LinkCapacityEstimate;
+
+/**
+ * Interface declaring unsolicited radio indications.
+ */
+interface IRadioIndication extends @1.5::IRadioIndication {
+
+ /**
+ * Indicates data call contexts have changed.
+ *
+ * This indication is updated from IRadioIndication@1.5 to report the @1.6 version of
+ * SetupDataCallResult.
+ *
+ * @param type Type of radio indication
+ * @param dcList Array of SetupDataCallResult identical to that returned by
+ * IRadio.getDataCallList(). It is the complete list of current data contexts including
+ * new contexts that have been activated. A data call is only removed from this list
+ * when any of the below conditions is matched.
+ * 1. The framework sends a IRadio.deactivateDataCall().
+ * 2. The radio is powered off/on.
+ * 3. Unsolicited disconnect from either modem or network side.
+ */
+ oneway dataCallListChanged_1_6(RadioIndicationType type, vec<SetupDataCallResult> dcList);
+
+ /**
+ * The modem can explicitly set SetupDataCallResult::suggestedRetryTime after a failure in
+ * IRadio@1.6::SetupDataCall. During that time, no new calls are allowed to
+ * IRadio@1.6::SetupDataCall that use the same APN.
+ *
+ * When IRadioIndication@1.6::unthrottleApn is sent, AOSP will no longer throttle calls
+ * to IRadio@1.6::SetupDataCall for the given APN.
+ *
+ * @param type Type of radio indication
+ * @param apn Apn to unthrottle
+ */
+ oneway unthrottleApn(RadioIndicationType type, string apn);
+
+ /**
+ * Indicates current link capacity estimate.
+ * This replaces @1.2::IRadioIndication.currentLinkCapacityEstimate().
+ * This indication is sent whenever the reporting criteria, as set by
+ * @1.2::IRadio.setLinkCapacityReportingCriteria, are met and the indication is not
+ * suppressed by @1.2::IRadio.setIndicationFilter_1_2().
+ *
+ * @param type Type of radio indication
+ * @param lce LinkCapacityEstimate
+ */
+ oneway currentLinkCapacityEstimate_1_6(RadioIndicationType type, LinkCapacityEstimate lce);
+};
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
new file mode 100644
index 0000000..5a71c1f
--- /dev/null
+++ b/radio/1.6/IRadioResponse.hal
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio@1.6;
+
+import @1.0::SendSmsResult;
+import @1.6::RadioResponseInfo;
+import @1.5::IRadioResponse;
+import @1.6::SetupDataCallResult;
+
+/**
+ * Interface declaring response functions to solicited radio requests.
+ */
+interface IRadioResponse extends @1.5::IRadioResponse {
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:RF_HARDWARE_ISSUE
+ * RadioError:NO_RF_CALIBRATION_INFO
+ */
+ oneway setRadioPowerResponse_1_6(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dcResponse SetupDataCallResult defined in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE must be returned on both success and failure of setup with the
+ * DataCallResponse.status containing the actual status
+ * For all other errors the DataCallResponse is ignored.
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:OP_NOT_ALLOWED_BEFORE_REG_TO_NW
+ * RadioError:OP_NOT_ALLOWED_DURING_VOICE_CALL
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES if the vendor is unable handle due to resources
+ * are full.
+ * RadioError:SIM_ABSENT
+ */
+ oneway setupDataCallResponse_1_6(RadioResponseInfo info, SetupDataCallResult dcResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dcResponse List of SetupDataCallResult as defined in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:SIM_ABSENT
+ */
+ oneway getDataCallListResponse_1_6(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param sms Response to sms sent as defined by SendSmsResult in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SMS_SEND_FAIL_RETRY
+ * RadioError:NETWORK_REJECT
+ * RadioError:INVALID_STATE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_MEMORY
+ * RadioError:REQUEST_RATE_LIMITED
+ * RadioError:INVALID_SMS_FORMAT
+ * RadioError:SYSTEM_ERR
+ * RadioError:ENCODING_ERR
+ * RadioError:INVALID_SMSC_ADDRESS
+ * RadioError:MODEM_ERR
+ * RadioError:NETWORK_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_MODEM_STATE
+ * RadioError:NETWORK_NOT_READY
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
+ * RadioError:ACCESS_BARRED
+ * RadioError:BLOCKED_DUE_TO_CALL
+ */
+ oneway sendSmsResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param sms Response to sms sent as defined by SendSmsResult in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SMS_SEND_FAIL_RETRY
+ * RadioError:NETWORK_REJECT
+ * RadioError:INVALID_STATE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_MEMORY
+ * RadioError:REQUEST_RATE_LIMITED
+ * RadioError:INVALID_SMS_FORMAT
+ * RadioError:SYSTEM_ERR
+ * RadioError:FDN_CHECK_FAILURE
+ * RadioError:ENCODING_ERR
+ * RadioError:INVALID_SMSC_ADDRESS
+ * RadioError:MODEM_ERR
+ * RadioError:NETWORK_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_MODEM_STATE
+ * RadioError:NETWORK_NOT_READY
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
+ * RadioError:ACCESS_BARRED
+ * RadioError:BLOCKED_DUE_TO_CALL
+ */
+ oneway sendSMSExpectMoreResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param sms Sms result struct as defined by SendSmsResult in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:SMS_SEND_FAIL_RETRY
+ * RadioError:NETWORK_REJECT
+ * RadioError:INVALID_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:REQUEST_RATE_LIMITED
+ * RadioError:INVALID_SMS_FORMAT
+ * RadioError:SYSTEM_ERR
+ * RadioError:FDN_CHECK_FAILURE
+ * RadioError:MODEM_ERR
+ * RadioError:NETWORK_ERR
+ * RadioError:ENCODING_ERR
+ * RadioError:INVALID_SMSC_ADDRESS
+ * RadioError:INTERNAL_ERR
+ * RadioError:SYSTEM_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:ENCODING_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
+ * RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+ * RadioError:ACCESS_BARRED
+ * RadioError:BLOCKED_DUE_TO_CALL
+ */
+ oneway sendCdmaSmsResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param sms Response to sms sent as defined by SendSmsResult in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SMS_SEND_FAIL_RETRY
+ * RadioError:NETWORK_REJECT
+ * RadioError:INVALID_STATE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_MEMORY
+ * RadioError:REQUEST_RATE_LIMITED
+ * RadioError:INVALID_SMS_FORMAT
+ * RadioError:SYSTEM_ERR
+ * RadioError:FDN_CHECK_FAILURE
+ * RadioError:ENCODING_ERR
+ * RadioError:INVALID_SMSC_ADDRESS
+ * RadioError:MODEM_ERR
+ * RadioError:NETWORK_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_MODEM_STATE
+ * RadioError:NETWORK_NOT_READY
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
+ * RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+ * RadioError:ACCESS_BARRED
+ * RadioError:BLOCKED_DUE_TO_CALL
+ */
+ oneway sendCdmaSmsExpectMoreResponse_1_6(RadioResponseInfo info, SendSmsResult sms);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:SIM_ERR (indicates a timeout or other issue making the SIM unresponsive)
+ *
+ * Note that this differs from setSimCardPowerResponse_1_1 in that the response
+ * should only be sent once the request from setSimCardPower_1_6 is complete
+ * (the SIM has finished powering on or off).
+ */
+ oneway setSimCardPowerResponse_1_6(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway setNrDualConnectivityStateResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * @param isEnabled Indicates whether NR dual connectivity is enabled or not, True if enabled
+ * else false.
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ oneway isNrDualConnectivityEnabledResponse(RadioResponseInfo info, bool isEnabled);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param id The allocated id. On an error, this is set to 0.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES- Indicates that no pdu session ids are available
+ * RadioError:REQUEST_NOT_SUPPORTED
+ */
+ oneway allocatePduSessionIdResponse(RadioResponseInfo info, int32_t id);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:REQUEST_NOT_SUPPORTED
+ */
+ oneway releasePduSessionIdResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_CALL_ID
+ */
+ oneway startHandoverResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param dcResponse Attributes of data call
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_CALL_ID
+ */
+ oneway cancelHandoverResponse(RadioResponseInfo info);
+
+ /**
+ * Callback of IRadio.setAllowedNetworkTypeBitmap(int, bitfield<RadioAccessFamily>)
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:MODE_NOT_SUPPORTED
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:MODEM_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:NO_RESOURCES
+ */
+ oneway setAllowedNetworkTypeBitmapResponse(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:MODEM_ERR
+ * RadioError:INVALID_ARGUMENTS
+ */
+ oneway setDataThrottlingResponse(RadioResponseInfo info);
+};
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
new file mode 100644
index 0000000..556d8a3
--- /dev/null
+++ b/radio/1.6/types.hal
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio@1.6;
+
+import @1.0::RadioError;
+import @1.0::RadioResponseType;
+import @1.4::DataCallFailCause;
+import @1.4::DataConnActiveStatus;
+import @1.4::PdpProtocolType;
+import @1.5::LinkAddress;
+
+import android.hidl.safe_union@1.0::Monostate;
+
+struct QosBandwidth {
+ /** Maximum bit rate possible on the bearer */
+ int32_t maxBitrateKbps;
+ /** Minimum bit rate that is guaranteed to be provided by the network */
+ int32_t guaranteedBitrateKbps;
+};
+
+/** LTE/EPS Quality of Service parameters as per 3gpp spec 24.301 sec 9.9.4.3. */
+struct EpsQos {
+ /**
+ * Quality of Service Class Identifier (QCI), see 3GPP TS 23.203 and 29.212.
+ * The allowed values are standard values(1-9, 65-68, 69-70, 75, 79-80, 82-85)
+ * defined in the spec and operator specific values in the range 128-254.
+ */
+ uint16_t qci;
+ QosBandwidth downlink;
+ QosBandwidth uplink;
+};
+
+/** 5G Quality of Service parameters as per 3gpp spec 24.501 sec 9.11.4.12 */
+struct NrQos {
+ /**
+ * 5G QOS Identifier (5QI), see 3GPP TS 24.501 and 23.501.
+ * The allowed values are standard values(1-9, 65-68, 69-70, 75, 79-80, 82-85)
+ * defined in the spec and operator specific values in the range 128-254.
+ */
+ uint16_t fiveQi;
+ QosBandwidth downlink;
+ QosBandwidth uplink;
+ /**
+ * QOS flow identifier of the QOS flow description in the
+ * range of QosFlowIdRange::MIN to QosFlowIdRange::MAX
+ */
+ uint8_t qfi;
+ uint16_t averagingWindowMs;
+};
+
+/** Allowed values for 5G QOS flow identifier */
+enum QosFlowIdRange : uint8_t {
+ MIN = 1,
+ MAX = 63
+};
+
+/** EPS or NR QOS parameters */
+safe_union Qos {
+ Monostate noinit;
+ EpsQos eps;
+ NrQos nr;
+};
+
+/**
+ * Next header protocol numbers defined by IANA, RFC 5237
+ */
+enum QosProtocol : int32_t {
+ /** No protocol specified */
+ UNSPECIFIED = -1,
+ /** Transmission Control Protocol */
+ TCP = 6,
+ /** User Datagram Protocol */
+ UDP = 17,
+ /** Encapsulating Security Payload Protocol */
+ ESP = 50,
+ /** Authentication Header */
+ AH = 51,
+};
+
+enum QosFilterDirection : int32_t {
+ DOWNLINK = 0,
+ UPLINK = 1,
+ BIDIRECTIONAL = 2,
+};
+
+/** Allowed port numbers */
+enum QosPortRange : int32_t {
+ MIN = 20,
+ MAX = 65535
+};
+
+enum RadioError : @1.0::RadioError {
+ /** 1X voice and SMS are not allowed simulteneously. */
+ SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67,
+
+ /** Access is barred. */
+ ACCESS_BARRED = 68,
+
+ /**
+ * SMS is blocked due to call control, e.g., resource unavailable
+ * in the SMR entity.
+ */
+ BLOCKED_DUE_TO_CALL = 69,
+
+ /**
+ * Returned from setRadioPowerResponse when detecting RF HW issues. Some RF
+ * Front-End(RFFE) components like antenna are considered critical for modem
+ * to provide telephony service. This RadioError is used when modem detect
+ * such RFFE problem.
+ */
+ RF_HARDWARE_ISSUE = 70,
+
+ /**
+ * Returned from setRadioPowerResponse when detecting no RF calibration
+ * issue. Unlike RF_HARDWARE_ISSUE, this is a SW problem and no HW repair is
+ * needed.
+ */
+ NO_RF_CALIBRATION_INFO = 71,
+};
+
+/**
+ * Overwritten from @1.0::RadioResponseInfo in order to update the RadioError to 1.6 version.
+ */
+struct RadioResponseInfo {
+ RadioResponseType type; // Response type
+ int32_t serial; // Serial number of the request
+ RadioError error; // Response error
+};
+
+/**
+ * Defines range of ports. start and end are the first and last port numbers
+ * (inclusive) in the range. Both start and end are in QosPortRange.MIN to
+ * QosPortRange.MAX range. A single port shall be represented by the same
+ * start and end value.
+ */
+struct PortRange {
+ int32_t start;
+ int32_t end;
+};
+
+/** Port is optional, contains either single port or range of ports */
+safe_union MaybePort {
+ Monostate noinit;
+ PortRange range;
+};
+
+/** See 3gpp 24.008 10.5.6.12 and 3gpp 24.501 9.11.4.13 */
+struct QosFilter {
+ /**
+ * Local and remote IP addresses, typically one IPv4 or one IPv6
+ * or one of each. Addresses could be with optional "/" prefix
+ * length, e.g.,"192.0.1.3" or "192.0.1.11/16 2001:db8::1/64".
+ * If the prefix length is absent the addresses are assumed to be
+ * point to point with IPv4 having a prefix length of 32 and
+ * IPv6 128.
+ */
+ vec<string> localAddresses;
+ vec<string> remoteAddresses;
+
+ /** Local and remote port/ranges */
+ MaybePort localPort;
+ MaybePort remotePort;
+
+ /** QoS protocol */
+ QosProtocol protocol;
+
+ /** Type of service value or mask as defined in RFC 1349 */
+ safe_union TypeOfService {
+ Monostate noinit;
+ uint8_t value;
+ } tos;
+
+ /** IPv6 flow label as defined in RFC 6437 */
+ safe_union Ipv6FlowLabel {
+ Monostate noinit;
+ uint32_t value;
+ } flowLabel;
+
+ /** IPSec security parameter index */
+ safe_union IpsecSpi {
+ Monostate noinit;
+ uint32_t value;
+ } spi;
+
+ /** Filter direction */
+ QosFilterDirection direction;
+
+ /**
+ * Specifies the order in which the filter needs to be matched.
+ * A lower numerical(positive) value has a higher precedence.
+ * Set -1 when unspecified.
+ */
+ int32_t precedence;
+};
+
+/** QOS session associated with a dedicated bearer */
+struct QosSession {
+ /** Unique ID of the QoS session within the data call */
+ int32_t qosSessionId;
+
+ /** QOS attributes */
+ Qos qos;
+
+ /** List of QOS filters associated with this session */
+ vec<QosFilter> qosFilters;
+};
+
+/** The allowed failure modes on an IWLAN handover failure. */
+enum HandoverFailureMode : int32_t {
+ /**
+ * On data handover failure, fallback to the source data transport when the
+ * fail cause is due to a hand off preference change.
+ */
+ LEGACY = 0,
+
+ /** On data handover failure, fallback to the source data transport. */
+ DO_FALLBACK = 1,
+
+ /**
+ * On data handover failure, retry the handover instead of falling back to
+ * the source data transport.
+ */
+ NO_FALLBACK_RETRY_HANDOVER = 2,
+
+ /**
+ * On data handover failure, setup a new data connection by sending a normal
+ * request to the underlying data service.
+ */
+ NO_FALLBACK_RETRY_SETUP_NORMAL = 3
+};
+
+/**
+ * Overwritten from @1.5::SetupDataCallResult in order to change the suggestedRetryTime
+ * to 64-bit value. In the future, this must be extended instead of overwritten.
+ * Also added defaultQos, qosSessions, and handoverFailureMode in this version.
+ */
+struct SetupDataCallResult {
+ /** Data call fail cause. DataCallFailCause.NONE if no error. */
+ DataCallFailCause cause;
+
+ /**
+ * If cause is not DataCallFailCause.NONE, this field indicates the network suggested data
+ * retry back-off time in milliseconds. Negative value indicates network does not give any
+ * suggestion. 0 indicates retry should be performed immediately. 0x7fffffffffffffff indicates
+ * the device should not retry data setup anymore.
+ */
+ uint64_t suggestedRetryTime;
+
+ /** Context ID, uniquely identifies this data connection. */
+ int32_t cid;
+
+ /** Data connection active status. */
+ DataConnActiveStatus active;
+
+ /**
+ * PDP protocol type. If cause is DataCallFailCause.ONLY_SINGLE_BEARER_ALLOWED, this is the
+ * protocol type supported, such as "IP" or "IPV6".
+ */
+ PdpProtocolType type;
+
+ /** The network interface name. */
+ string ifname;
+
+ /**
+ * List of link address.
+ */
+ vec<LinkAddress> addresses;
+
+ /**
+ * List of DNS server addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1". Empty if no dns
+ * server addresses returned.
+ */
+ vec<string> dnses;
+
+ /**
+ * List of default gateway addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1".
+ * When empty, the addresses represent point to point connections.
+ */
+ vec<string> gateways;
+
+ /**
+ * List of P-CSCF(Proxy Call State Control Function) addresses via PCO(Protocol Configuration
+ * Option), e.g., "2001:db8::1 2001:db8::2 2001:db8::3". Empty if not IMS client.
+ */
+ vec<string> pcscf;
+
+ /**
+ * MTU received from network for IPv4.
+ * Value <= 0 means network has either not sent a value or sent an invalid value.
+ */
+ int32_t mtuV4;
+
+ /**
+ * MTU received from network for IPv6.
+ * Value <= 0 means network has either not sent a value or sent an invalid value.
+ */
+ int32_t mtuV6;
+
+ /** Default bearer QoS. Applicable to LTE and NR */
+ Qos defaultQos;
+
+ /**
+ * Active QOS sessions of the dedicated bearers. Applicable to
+ * PDNs that support dedicated bearers.
+ */
+ vec<QosSession> qosSessions;
+
+ /** Specifies the fallback mode on an IWLAN handover failure. */
+ HandoverFailureMode handoverFailureMode;
+
+ /**
+ * The allocated pdu session id for this data call.
+ * A value of -1 means no pdu session id was attached to this call.
+ *
+ * Reference: 3GPP TS 24.007 section 11.2.3.1b
+ */
+ int32_t pduSessionId;
+};
+
+/**
+ * NR Dual connectivity state
+ */
+enum NrDualConnectivityState: int32_t {
+ /**
+ * Enable NR dual connectivity. Enabled state does not mean dual connectivity
+ * is active. It means device is allowed to connect to both primary and secondary.
+ */
+ ENABLE = 1,
+ /**
+ * Disable NR dual connectivity. Disabled state does not mean secondary cell is released.
+ * Modem will release it only if current bearer is released to avoid radio link failure.
+ */
+ DISABLE = 2,
+ /**
+ * Disable NR dual connectivity and force secondary cell to be released if dual connectivity
+ * was active. This may result in radio link failure.
+ */
+ DISABLE_IMMEDIATE= 3,
+};
+
+/**
+ * Overwritten from @1.2::LinkCapacityEstimate to update LinkCapacityEstimate to 1.6 version.
+ */
+struct LinkCapacityEstimate {
+
+ /**
+ * Estimated downlink capacity in kbps. In case of a dual connected network,
+ * this includes capacity of both primary and secondary. This bandwidth estimate shall be
+ * the estimated maximum sustainable link bandwidth (as would be measured
+ * at the Upper PDCP or SNDCP SAP). If the DL Aggregate Maximum Bit Rate is known,
+ * this value shall not exceed the DL-AMBR for the Internet PDN connection.
+ * This must be filled with -1 if network is not connected.
+ */
+ uint32_t downlinkCapacityKbps;
+
+ /**
+ * Estimated uplink capacity in kbps. In case of a dual connected network,
+ * this includes capacity of both primary and secondary. This bandwidth estimate shall be the
+ * estimated maximum sustainable link bandwidth (as would be measured at the
+ * Upper PDCP or SNDCP SAP). If the UL Aggregate Maximum Bit Rate is known,
+ * this value shall not exceed the UL-AMBR for the Internet PDN connection.
+ * This must be filled with -1 if network is not connected.
+ */
+ uint32_t uplinkCapacityKbps;
+
+ /**
+ * Estimated downlink capacity of secondary carrier in a dual connected NR mode in kbps.
+ * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth
+ * (as would be measured at the Upper PDCP or SNDCP SAP). This is valid only
+ * in if device is connected to both primary and secodary in dual connected
+ * mode. This must be filled with -1 if secondary is not connected.
+ */
+ uint32_t secondaryDownlinkCapacityKbps;
+
+ /**
+ * Estimated uplink capacity secondary carrier in a dual connected NR mode in kbps.
+ * This bandwidth estimate shall be the estimated
+ * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
+ * This is valid only in if device is connected to both primary and secodary in dual connected
+ * mode.This must be filled with -1 if secondary is not connected.
+ */
+ uint32_t secondaryUplinkCapacityKbps;
+};
+
+enum DataThrottlingAction : int32_t {
+ /* Clear all existing data throttling. */
+ NO_DATA_THROTTLING = 0,
+
+ /**
+ * Enact secondary carrier data throttling and remove any existing data
+ * throttling on anchor carrier.
+ */
+ THROTTLE_SECONDARY_CARRIER = 1,
+
+ /**
+ * Enact anchor carrier data throttling and disable data on secondary
+ * carrier if currently enabled.
+ */
+ THROTTLE_ANCHOR_CARRIER = 2,
+
+ /**
+ * Immediately hold on to current level of throttling.
+ */
+ HOLD = 3
+};
diff --git a/radio/1.6/vts/OWNERS b/radio/1.6/vts/OWNERS
new file mode 100644
index 0000000..3629a6c
--- /dev/null
+++ b/radio/1.6/vts/OWNERS
@@ -0,0 +1,10 @@
+# Telephony team
+refuhoo@google.com
+amitmahajan@google.com
+jackyu@google.com
+fionaxu@google.com
+# more to add
+
+# VTS team
+yuexima@google.com
+dshi@google.com
\ No newline at end of file
diff --git a/radio/1.6/vts/functional/Android.bp b/radio/1.6/vts/functional/Android.bp
new file mode 100644
index 0000000..db90f88
--- /dev/null
+++ b/radio/1.6/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+ name: "VtsHalRadioV1_6TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "radio_hidl_hal_api.cpp",
+ "radio_hidl_hal_test.cpp",
+ "radio_response.cpp",
+ "radio_indication.cpp",
+ "VtsHalRadioV1_6TargetTest.cpp",
+ "vts_test_util_v1_6.cpp",
+ ],
+ static_libs: [
+ "RadioVtsTestUtilBase",
+ "android.hardware.radio@1.6",
+ "android.hardware.radio@1.5",
+ "android.hardware.radio@1.4",
+ "android.hardware.radio@1.3",
+ "android.hardware.radio@1.2",
+ "android.hardware.radio@1.1",
+ "android.hardware.radio@1.0",
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
+ ],
+ header_libs: ["radio.util.header@1.0"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp b/radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp
new file mode 100644
index 0000000..ffa3587
--- /dev/null
+++ b/radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_6.h>
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioHidlTest_v1_6);
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_6,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ android::hardware::radio::V1_6::IRadio::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
new file mode 100644
index 0000000..d3ffba9
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_6.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadio.setupDataCall_1_6() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setupDataCall_1_6) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::AccessNetwork accessNetwork =
+ ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN;
+
+ android::hardware::radio::V1_5::DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileId::DEFAULT;
+ dataProfileInfo.apn = hidl_string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IP;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = hidl_string("username");
+ dataProfileInfo.password = hidl_string("password");
+ dataProfileInfo.type = DataProfileInfoType::THREE_GPP;
+ dataProfileInfo.maxConnsTime = 300;
+ dataProfileInfo.maxConns = 20;
+ dataProfileInfo.waitTime = 0;
+ dataProfileInfo.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap = 320;
+ dataProfileInfo.bearerBitmap = 161543;
+ dataProfileInfo.mtuV4 = 0;
+ dataProfileInfo.mtuV6 = 0;
+ dataProfileInfo.preferred = true;
+ dataProfileInfo.persistent = false;
+
+ bool roamingAllowed = false;
+
+ std::vector<::android::hardware::radio::V1_5::LinkAddress> addresses = {};
+ std::vector<hidl_string> dnses = {};
+
+ ::android::hardware::radio::V1_2::DataRequestReason reason =
+ ::android::hardware::radio::V1_2::DataRequestReason::NORMAL;
+
+ Return<void> res = radio_v1_6->setupDataCall_1_6(serial, accessNetwork, dataProfileInfo,
+ roamingAllowed, reason, addresses, dnses, -1);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::SIM_ABSENT,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ }
+}
+
+/*
+ * Test IRadio_1_6.sendSms() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, sendSms_1_6) {
+ LOG(DEBUG) << "sendSms";
+ serial = GetRandomSerialNumber();
+ GsmSmsMessage msg;
+ msg.smscPdu = "";
+ msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+ radio_v1_6->sendSms(serial, msg);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ EXPECT_EQ(0, radioRsp_v1_6->sendSmsResult.errorCode);
+ }
+ LOG(DEBUG) << "sendSms finished";
+}
+
+/*
+ * Test IRadio_1_6.sendSMSExpectMore() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, sendSMSExpectMore_1_6) {
+ LOG(DEBUG) << "sendSMSExpectMore";
+ serial = GetRandomSerialNumber();
+ GsmSmsMessage msg;
+ msg.smscPdu = "";
+ msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+ radio_v1_6->sendSMSExpectMore(serial, msg);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendSMSExpectMore finished";
+}
+
+/*
+ * Test IRadio_1_6.sendCdmaSms() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, sendCdmaSms_1_6) {
+ LOG(DEBUG) << "sendCdmaSms";
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsDigitMode::FOUR_BIT;
+ cdmaSmsAddress.numberMode = CdmaSmsNumberMode::NOT_DATA_NETWORK;
+ cdmaSmsAddress.numberType = CdmaSmsNumberType::UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsNumberPlan::UNKNOWN;
+ cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+ // Create a CdmaSmsSubAddress
+ CdmaSmsSubaddress cdmaSmsSubaddress;
+ cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddressType::NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ android::hardware::radio::V1_0::CdmaSmsMessage cdmaSmsMessage;
+ cdmaSmsMessage.teleserviceId = 4098;
+ cdmaSmsMessage.isServicePresent = false;
+ cdmaSmsMessage.serviceCategory = 0;
+ cdmaSmsMessage.address = cdmaSmsAddress;
+ cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+ cdmaSmsMessage.bearerData =
+ (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+ radio_v1_6->sendCdmaSms(serial, cdmaSmsMessage);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendCdmaSms finished";
+}
+
+/*
+ * Test IRadio_1_6.sendCdmaSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, sendCdmaSmsExpectMore_1_6) {
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsDigitMode::FOUR_BIT;
+ cdmaSmsAddress.numberMode = CdmaSmsNumberMode::NOT_DATA_NETWORK;
+ cdmaSmsAddress.numberType = CdmaSmsNumberType::UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsNumberPlan::UNKNOWN;
+ cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+ // Create a CdmaSmsSubAddress
+ CdmaSmsSubaddress cdmaSmsSubaddress;
+ cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddressType::NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ android::hardware::radio::V1_0::CdmaSmsMessage cdmaSmsMessage;
+ cdmaSmsMessage.teleserviceId = 4098;
+ cdmaSmsMessage.isServicePresent = false;
+ cdmaSmsMessage.serviceCategory = 0;
+ cdmaSmsMessage.address = cdmaSmsAddress;
+ cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+ cdmaSmsMessage.bearerData =
+ (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+ radio_v1_6->sendCdmaSmsExpectMore(serial, cdmaSmsMessage);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadio.setRadioPower_1_6() for the response returned by
+ * IRadio.setRadioPowerResponse_1_6().
+ */
+TEST_P(RadioHidlTest_v1_6, setRadioPower_1_6_emergencyCall_cancelled) {
+ // Set radio power to off.
+ serial = GetRandomSerialNumber();
+ radio_v1_6->setRadioPower_1_6(serial, false, false, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+
+ // Set radio power to on with forEmergencyCall being true. This should put modem to only scan
+ // emergency call bands.
+ serial = GetRandomSerialNumber();
+ radio_v1_6->setRadioPower_1_6(serial, true, true, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+
+ // Set radio power to on with forEmergencyCall being false. This should put modem in regular
+ // operation modem.
+ serial = GetRandomSerialNumber();
+ radio_v1_6->setRadioPower_1_6(serial, true, false, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+}
+
+/*
+ * Test IRadio.setNrDualConnectivityState() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setNrDualConnectivityState) {
+ serial = GetRandomSerialNumber();
+
+ Return<void> res =
+ radio_v1_6->setNrDualConnectivityState(serial, NrDualConnectivityState::DISABLE);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
+}
+
+/*
+ * Test IRadio.isNrDualConnectivityEnabled() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, isNrDualConnectivityEnabled) {
+ serial = GetRandomSerialNumber();
+
+ Return<void> res = radio_v1_6->isNrDualConnectivityEnabled(serial);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
+}
+
+/*
+ * Test IRadio.setDataThrottling() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setDataThrottling) {
+ serial = GetRandomSerialNumber();
+
+ Return<void> res = radio_v1_6->setDataThrottling(
+ serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+
+ serial = GetRandomSerialNumber();
+
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER, 60);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+
+ serial = GetRandomSerialNumber();
+
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::HOLD, 60);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+
+ serial = GetRandomSerialNumber();
+
+ res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
+}
\ No newline at end of file
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
new file mode 100644
index 0000000..79c3cde
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_6.h>
+
+void RadioHidlTest_v1_6::SetUp() {
+ radio_v1_6 = android::hardware::radio::V1_6::IRadio::getService(GetParam());
+ ASSERT_NE(nullptr, radio_v1_6.get());
+
+ radioRsp_v1_6 = new (std::nothrow) RadioResponse_v1_6(*this);
+ ASSERT_NE(nullptr, radioRsp_v1_6.get());
+
+ count_ = 0;
+
+ radioInd_v1_6 = new (std::nothrow) RadioIndication_v1_6(*this);
+ ASSERT_NE(nullptr, radioInd_v1_6.get());
+
+ radio_v1_6->setResponseFunctions(radioRsp_v1_6, radioInd_v1_6);
+
+ updateSimCardStatus();
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo_v1_0.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo_v1_0.serial);
+ EXPECT_EQ(::android::hardware::radio::V1_0::RadioError::NONE,
+ radioRsp_v1_6->rspInfo_v1_0.error);
+
+ sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
+ ::android::hardware::radio::config::V1_1::IRadioConfig::getService();
+ /* Enforce Vts testing with RadioConfig is existed. */
+ ASSERT_NE(nullptr, radioConfig.get());
+
+ /* Enforce Vts Testing with Sim Status Present only. */
+ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioHidlTest_v1_6::notify(int receivedSerial) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ if (serial == receivedSerial) {
+ count_++;
+ cv_.notify_one();
+ }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioHidlTest_v1_6::wait() {
+ std::unique_lock<std::mutex> lock(mtx_);
+
+ std::cv_status status = std::cv_status::no_timeout;
+ auto now = std::chrono::system_clock::now();
+ while (count_ == 0) {
+ status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) {
+ return status;
+ }
+ }
+ count_--;
+ return status;
+}
+
+void RadioHidlTest_v1_6::updateSimCardStatus() {
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getIccCardStatus(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
+
+void RadioHidlTest_v1_6::getDataCallList() {
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getDataCallList_1_6(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
new file mode 100644
index 0000000..fcf679c
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -0,0 +1,1062 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+
+#include <android/hardware/radio/1.6/IRadio.h>
+#include <android/hardware/radio/1.6/IRadioIndication.h>
+#include <android/hardware/radio/1.6/IRadioResponse.h>
+#include <android/hardware/radio/1.6/types.h>
+
+#include "vts_test_util_v1_6.h"
+
+using namespace ::android::hardware::radio::V1_6;
+using namespace ::android::hardware::radio::V1_5;
+using namespace ::android::hardware::radio::V1_4;
+using namespace ::android::hardware::radio::V1_3;
+using namespace ::android::hardware::radio::V1_2;
+using namespace ::android::hardware::radio::V1_1;
+using namespace ::android::hardware::radio::V1_0;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+#define TIMEOUT_PERIOD 75
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioHidlTest_v1_6;
+extern ::android::hardware::radio::V1_5::CardStatus cardStatus;
+
+/* Callback class for radio response v1_6 */
+class RadioResponse_v1_6 : public ::android::hardware::radio::V1_6::IRadioResponse {
+ protected:
+ RadioHidlTest_v1_6& parent_v1_6;
+
+ public:
+ hidl_vec<RadioBandMode> radioBandModes;
+
+ ::android::hardware::radio::V1_0::RadioResponseInfo rspInfo_v1_0;
+ ::android::hardware::radio::V1_6::RadioResponseInfo rspInfo;
+
+ // Call
+ hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls;
+
+ // Sms
+ SendSmsResult sendSmsResult;
+
+ // Modem
+ bool isModemEnabled;
+ bool enableModemResponseToggle;
+ bool isNRDualConnectivityEnabled;
+
+ // Pdu Session Id and Handover
+ int32_t allocatedPduSessionId;
+
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ networkTypeBitmapResponse;
+
+ // Data
+ ::android::hardware::radio::V1_4::DataRegStateResult dataRegResp;
+
+ // SimLock status
+ ::android::hardware::radio::V1_4::CarrierRestrictionsWithPriority carrierRestrictionsResp;
+ ::android::hardware::radio::V1_4::SimLockMultiSimPolicy multiSimPolicyResp;
+
+ // Whether toggling uicc applications operation is supported.
+ bool canToggleUiccApplicationsEnablement;
+
+ // Whether Uicc applications are enabled or not.
+ bool areUiccApplicationsEnabled;
+
+ // Barring Info Response
+ ::android::hardware::radio::V1_5::CellIdentity barringCellIdentity;
+ ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos;
+
+ RadioResponse_v1_6(RadioHidlTest_v1_6& parent_v1_6);
+ virtual ~RadioResponse_v1_6() = default;
+
+ Return<void> getIccCardStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::CardStatus& cardStatus);
+
+ Return<void> supplyIccPinForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPukForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPin2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyIccPuk2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> changeIccPinForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> changeIccPin2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> supplyNetworkDepersonalizationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries);
+
+ Return<void> getCurrentCallsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& calls);
+
+ Return<void> dialResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getIMSIForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& imsi);
+
+ Return<void> hangupConnectionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> hangupWaitingOrBackgroundResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> hangupForegroundResumeBackgroundResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> switchWaitingOrHoldingAndActiveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> conferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> rejectCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getLastCallFailCauseResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const LastCallFailCauseInfo& failCauseInfo);
+
+ Return<void> getSignalStrengthResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::SignalStrength& sigStrength);
+
+ Return<void> getVoiceRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::VoiceRegStateResult& voiceRegResponse);
+
+ Return<void> getDataRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_0::DataRegStateResult& dataRegResponse);
+
+ Return<void> getOperatorResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& longName,
+ const ::android::hardware::hidl_string& shortName,
+ const ::android::hardware::hidl_string& numeric);
+
+ Return<void> setRadioPowerResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendDtmfResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendSmsResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> sendSMSExpectMoreResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> setupDataCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::SetupDataCallResult& dcResponse);
+
+ Return<void> iccIOForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const IccIoResult& iccIo);
+
+ Return<void> sendUssdResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> cancelPendingUssdResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getClirResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ int32_t n, int32_t m);
+
+ Return<void> setClirResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCallForwardStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<CallForwardInfo>& call_forwardInfos);
+
+ Return<void> setCallForwardResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCallWaitingResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool enable,
+ int32_t serviceClass);
+
+ Return<void> setCallWaitingResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> acknowledgeLastIncomingGsmSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> acceptCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> deactivateDataCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getFacilityLockForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, int32_t response);
+
+ Return<void> setFacilityLockForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, int32_t retry);
+
+ Return<void> setBarringPasswordResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getNetworkSelectionModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool manual);
+
+ Return<void> setNetworkSelectionModeAutomaticResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setNetworkSelectionModeManualResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getAvailableNetworksResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<OperatorInfo>& networkInfos);
+
+ Return<void> startDtmfResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> stopDtmfResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getBasebandVersionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& version);
+
+ Return<void> separateConnectionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setMuteResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getMuteResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ bool enable);
+
+ Return<void> getClipResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ ClipStatus status);
+
+ Return<void> getDataCallListResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_0::SetupDataCallResult>& dcResponse);
+
+ Return<void> sendOemRilRequestRawResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<uint8_t>& data);
+
+ Return<void> sendOemRilRequestStringsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
+
+ Return<void> setSuppServiceNotificationsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> writeSmsToSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, int32_t index);
+
+ Return<void> deleteSmsOnSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setBandModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getAvailableBandModesResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<RadioBandMode>& bandModes);
+
+ Return<void> sendEnvelopeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& commandResponse);
+
+ Return<void> sendTerminalResponseToSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> handleStkCallSetupRequestFromSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> explicitCallTransferResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setPreferredNetworkTypeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getPreferredNetworkTypeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ PreferredNetworkType nwType);
+
+ Return<void> getNeighboringCidsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<NeighboringCell>& cells);
+
+ Return<void> setLocationUpdatesResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setCdmaSubscriptionSourceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setCdmaRoamingPreferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCdmaRoamingPreferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, CdmaRoamingType type);
+
+ Return<void> setTTYModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getTTYModeResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ TtyMode mode);
+
+ Return<void> setPreferredVoicePrivacyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getPreferredVoicePrivacyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool enable);
+
+ Return<void> sendCDMAFeatureCodeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendBurstDtmfResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendCdmaSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> acknowledgeLastIncomingCdmaSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getGsmBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& configs);
+
+ Return<void> setGsmBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setGsmBroadcastActivationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCdmaBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& configs);
+
+ Return<void> setCdmaBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setCdmaBroadcastActivationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCDMASubscriptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& mdn,
+ const ::android::hardware::hidl_string& hSid,
+ const ::android::hardware::hidl_string& hNid,
+ const ::android::hardware::hidl_string& min,
+ const ::android::hardware::hidl_string& prl);
+
+ Return<void> writeSmsToRuimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, uint32_t index);
+
+ Return<void> deleteSmsOnRuimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getDeviceIdentityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& imei,
+ const ::android::hardware::hidl_string& imeisv,
+ const ::android::hardware::hidl_string& esn,
+ const ::android::hardware::hidl_string& meid);
+
+ Return<void> exitEmergencyCallbackModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getSmscAddressResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& smsc);
+
+ Return<void> setSmscAddressResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> reportSmsMemoryStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> reportStkServiceIsRunningResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCdmaSubscriptionSourceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ CdmaSubscriptionSource source);
+
+ Return<void> requestIsimAuthenticationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& response);
+
+ Return<void> acknowledgeIncomingGsmSmsWithPduResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendEnvelopeWithStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const IccIoResult& iccIo);
+
+ Return<void> getVoiceRadioTechnologyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+ Return<void> getCellInfoListResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+ cellInfo);
+
+ Return<void> setCellInfoListRateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setInitialAttachApnResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getImsRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool isRegistered,
+ RadioTechnologyFamily ratFamily);
+
+ Return<void> sendImsSmsResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> iccTransmitApduBasicChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> iccOpenLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, int32_t channelId,
+ const ::android::hardware::hidl_vec<int8_t>& selectResponse);
+
+ Return<void> iccCloseLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> iccTransmitApduLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> nvReadItemResponse(const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_string& result);
+
+ Return<void> nvWriteItemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> nvWriteCdmaPrlResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> nvResetConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setUiccSubscriptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setDataAllowedResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getHardwareConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<HardwareConfig>& config);
+
+ Return<void> requestIccSimAuthenticationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const IccIoResult& result);
+
+ Return<void> setDataProfileResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> requestShutdownResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getRadioCapabilityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> setRadioCapabilityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> startLceServiceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const LceStatusInfo& statusInfo);
+
+ Return<void> stopLceServiceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const LceStatusInfo& statusInfo);
+
+ Return<void> pullLceDataResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const LceDataInfo& lceInfo);
+
+ Return<void> getModemActivityInfoResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ActivityStatsInfo& activityInfo);
+
+ Return<void> setAllowedCarriersResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, int32_t numAllowed);
+
+ Return<void> getAllowedCarriersResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool allAllowed,
+ const CarrierRestrictions& carriers);
+
+ Return<void> sendDeviceStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setIndicationFilterResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setSimCardPowerResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> acknowledgeRequest(int32_t serial);
+
+ /* 1.1 Api */
+ Return<void> setCarrierInfoForImsiEncryptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setSimCardPowerResponse_1_1(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> stopNetworkScanResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> startKeepaliveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const KeepaliveStatus& status);
+
+ Return<void> stopKeepaliveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ /* 1.2 Api */
+ Return<void> setSignalStrengthReportingCriteriaResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setLinkCapacityReportingCriteriaResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getIccCardStatusResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::CardStatus& card_status);
+
+ Return<void> getCurrentCallsResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls);
+
+ Return<void> getSignalStrengthResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::SignalStrength& sig_strength);
+
+ Return<void> getSignalStrengthResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::SignalStrength& sig_strength);
+
+ Return<void> getCellInfoListResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+ cellInfo);
+
+ Return<void> getVoiceRegistrationStateResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse);
+
+ Return<void> getDataRegistrationStateResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_2::DataRegStateResult& dataRegResponse);
+
+ /* 1.3 Api */
+ Return<void> setSystemSelectionChannelsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> enableModemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getModemStackStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, const bool enabled);
+
+ /* 1.4 Api */
+ Return<void> emergencyDialResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getCellInfoListResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+ cellInfo);
+
+ Return<void> getDataRegistrationStateResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse);
+
+ Return<void> getIccCardStatusResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_4::CardStatus& card_status);
+
+ Return<void> getPreferredNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_bitfield<
+ ::android::hardware::radio::V1_4::RadioAccessFamily>
+ networkTypeBitmap);
+
+ Return<void> setPreferredNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getDataCallListResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::SetupDataCallResult>& dcResponse);
+
+ Return<void> setupDataCallResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const android::hardware::radio::V1_4::SetupDataCallResult& dcResponse);
+
+ Return<void> setAllowedCarriersResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getAllowedCarriersResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const CarrierRestrictionsWithPriority& carriers, SimLockMultiSimPolicy multiSimPolicy);
+
+ /* 1.5 Api */
+ Return<void> setSignalStrengthReportingCriteriaResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setLinkCapacityReportingCriteriaResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> enableUiccApplicationsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> areUiccApplicationsEnabledResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool enabled);
+
+ Return<void> canToggleUiccApplicationsEnablementResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info, bool canToggle);
+
+ Return<void> setSystemSelectionChannelsResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setupDataCallResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const android::hardware::radio::V1_5::SetupDataCallResult& dcResponse);
+
+ Return<void> getDataCallListResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcResponse);
+
+ Return<void> setInitialAttachApnResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setDataProfileResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setRadioPowerResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> setIndicationFilterResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> getBarringInfoResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+ barringInfos);
+
+ Return<void> getVoiceRegistrationStateResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
+
+ Return<void> getDataRegistrationStateResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
+
+ Return<void> getCellInfoListResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::CellInfo>&
+ cellInfo);
+
+ Return<void> setNetworkSelectionModeManualResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info);
+
+ Return<void> sendCdmaSmsExpectMoreResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> supplySimDepersonalizationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ ::android::hardware::radio::V1_5::PersoSubstate persoType, int32_t remainingRetries);
+
+ Return<void> getIccCardStatusResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::CardStatus& card_status);
+
+ /* 1.6 Api */
+ Return<void> setRadioPowerResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> setupDataCallResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const android::hardware::radio::V1_6::SetupDataCallResult& dcResponse);
+
+ Return<void> getDataCallListResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const hidl_vec<::android::hardware::radio::V1_6::SetupDataCallResult>& dcResponse);
+
+ Return<void> sendSmsResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> sendSMSExpectMoreResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> sendCdmaSmsResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> setSimCardPowerResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> sendCdmaSmsExpectMoreResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms);
+
+ Return<void> setNrDualConnectivityStateResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+ Return<void> isNrDualConnectivityEnabledResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info, bool isEnabled);
+
+ Return<void> allocatePduSessionIdResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info, int32_t id);
+
+ Return<void> releasePduSessionIdResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> startHandoverResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> cancelHandoverResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> setAllowedNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+ Return<void> setDataThrottlingResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+};
+
+/* Callback class for radio indication */
+class RadioIndication_v1_6 : public ::android::hardware::radio::V1_6::IRadioIndication {
+ protected:
+ RadioHidlTest_v1_6& parent_v1_6;
+
+ public:
+ RadioIndication_v1_6(RadioHidlTest_v1_6& parent_v1_6);
+ virtual ~RadioIndication_v1_6() = default;
+
+ /* 1.6 Api */
+ Return<void> dataCallListChanged_1_6(
+ RadioIndicationType type,
+ const hidl_vec<::android::hardware::radio::V1_6::SetupDataCallResult>& dcList);
+
+ Return<void> unthrottleApn(RadioIndicationType type,
+ const ::android::hardware::hidl_string& apn);
+
+ /* 1.5 Api */
+ Return<void> uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
+
+ Return<void> networkScanResult_1_5(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_5::NetworkScanResult& result);
+
+ Return<void> cellInfoList_1_5(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::CellInfo>&
+ records);
+
+ Return<void> dataCallListChanged_1_5(
+ RadioIndicationType type,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcList);
+
+ /* 1.4 Api */
+ Return<void> currentEmergencyNumberList(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<EmergencyNumber>& emergencyNumberList);
+
+ Return<void> cellInfoList_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+ records);
+
+ Return<void> networkScanResult_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_4::NetworkScanResult& result);
+
+ Return<void> currentPhysicalChannelConfigs_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::PhysicalChannelConfig>& configs);
+
+ Return<void> dataCallListChanged_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_4::SetupDataCallResult>& dcList);
+
+ /* 1.2 Api */
+ Return<void> networkScanResult_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::NetworkScanResult& result);
+
+ Return<void> cellInfoList_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+ records);
+
+ Return<void> currentLinkCapacityEstimate(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::LinkCapacityEstimate& lce);
+
+ Return<void> currentLinkCapacityEstimate_1_6(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_6::LinkCapacityEstimate& lce);
+
+ Return<void> currentPhysicalChannelConfigs(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::PhysicalChannelConfig>& configs);
+
+ Return<void> currentSignalStrength_1_2(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_2::SignalStrength& signalStrength);
+
+ Return<void> currentSignalStrength_1_4(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_4::SignalStrength& signalStrength);
+
+ /* 1.1 Api */
+ Return<void> carrierInfoForImsiEncryption(RadioIndicationType info);
+
+ Return<void> networkScanResult(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_1::NetworkScanResult& result);
+
+ Return<void> keepaliveStatus(RadioIndicationType type, const KeepaliveStatus& status);
+
+ /* 1.0 Api */
+ Return<void> radioStateChanged(RadioIndicationType type, RadioState radioState);
+
+ Return<void> callStateChanged(RadioIndicationType type);
+
+ Return<void> networkStateChanged(RadioIndicationType type);
+
+ Return<void> newSms(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+ Return<void> newSmsStatusReport(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+ Return<void> newSmsOnSim(RadioIndicationType type, int32_t recordNumber);
+
+ Return<void> onUssd(RadioIndicationType type, UssdModeType modeType,
+ const ::android::hardware::hidl_string& msg);
+
+ Return<void> nitzTimeReceived(RadioIndicationType type,
+ const ::android::hardware::hidl_string& nitzTime,
+ uint64_t receivedTime);
+
+ Return<void> currentSignalStrength(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_0::SignalStrength& signalStrength);
+
+ Return<void> dataCallListChanged(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<
+ android::hardware::radio::V1_0::SetupDataCallResult>& dcList);
+
+ Return<void> suppSvcNotify(RadioIndicationType type, const SuppSvcNotification& suppSvc);
+
+ Return<void> stkSessionEnd(RadioIndicationType type);
+
+ Return<void> stkProactiveCommand(RadioIndicationType type,
+ const ::android::hardware::hidl_string& cmd);
+
+ Return<void> stkEventNotify(RadioIndicationType type,
+ const ::android::hardware::hidl_string& cmd);
+
+ Return<void> stkCallSetup(RadioIndicationType type, int64_t timeout);
+
+ Return<void> simSmsStorageFull(RadioIndicationType type);
+
+ Return<void> simRefresh(RadioIndicationType type, const SimRefreshResult& refreshResult);
+
+ Return<void> callRing(RadioIndicationType type, bool isGsm, const CdmaSignalInfoRecord& record);
+
+ Return<void> simStatusChanged(RadioIndicationType type);
+
+ Return<void> cdmaNewSms(RadioIndicationType type, const CdmaSmsMessage& msg);
+
+ Return<void> newBroadcastSms(RadioIndicationType type,
+ const ::android::hardware::hidl_vec<uint8_t>& data);
+
+ Return<void> cdmaRuimSmsStorageFull(RadioIndicationType type);
+
+ Return<void> restrictedStateChanged(RadioIndicationType type, PhoneRestrictedState state);
+
+ Return<void> enterEmergencyCallbackMode(RadioIndicationType type);
+
+ Return<void> cdmaCallWaiting(RadioIndicationType type,
+ const CdmaCallWaiting& callWaitingRecord);
+
+ Return<void> cdmaOtaProvisionStatus(RadioIndicationType type, CdmaOtaProvisionStatus status);
+
+ Return<void> cdmaInfoRec(RadioIndicationType type, const CdmaInformationRecords& records);
+
+ Return<void> indicateRingbackTone(RadioIndicationType type, bool start);
+
+ Return<void> resendIncallMute(RadioIndicationType type);
+
+ Return<void> cdmaSubscriptionSourceChanged(RadioIndicationType type,
+ CdmaSubscriptionSource cdmaSource);
+
+ Return<void> cdmaPrlChanged(RadioIndicationType type, int32_t version);
+
+ Return<void> exitEmergencyCallbackMode(RadioIndicationType type);
+
+ Return<void> rilConnected(RadioIndicationType type);
+
+ Return<void> voiceRadioTechChanged(RadioIndicationType type,
+ ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+ Return<void> cellInfoList(
+ RadioIndicationType type,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+ records);
+
+ Return<void> imsNetworkStateChanged(RadioIndicationType type);
+
+ Return<void> subscriptionStatusChanged(RadioIndicationType type, bool activate);
+
+ Return<void> srvccStateNotify(RadioIndicationType type, SrvccState state);
+
+ Return<void> hardwareConfigChanged(
+ RadioIndicationType type, const ::android::hardware::hidl_vec<HardwareConfig>& configs);
+
+ Return<void> radioCapabilityIndication(
+ RadioIndicationType type, const android::hardware::radio::V1_0::RadioCapability& rc);
+
+ Return<void> onSupplementaryServiceIndication(RadioIndicationType type,
+ const StkCcUnsolSsResult& ss);
+
+ Return<void> stkCallControlAlphaNotify(RadioIndicationType type,
+ const ::android::hardware::hidl_string& alpha);
+
+ Return<void> lceData(RadioIndicationType type, const LceDataInfo& lce);
+
+ Return<void> pcoData(RadioIndicationType type, const PcoDataInfo& pco);
+
+ Return<void> modemReset(RadioIndicationType type,
+ const ::android::hardware::hidl_string& reason);
+
+ Return<void> registrationFailed(
+ RadioIndicationType type,
+ const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
+ const ::android::hardware::hidl_string& chosenPlmn,
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> domain,
+ int32_t causeCode, int32_t additionalCauseCode);
+
+ Return<void> barringInfoChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+ /*barringInfos*/);
+};
+
+// The main test class for Radio HIDL.
+class RadioHidlTest_v1_6 : public ::testing::TestWithParam<std::string> {
+ protected:
+ std::mutex mtx_;
+ std::condition_variable cv_;
+ int count_;
+
+ /* Serial number for radio request */
+ int serial;
+
+ /* Clear Potential Established Calls */
+ void clearPotentialEstablishedCalls();
+
+ /* Update Sim Card Status */
+ void updateSimCardStatus();
+
+ /* Get current data call list */
+ void getDataCallList();
+
+ public:
+ virtual void SetUp() override;
+
+ /* Used as a mechanism to inform the test about data/event callback */
+ void notify(int receivedSerial);
+
+ /* Test code calls this function to wait for response */
+ std::cv_status wait();
+
+ /* radio service handle */
+ sp<::android::hardware::radio::V1_6::IRadio> radio_v1_6;
+
+ /* radio response handle */
+ sp<RadioResponse_v1_6> radioRsp_v1_6;
+
+ /* radio indication handle */
+ sp<RadioIndication_v1_6> radioInd_v1_6;
+};
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
new file mode 100644
index 0000000..afde291
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_6.h>
+
+RadioIndication_v1_6::RadioIndication_v1_6(RadioHidlTest_v1_6& parent) : parent_v1_6(parent) {}
+
+/* 1.6 Apis */
+Return<void> RadioIndication_v1_6::dataCallListChanged_1_6(
+ RadioIndicationType /*type*/,
+ const hidl_vec<android::hardware::radio::V1_6::SetupDataCallResult>& /*dcList*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::unthrottleApn(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_string& /*apn*/) {
+ return Void();
+}
+
+/* 1.5 Apis */
+Return<void> RadioIndication_v1_6::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
+ bool /*enabled*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::registrationFailed(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const hidl_string& /*chosenPlmn*/,
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> /*domain*/,
+ int32_t /*causeCode*/, int32_t /*additionalCauseCode*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::barringInfoChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const hidl_vec<::android::hardware::radio::V1_5::BarringInfo>& /*barringInfos*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult_1_5(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_5(
+ RadioIndicationType /*type*/,
+ const hidl_vec<::android::hardware::radio::V1_5::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged_1_5(
+ RadioIndicationType /*type*/,
+ const hidl_vec<android::hardware::radio::V1_5::SetupDataCallResult>& /*dcList*/) {
+ return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioIndication_v1_6::currentPhysicalChannelConfigs_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::PhysicalChannelConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_4::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentEmergencyNumberList(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<EmergencyNumber>& /*emergencyNumberList*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_4::SetupDataCallResult>&
+ /*dcList*/) {
+ return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioIndication_v1_6::networkScanResult_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentLinkCapacityEstimate(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::LinkCapacityEstimate& /*lce*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentLinkCapacityEstimate_1_6(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_6::LinkCapacityEstimate& /*lce*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentPhysicalChannelConfigs(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::PhysicalChannelConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength_1_2(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_2::SignalStrength& /*signalStrength*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength_1_4(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_4::SignalStrength& /*signalStrength*/) {
+ return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioIndication_v1_6::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_1::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::keepaliveStatus(RadioIndicationType /*type*/,
+ const KeepaliveStatus& /*status*/) {
+ return Void();
+}
+
+/* 1.0 Apis */
+Return<void> RadioIndication_v1_6::radioStateChanged(RadioIndicationType /*type*/,
+ RadioState /*radioState*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::callStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSms(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSmsStatusReport(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSmsOnSim(RadioIndicationType /*type*/,
+ int32_t /*recordNumber*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::onUssd(RadioIndicationType /*type*/, UssdModeType /*modeType*/,
+ const ::android::hardware::hidl_string& /*msg*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::nitzTimeReceived(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*nitzTime*/,
+ uint64_t /*receivedTime*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_0::SignalStrength& /*signalStrength*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+ /*dcList*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::suppSvcNotify(RadioIndicationType /*type*/,
+ const SuppSvcNotification& /*suppSvc*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkSessionEnd(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkProactiveCommand(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*cmd*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkEventNotify(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_string& /*cmd*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkCallSetup(RadioIndicationType /*type*/, int64_t /*timeout*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::simSmsStorageFull(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::simRefresh(RadioIndicationType /*type*/,
+ const SimRefreshResult& /*refreshResult*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+ const CdmaSignalInfoRecord& /*record*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::simStatusChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaNewSms(RadioIndicationType /*type*/,
+ const CdmaSmsMessage& /*msg*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::newBroadcastSms(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::restrictedStateChanged(RadioIndicationType /*type*/,
+ PhoneRestrictedState /*state*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaCallWaiting(RadioIndicationType /*type*/,
+ const CdmaCallWaiting& /*callWaitingRecord*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+ CdmaOtaProvisionStatus /*status*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaInfoRec(RadioIndicationType /*type*/,
+ const CdmaInformationRecords& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::indicateRingbackTone(RadioIndicationType /*type*/,
+ bool /*start*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::resendIncallMute(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaSubscriptionSourceChanged(
+ RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaPrlChanged(RadioIndicationType /*type*/,
+ int32_t /*version*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::rilConnected(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::voiceRadioTechChanged(
+ RadioIndicationType /*type*/, ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_0::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::subscriptionStatusChanged(RadioIndicationType /*type*/,
+ bool /*activate*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::srvccStateNotify(RadioIndicationType /*type*/,
+ SrvccState /*state*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::hardwareConfigChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_vec<HardwareConfig>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::radioCapabilityIndication(
+ RadioIndicationType /*type*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::onSupplementaryServiceIndication(
+ RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkCallControlAlphaNotify(
+ RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*alpha*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::lceData(RadioIndicationType /*type*/,
+ const LceDataInfo& /*lce*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::pcoData(RadioIndicationType /*type*/,
+ const PcoDataInfo& /*pco*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_6::modemReset(RadioIndicationType /*type*/,
+ const ::android::hardware::hidl_string& /*reason*/) {
+ return Void();
+}
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
new file mode 100644
index 0000000..788038a
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -0,0 +1,1165 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_6.h>
+
+::android::hardware::radio::V1_5::CardStatus cardStatus;
+
+RadioResponse_v1_6::RadioResponse_v1_6(RadioHidlTest_v1_6& parent) : parent_v1_6(parent) {}
+
+/* 1.0 Apis */
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::CardStatus& /*card_status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPinForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPukForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPin2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPuk2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::changeIccPinForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::changeIccPin2ForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyNetworkDepersonalizationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCurrentCallsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& /*calls*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::dialResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIMSIForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*imsi*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupConnectionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupWaitingOrBackgroundResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupForegroundResumeBackgroundResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::switchWaitingOrHoldingAndActiveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::conferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::rejectCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getLastCallFailCauseResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const LastCallFailCauseInfo& /*failCauseInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::SignalStrength& /*sig_strength*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::VoiceRegStateResult& /*voiceRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_0::DataRegStateResult& /*dataRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getOperatorResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*longName*/,
+ const ::android::hardware::hidl_string& /*shortName*/,
+ const ::android::hardware::hidl_string& /*numeric*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioPowerResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendDtmfResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSMSExpectMoreResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::SetupDataCallResult& /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccIOForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const IccIoResult& /*iccIo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendUssdResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::cancelPendingUssdResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getClirResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, int32_t /*n*/,
+ int32_t /*m*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setClirResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCallForwardStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<CallForwardInfo>&
+ /*callForwardInfos*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCallForwardResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCallWaitingResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*enable*/,
+ int32_t /*serviceClass*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCallWaitingResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeLastIncomingGsmSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::acceptCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::deactivateDataCallResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getFacilityLockForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, int32_t /*response*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setFacilityLockForAppResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, int32_t /*retry*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setBarringPasswordResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getNetworkSelectionModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*manual*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeAutomaticResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeManualResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAvailableNetworksResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<OperatorInfo>& /*networkInfos*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startDtmfResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopDtmfResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getBasebandVersionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*version*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::separateConnectionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setMuteResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getMuteResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*enable*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getClipResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ ClipStatus /*status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+ /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendOemRilRequestRawResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendOemRilRequestStringsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& /*data*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSuppServiceNotificationsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::writeSmsToSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, int32_t /*index*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::deleteSmsOnSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setBandModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAvailableBandModesResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<RadioBandMode>& /*bandModes*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendEnvelopeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*commandResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendTerminalResponseToSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::handleStkCallSetupRequestFromSimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::explicitCallTransferResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredNetworkTypeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredNetworkTypeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ PreferredNetworkType /*nw_type*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getNeighboringCidsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<NeighboringCell>& /*cells*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLocationUpdatesResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaSubscriptionSourceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaRoamingPreferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaRoamingPreferenceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ CdmaRoamingType /*type*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setTTYModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getTTYModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, TtyMode /*mode*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredVoicePrivacyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredVoicePrivacyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*enable*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCDMAFeatureCodeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendBurstDtmfResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeLastIncomingCdmaSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getGsmBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setGsmBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setGsmBroadcastActivationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaBroadcastConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaBroadcastActivationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCDMASubscriptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*mdn*/,
+ const ::android::hardware::hidl_string& /*hSid*/,
+ const ::android::hardware::hidl_string& /*hNid*/,
+ const ::android::hardware::hidl_string& /*min*/,
+ const ::android::hardware::hidl_string& /*prl*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::writeSmsToRuimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, uint32_t /*index*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::deleteSmsOnRuimResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDeviceIdentityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*imei*/,
+ const ::android::hardware::hidl_string& /*imeisv*/,
+ const ::android::hardware::hidl_string& /*esn*/,
+ const ::android::hardware::hidl_string& /*meid*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::exitEmergencyCallbackModeResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSmscAddressResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*smsc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSmscAddressResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::reportSmsMemoryStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::reportStkServiceIsRunningResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaSubscriptionSourceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ CdmaSubscriptionSource /*source*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestIsimAuthenticationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*response*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeIncomingGsmSmsWithPduResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendEnvelopeWithStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const IccIoResult& /*iccIo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRadioTechnologyResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_0::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCellInfoListRateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setInitialAttachApnResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getImsRegistrationStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*isRegistered*/,
+ RadioTechnologyFamily /*ratFamily*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendImsSmsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccTransmitApduBasicChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccOpenLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, int32_t /*channelId*/,
+ const ::android::hardware::hidl_vec<int8_t>& /*selectResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccCloseLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccTransmitApduLogicalChannelResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvReadItemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_string& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvWriteItemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvWriteCdmaPrlResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvResetConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setUiccSubscriptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataAllowedResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getHardwareConfigResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<HardwareConfig>& /*config*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestIccSimAuthenticationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const IccIoResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataProfileResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestShutdownResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getRadioCapabilityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioCapabilityResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startLceServiceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const LceStatusInfo& /*statusInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopLceServiceResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const LceStatusInfo& /*statusInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::pullLceDataResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const LceDataInfo& /*lceInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getModemActivityInfoResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ActivityStatsInfo& /*activityInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setAllowedCarriersResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ int32_t /*numAllowed*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAllowedCarriersResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*allAllowed*/,
+ const CarrierRestrictions& /*carriers*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendDeviceStateResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setIndicationFilterResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSimCardPowerResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeRequest(int32_t /*serial*/) {
+ return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioResponse_v1_6::setCarrierInfoForImsiEncryptionResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSimCardPowerResponse_1_1(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopNetworkScanResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startKeepaliveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const KeepaliveStatus& /*status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopKeepaliveResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioResponse_v1_6::setSignalStrengthReportingCriteriaResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLinkCapacityReportingCriteriaResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::CardStatus& /*card_status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCurrentCallsResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& /*calls*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::SignalStrength& /*sig_strength*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_4::SignalStrength& /*sig_strength*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_2::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_2(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_2::DataRegStateResult& /*dataRegResponse*/) {
+ return Void();
+}
+
+/* 1.3 Apis */
+Return<void> RadioResponse_v1_6::setSystemSelectionChannelsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::enableModemResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getModemStackStatusResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const bool /*enabled*/) {
+ return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioResponse_v1_6::emergencyDialResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_4::DataRegStateResult& /*dataRegResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_4::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_4::CardStatus& /*card_status*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_bitfield<
+ ::android::hardware::radio::V1_4::RadioAccessFamily>
+ /*networkTypeBitmap*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::SetupDataCallResult>&
+ /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_4::SetupDataCallResult& /*dcResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setAllowedCarriersResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAllowedCarriersResponse_1_4(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const CarrierRestrictionsWithPriority& /*carriers*/,
+ SimLockMultiSimPolicy /*multiSimPolicy*/) {
+ return Void();
+}
+
+/* 1.5 Apis */
+Return<void> RadioResponse_v1_6::setSignalStrengthReportingCriteriaResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLinkCapacityReportingCriteriaResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::enableUiccApplicationsResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::areUiccApplicationsEnabledResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*enabled*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::canToggleUiccApplicationsEnablementResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/, bool /*canToggle*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSystemSelectionChannelsResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const android::hardware::radio::V1_5::SetupDataCallResult& /* dcResponse */) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& /* dcResponse */) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setInitialAttachApnResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataProfileResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioPowerResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setIndicationFilterResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getBarringInfoResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+ /*barringInfos*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::radio::V1_5::CellInfo>& /*cellInfo*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeManualResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsExpectMoreResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ const SendSmsResult& /*sms*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplySimDepersonalizationResponse(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/,
+ ::android::hardware::radio::V1_5::PersoSubstate /*persoType*/,
+ int32_t /*remainingRetries*/) {
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_5(
+ const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::CardStatus& card_status) {
+ rspInfo_v1_0 = info;
+ cardStatus = card_status;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+/* 1.6 Apis */
+Return<void> RadioResponse_v1_6::setRadioPowerResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const android::hardware::radio::V1_6::SetupDataCallResult& /* dcResponse */) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+Return<void> RadioResponse_v1_6::setNrDualConnectivityStateResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const hidl_vec<::android::hardware::radio::V1_6::SetupDataCallResult>& /* dcResponse */) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSmsResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSMSExpectMoreResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSimCardPowerResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsExpectMoreResponse_1_6(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::isNrDualConnectivityEnabledResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info, bool isEnabled) {
+ rspInfo = info;
+ isNRDualConnectivityEnabled = isEnabled;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::allocatePduSessionIdResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info, int32_t id) {
+ rspInfo = info;
+ allocatedPduSessionId = id;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::releasePduSessionIdResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::startHandoverResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::cancelHandoverResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setAllowedNetworkTypeBitmapResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataThrottlingResponse(
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_6.notify(info.serial);
+ return Void();
+}
diff --git a/radio/1.6/vts/functional/vts_test_util_v1_6.cpp b/radio/1.6/vts/functional/vts_test_util_v1_6.cpp
new file mode 100644
index 0000000..2653865
--- /dev/null
+++ b/radio/1.6/vts/functional/vts_test_util_v1_6.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "RadioTest"
+
+#include <vts_test_util_v1_6.h>
+#include <iostream>
+#include "VtsCoreUtil.h"
+
+::testing::AssertionResult CheckAnyOfErrors(
+ ::android::hardware::radio::V1_6::RadioError err,
+ std::vector<::android::hardware::radio::V1_6::RadioError> errors, CheckFlag flag) {
+ const static vector<::android::hardware::radio::V1_6::RadioError> generalErrors = {
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::NO_MEMORY,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::SYSTEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::CANCELLED};
+ if (flag == CHECK_GENERAL_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+ for (size_t i = 0; i < generalErrors.size(); i++) {
+ if (err == generalErrors[i]) {
+ return testing::AssertionSuccess();
+ }
+ }
+ }
+ if (flag == CHECK_OEM_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+ if (err >= ::android::hardware::radio::V1_6::RadioError::OEM_ERROR_1 &&
+ err <= ::android::hardware::radio::V1_6::RadioError::OEM_ERROR_25) {
+ return testing::AssertionSuccess();
+ }
+ }
+ for (size_t i = 0; i < errors.size(); i++) {
+ if (err == errors[i]) {
+ return testing::AssertionSuccess();
+ }
+ }
+ return testing::AssertionFailure() << "RadioError:" + toString(err) + " is returned";
+}
diff --git a/radio/1.6/vts/functional/vts_test_util_v1_6.h b/radio/1.6/vts/functional/vts_test_util_v1_6.h
new file mode 100644
index 0000000..e04d201
--- /dev/null
+++ b/radio/1.6/vts/functional/vts_test_util_v1_6.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/radio/1.6/types.h>
+
+#include "vts_test_util.h"
+
+/*
+ * Check multiple radio error codes which are possibly returned because of the different
+ * vendor/devices implementations. It allows optional checks for general errors or/and oem errors.
+ */
+::testing::AssertionResult CheckAnyOfErrors(
+ ::android::hardware::radio::V1_6::RadioError err,
+ std::vector<::android::hardware::radio::V1_6::RadioError> generalError,
+ CheckFlag flag = CHECK_DEFAULT);
diff --git a/radio/config/1.0/Android.bp b/radio/config/1.0/Android.bp
index 387f953..eea4c34 100644
--- a/radio/config/1.0/Android.bp
+++ b/radio/config/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio.config@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadioConfig.hal",
diff --git a/radio/config/1.0/vts/functional/VtsHalRadioConfigV1_0TargetTest.cpp b/radio/config/1.0/vts/functional/VtsHalRadioConfigV1_0TargetTest.cpp
index b3fae86..648b63a 100644
--- a/radio/config/1.0/vts/functional/VtsHalRadioConfigV1_0TargetTest.cpp
+++ b/radio/config/1.0/vts/functional/VtsHalRadioConfigV1_0TargetTest.cpp
@@ -16,6 +16,7 @@
#include <radio_config_hidl_hal_utils.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, RadioConfigHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IRadioConfig::descriptor)),
diff --git a/tests/bar/1.0/.hidl_for_test b/radio/config/1.1/.hidl_for_system_ext
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to radio/config/1.1/.hidl_for_system_ext
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 1e9071a..69d9a83 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio.config@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadioConfig.hal",
@@ -18,4 +15,5 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ system_ext_specific: true,
}
diff --git a/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
index b3fae86..648b63a 100644
--- a/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
+++ b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
@@ -16,6 +16,7 @@
#include <radio_config_hidl_hal_utils.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, RadioConfigHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IRadioConfig::descriptor)),
diff --git a/tests/bar/1.0/.hidl_for_test b/radio/config/1.2/.hidl_for_system_ext
similarity index 100%
copy from tests/bar/1.0/.hidl_for_test
copy to radio/config/1.2/.hidl_for_system_ext
diff --git a/radio/config/1.2/Android.bp b/radio/config/1.2/Android.bp
index 812f166..f751868 100644
--- a/radio/config/1.2/Android.bp
+++ b/radio/config/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio.config@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IRadioConfigIndication.hal",
@@ -18,4 +15,5 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ system_ext_specific: true,
}
diff --git a/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp
index f09ac3a..c92ef69 100644
--- a/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp
+++ b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp
@@ -16,6 +16,7 @@
#include <radio_config_hidl_hal_utils.h>
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, RadioConfigHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IRadioConfig::descriptor)),
diff --git a/radio/deprecated/1.0/Android.bp b/radio/deprecated/1.0/Android.bp
index cb13b86..1a7cb94 100644
--- a/radio/deprecated/1.0/Android.bp
+++ b/radio/deprecated/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.radio.deprecated@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IOemHook.hal",
"IOemHookIndication.hal",
diff --git a/rebootescrow/aidl/default/RebootEscrow.cpp b/rebootescrow/aidl/default/RebootEscrow.cpp
index dbc0921..8e5e97c 100644
--- a/rebootescrow/aidl/default/RebootEscrow.cpp
+++ b/rebootescrow/aidl/default/RebootEscrow.cpp
@@ -28,7 +28,7 @@
using ::android::base::unique_fd;
-ndk::ScopedAStatus RebootEscrow::storeKey(const std::vector<int8_t>& kek) {
+ndk::ScopedAStatus RebootEscrow::storeKey(const std::vector<uint8_t>& ukek) {
int rawFd = TEMP_FAILURE_RETRY(::open(devicePath_.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
unique_fd fd(rawFd);
if (fd.get() < 0) {
@@ -36,7 +36,6 @@
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
}
- std::vector<uint8_t> ukek(kek.begin(), kek.end());
auto encoded = hadamard::EncodeKey(ukek);
if (!::android::base::WriteFully(fd, encoded.data(), encoded.size())) {
@@ -47,7 +46,7 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus RebootEscrow::retrieveKey(std::vector<int8_t>* _aidl_return) {
+ndk::ScopedAStatus RebootEscrow::retrieveKey(std::vector<uint8_t>* _aidl_return) {
int rawFd = TEMP_FAILURE_RETRY(::open(devicePath_.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
unique_fd fd(rawFd);
if (fd.get() < 0) {
@@ -63,8 +62,7 @@
auto keyBytes = hadamard::DecodeKey(encodedBytes);
- std::vector<int8_t> signedKeyBytes(keyBytes.begin(), keyBytes.end());
- *_aidl_return = signedKeyBytes;
+ *_aidl_return = keyBytes;
return ndk::ScopedAStatus::ok();
}
diff --git a/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h b/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
index 00ff16b..cdbeb67 100644
--- a/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
+++ b/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
@@ -26,8 +26,8 @@
class RebootEscrow : public BnRebootEscrow {
public:
explicit RebootEscrow(const std::string& devicePath) : devicePath_(devicePath) {}
- ndk::ScopedAStatus storeKey(const std::vector<int8_t>& kek) override;
- ndk::ScopedAStatus retrieveKey(std::vector<int8_t>* _aidl_return) override;
+ ndk::ScopedAStatus storeKey(const std::vector<uint8_t>& kek) override;
+ ndk::ScopedAStatus retrieveKey(std::vector<uint8_t>* _aidl_return) override;
private:
const std::string devicePath_;
diff --git a/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp b/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
index 5e5776c..ddd99fb 100644
--- a/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
+++ b/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
@@ -34,6 +34,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RenderscriptHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, RenderscriptHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDevice::descriptor)),
diff --git a/secure_element/1.0/Android.bp b/secure_element/1.0/Android.bp
index 32b752b..a32b9d1 100644
--- a/secure_element/1.0/Android.bp
+++ b/secure_element/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.secure_element@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISecureElement.hal",
diff --git a/secure_element/1.0/vts/functional/AndroidTest.xml b/secure_element/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..4724f23
--- /dev/null
+++ b/secure_element/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalSecureElementV1_0TargetTest->/data/local/tmp/VtsHalSecureElementV1_0TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalSecureElementV1_0TargetTest" />
+ </test>
+</configuration>
diff --git a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
index 93ffd05..63c2eca 100644
--- a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
+++ b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
@@ -204,6 +204,7 @@
EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SecureElementHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISecureElement::descriptor)),
diff --git a/secure_element/1.1/Android.bp b/secure_element/1.1/Android.bp
index 3ea2de9..08e6c88 100644
--- a/secure_element/1.1/Android.bp
+++ b/secure_element/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.secure_element@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ISecureElement.hal",
"ISecureElementHalCallback.hal",
diff --git a/secure_element/1.1/vts/functional/AndroidTest.xml b/secure_element/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3d7b715
--- /dev/null
+++ b/secure_element/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_1TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalSecureElementV1_1TargetTest->/data/local/tmp/VtsHalSecureElementV1_1TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalSecureElementV1_1TargetTest" />
+ </test>
+</configuration>
diff --git a/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
index 66fc47c..234c33c 100644
--- a/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
+++ b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
@@ -88,6 +88,7 @@
EXPECT_TRUE(se_->isCardPresent());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SecureElementHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISecureElement::descriptor)),
diff --git a/secure_element/1.2/Android.bp b/secure_element/1.2/Android.bp
index e134771..03df5f9 100644
--- a/secure_element/1.2/Android.bp
+++ b/secure_element/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.secure_element@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ISecureElement.hal",
],
diff --git a/secure_element/1.2/vts/functional/AndroidTest.xml b/secure_element/1.2/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..0bd8061
--- /dev/null
+++ b/secure_element/1.2/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_2TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalSecureElementV1_2TargetTest->/data/local/tmp/VtsHalSecureElementV1_2TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalSecureElementV1_2TargetTest" />
+ </test>
+</configuration>
diff --git a/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp b/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
index 9392f14..66d581e 100644
--- a/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
+++ b/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
@@ -100,6 +100,7 @@
EXPECT_TRUE(res.args->state_);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SecureElementHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISecureElement::descriptor)),
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
index 509f72f..1093671 100644
--- a/sensors/1.0/Android.bp
+++ b/sensors/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.sensors@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISensors.hal",
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index e298651..56bc9cf 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -448,6 +448,7 @@
RateLevel::VERY_FAST, NullChecker<Event>());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SensorsHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISensors::descriptor)),
diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp
index c8517c8..d71f07b 100644
--- a/sensors/2.0/Android.bp
+++ b/sensors/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.sensors@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISensors.hal",
diff --git a/sensors/2.0/default/SensorsV2_0.h b/sensors/2.0/default/SensorsV2_0.h
index 345835a..8270a35 100644
--- a/sensors/2.0/default/SensorsV2_0.h
+++ b/sensors/2.0/default/SensorsV2_0.h
@@ -28,6 +28,19 @@
namespace implementation {
struct SensorsV2_0 : public ::android::hardware::sensors::V2_X::implementation::Sensors<ISensors> {
+ Return<void>
+ getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override {
+ std::vector<V1_0::SensorInfo> sensors;
+ for (const auto &sensor : mSensors) {
+ sensors.push_back(V2_1::implementation::convertToOldSensorInfo(
+ sensor.second->getSensorInfo()));
+ }
+
+ // Call the HIDL callback with the SensorInfo
+ _hidl_cb(sensors);
+
+ return Void();
+ }
};
} // namespace implementation
diff --git a/sensors/2.1/Android.bp b/sensors/2.1/Android.bp
index 8e80e1f..9ba3248 100644
--- a/sensors/2.1/Android.bp
+++ b/sensors/2.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.sensors@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISensors.hal",
diff --git a/sensors/2.1/default/SensorsV2_1.h b/sensors/2.1/default/SensorsV2_1.h
index 9f7fe04..c748383 100644
--- a/sensors/2.1/default/SensorsV2_1.h
+++ b/sensors/2.1/default/SensorsV2_1.h
@@ -54,6 +54,23 @@
// Methods from ::android::hardware::sensors::V2_1::ISensors follow.
Return<void> getSensorsList_2_1(ISensors::getSensorsList_2_1_cb _hidl_cb) override;
+ Return<void>
+ getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override {
+ std::vector<V1_0::SensorInfo> sensors;
+ for (const auto &sensor : mSensors) {
+ auto &info = sensor.second->getSensorInfo();
+ if (info.type != SensorType::HINGE_ANGLE) {
+ sensors.push_back(V2_1::implementation::convertToOldSensorInfo(
+ sensor.second->getSensorInfo()));
+ }
+ }
+
+ // Call the HIDL callback with the SensorInfo
+ _hidl_cb(sensors);
+
+ return Void();
+ }
+
Return<Result> initialize_2_1(
const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
@@ -71,4 +88,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_SENSORS_V2_1_H
\ No newline at end of file
+#endif // ANDROID_HARDWARE_SENSORS_V2_1_H
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 1841dff..870980f 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -57,11 +57,11 @@
return mSensorInfo;
}
-void Sensor::batch(int32_t samplingPeriodNs) {
- if (samplingPeriodNs < mSensorInfo.minDelay * 1000) {
- samplingPeriodNs = mSensorInfo.minDelay * 1000;
- } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000) {
- samplingPeriodNs = mSensorInfo.maxDelay * 1000;
+void Sensor::batch(int64_t samplingPeriodNs) {
+ if (samplingPeriodNs < mSensorInfo.minDelay * 1000ll) {
+ samplingPeriodNs = mSensorInfo.minDelay * 1000ll;
+ } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000ll) {
+ samplingPeriodNs = mSensorInfo.maxDelay * 1000ll;
}
if (mSamplingPeriodNs != samplingPeriodNs) {
@@ -133,6 +133,11 @@
}
std::vector<Event> Sensor::readEvents() {
+ // For an accelerometer sensor type, default the z-direction
+ // value to -9.8
+ float zValue = (mSensorInfo.type == SensorType::ACCELEROMETER)
+ ? -9.8 : 0.0;
+
std::vector<Event> events;
Event event;
event.sensorHandle = mSensorInfo.sensorHandle;
@@ -140,7 +145,7 @@
event.timestamp = ::android::elapsedRealtimeNano();
event.u.vec3.x = 0;
event.u.vec3.y = 0;
- event.u.vec3.z = 0;
+ event.u.vec3.z = zValue;
event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
events.push_back(event);
return events;
@@ -330,25 +335,6 @@
mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
};
-DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
- : OnChangeSensor(callback) {
- mSensorInfo.sensorHandle = sensorHandle;
- mSensorInfo.name = "Device Temp Sensor";
- mSensorInfo.vendor = "Vendor String";
- mSensorInfo.version = 1;
- mSensorInfo.type = SensorType::TEMPERATURE;
- mSensorInfo.typeAsString = "";
- mSensorInfo.maxRange = 80.0f;
- mSensorInfo.resolution = 0.01f;
- mSensorInfo.power = 0.001f;
- mSensorInfo.minDelay = 40 * 1000; // microseconds
- mSensorInfo.maxDelay = kDefaultMaxDelayUs;
- mSensorInfo.fifoReservedEventCount = 0;
- mSensorInfo.fifoMaxEventCount = 0;
- mSensorInfo.requiredPermission = "";
- mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
-}
-
RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
ISensorsEventCallback* callback)
: OnChangeSensor(callback) {
diff --git a/sensors/common/default/2.X/Sensor.h b/sensors/common/default/2.X/Sensor.h
index 2f8a143..a792797 100644
--- a/sensors/common/default/2.X/Sensor.h
+++ b/sensors/common/default/2.X/Sensor.h
@@ -32,7 +32,7 @@
namespace V2_X {
namespace implementation {
-static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000;
+static constexpr int32_t kDefaultMaxDelayUs = 10 * 1000 * 1000;
class ISensorsEventCallback {
public:
@@ -54,7 +54,7 @@
virtual ~Sensor();
const SensorInfo& getSensorInfo() const;
- void batch(int32_t samplingPeriodNs);
+ void batch(int64_t samplingPeriodNs);
virtual void activate(bool enable);
Result flush();
@@ -113,11 +113,6 @@
AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
-class DeviceTempSensor : public OnChangeSensor {
- public:
- DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
-};
-
class PressureSensor : public Sensor {
public:
PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
diff --git a/sensors/common/default/2.X/Sensors.h b/sensors/common/default/2.X/Sensors.h
index ee8240d..1124425 100644
--- a/sensors/common/default/2.X/Sensors.h
+++ b/sensors/common/default/2.X/Sensors.h
@@ -64,7 +64,6 @@
AddSensor<AccelSensor>();
AddSensor<GyroSensor>();
AddSensor<AmbientTempSensor>();
- AddSensor<DeviceTempSensor>();
AddSensor<PressureSensor>();
AddSensor<MagnetometerSensor>();
AddSensor<LightSensor>();
@@ -79,19 +78,6 @@
}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
- Return<void> getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override {
- std::vector<V1_0::SensorInfo> sensors;
- for (const auto& sensor : mSensors) {
- sensors.push_back(
- V2_1::implementation::convertToOldSensorInfo(sensor.second->getSensorInfo()));
- }
-
- // Call the HIDL callback with the SensorInfo
- _hidl_cb(sensors);
-
- return Void();
- }
-
Return<Result> setOperationMode(OperationMode mode) override {
for (auto sensor : mSensors) {
sensor.second->setOperationMode(mode);
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index fe3fc84..f5fc066 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -124,7 +124,9 @@
Return<void> HalProxy::getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) {
std::vector<V1_0::SensorInfo> sensors;
for (const auto& iter : mSensors) {
+ if (iter.second.type != SensorType::HINGE_ANGLE) {
sensors.push_back(convertToOldSensorInfo(iter.second));
+ }
}
_hidl_cb(sensors);
return Void();
@@ -341,7 +343,7 @@
return Void();
}
- android::base::borrowed_fd writeFd = dup(fd->data[0]);
+ int writeFd = fd->data[0];
std::ostringstream stream;
stream << "===HalProxy===" << std::endl;
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
index 1efd971..69debb6 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
@@ -71,9 +71,10 @@
return mSensorInfo;
}
-void Sensor::batch(int32_t samplingPeriodNs) {
- samplingPeriodNs =
- std::clamp(samplingPeriodNs, mSensorInfo.minDelay * 1000, mSensorInfo.maxDelay * 1000);
+void Sensor::batch(int64_t samplingPeriodNs) {
+ samplingPeriodNs = std::clamp(samplingPeriodNs,
+ static_cast<int64_t>(mSensorInfo.minDelay) * 1000,
+ static_cast<int64_t>(mSensorInfo.maxDelay) * 1000);
if (mSamplingPeriodNs != samplingPeriodNs) {
mSamplingPeriodNs = samplingPeriodNs;
@@ -323,17 +324,6 @@
mSensorInfo.minDelay = 40 * 1000; // microseconds
}
-DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
- : ContinuousSensor(sensorHandle, callback) {
- mSensorInfo.name = "Device Temp Sensor";
- mSensorInfo.type = SensorType::TEMPERATURE;
- mSensorInfo.typeAsString = SENSOR_STRING_TYPE_TEMPERATURE;
- mSensorInfo.maxRange = 80.0f;
- mSensorInfo.resolution = 0.01f;
- mSensorInfo.power = 0.001f;
- mSensorInfo.minDelay = 40 * 1000; // microseconds
-}
-
RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
ISensorsEventCallback* callback)
: OnChangeSensor(sensorHandle, callback) {
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
index 5cf9f83..08c8647 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
@@ -49,7 +49,7 @@
virtual ~Sensor();
const SensorInfo& getSensorInfo() const;
- void batch(int32_t samplingPeriodNs);
+ void batch(int64_t samplingPeriodNs);
virtual void activate(bool enable);
Result flush();
@@ -114,11 +114,6 @@
std::vector<Event> readEvents() override;
};
-class DeviceTempSensor : public ContinuousSensor {
- public:
- DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
-};
-
class PressureSensor : public ContinuousSensor {
public:
PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
index 1a78e84..353563c 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
@@ -206,7 +206,6 @@
ISensorsSubHalBase::AddSensor<GyroSensor>();
ISensorsSubHalBase::AddSensor<MagnetometerSensor>();
ISensorsSubHalBase::AddSensor<PressureSensor>();
- ISensorsSubHalBase::AddSensor<DeviceTempSensor>();
}
};
@@ -231,7 +230,6 @@
ISensorsSubHalBase::AddSensor<GyroSensor>();
ISensorsSubHalBase::AddSensor<MagnetometerSensor>();
ISensorsSubHalBase::AddSensor<PressureSensor>();
- ISensorsSubHalBase::AddSensor<DeviceTempSensor>();
ISensorsSubHalBase::AddSensor<AmbientTempSensor>();
ISensorsSubHalBase::AddSensor<LightSensor>();
ISensorsSubHalBase::AddSensor<ProximitySensor>();
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 2e5aca4..8cf5003 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -226,6 +226,7 @@
void activateAllSensors(bool enable);
std::vector<SensorInfoType> getNonOneShotSensors();
std::vector<SensorInfoType> getNonOneShotAndNonSpecialSensors();
+ std::vector<SensorInfoType> getNonOneShotAndNonOnChangeAndNonSpecialSensors();
std::vector<SensorInfoType> getOneShotSensors();
std::vector<SensorInfoType> getInjectEventSensors();
int32_t getInvalidSensorHandle();
@@ -326,6 +327,19 @@
return sensors;
}
+std::vector<SensorInfoType> SensorsHidlTest::getNonOneShotAndNonOnChangeAndNonSpecialSensors() {
+ std::vector<SensorInfoType> sensors;
+ for (const SensorInfoType& info : getSensorsList()) {
+ SensorFlagBits reportMode = extractReportMode(info.flags);
+ if (reportMode != SensorFlagBits::ONE_SHOT_MODE &&
+ reportMode != SensorFlagBits::ON_CHANGE_MODE &&
+ reportMode != SensorFlagBits::SPECIAL_REPORTING_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
std::vector<SensorInfoType> SensorsHidlTest::getOneShotSensors() {
std::vector<SensorInfoType> sensors;
for (const SensorInfoType& info : getSensorsList()) {
@@ -352,7 +366,7 @@
for (const SensorInfoType& sensor : getSensorsList()) {
maxHandle = std::max(maxHandle, sensor.sensorHandle);
}
- return maxHandle + 1;
+ return maxHandle + 42;
}
// Test if sensor list returned is valid
@@ -726,8 +740,8 @@
EventCallback callback;
getEnvironment()->registerCallback(&callback);
- // This test is not valid for one-shot or special-report-mode sensors
- const std::vector<SensorInfoType> sensors = getNonOneShotAndNonSpecialSensors();
+ // This test is not valid for one-shot, on-change or special-report-mode sensors
+ const std::vector<SensorInfoType> sensors = getNonOneShotAndNonOnChangeAndNonSpecialSensors();
milliseconds maxMinDelay(0);
for (const SensorInfoType& sensor : sensors) {
milliseconds minDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
@@ -750,10 +764,7 @@
<< " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
<< sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
<< " name=" << sensor.name);
- // Some on-change sensors may not report an event without stimulus
- if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) {
- ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1);
- }
+
if (callback.getEvents(sensor.sensorHandle).size() >= 1) {
lastEventTimestampMap[sensor.sensorHandle] =
callback.getEvents(sensor.sensorHandle).back().timestamp;
@@ -779,10 +790,7 @@
if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
continue;
}
- // Skip on-change sensors that do not consistently report an initial event
- if (callback.getEvents(sensor.sensorHandle).size() < 1) {
- continue;
- }
+
// Ensure that the first event received is not stale by ensuring that its timestamp is
// sufficiently different from the previous event
const EventType newEvent = callback.getEvents(sensor.sensorHandle).front();
@@ -837,7 +845,11 @@
std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem,
int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel) {
char* buffer = mem->getBuffer();
- memset(buffer, 0xff, mem->getSize());
+ size_t size = mem->getSize();
+
+ if (supportsSharedMemType) {
+ memset(buffer, 0xff, size);
+ }
registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
if (supportsSharedMemType) {
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index 03bec87..a8e1996 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -109,7 +109,6 @@
case SensorTypeT::MAGNETIC_FIELD:
case SensorTypeT::ORIENTATION:
case SensorTypeT::PRESSURE:
- case SensorTypeT::TEMPERATURE:
case SensorTypeT::GRAVITY:
case SensorTypeT::LINEAR_ACCELERATION:
case SensorTypeT::ROTATION_VECTOR:
@@ -145,6 +144,10 @@
case SensorTypeT::DYNAMIC_SENSOR_META:
return SensorFlagBits::SPECIAL_REPORTING_MODE;
+ case SensorTypeT::TEMPERATURE:
+ ALOGW("Device temperature sensor is deprecated, ignoring for test");
+ return (SensorFlagBits)-1;
+
default:
ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
return (SensorFlagBits)-1;
@@ -334,7 +337,7 @@
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
events1 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment());
- // second collection, without stop sensor
+ // second collection, without stopping the sensor
ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
diff --git a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
index 63edec5..0065dbc 100644
--- a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
+++ b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
@@ -293,6 +293,7 @@
EXPECT_NE(0, hidlReturn);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundTriggerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SoundTriggerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)),
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
index 30173cb..024e0f6 100644
--- a/soundtrigger/2.1/Android.bp
+++ b/soundtrigger/2.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.soundtrigger@2.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ISoundTriggerHw.hal",
"ISoundTriggerHwCallback.hal",
diff --git a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
index 392679d..91b8da8 100644
--- a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
+++ b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
@@ -317,6 +317,7 @@
EXPECT_NE(0, hidlReturn);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundTriggerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SoundTriggerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)),
diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp
index 7556aa4..dbf4f8b 100644
--- a/soundtrigger/2.2/Android.bp
+++ b/soundtrigger/2.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.soundtrigger@2.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ISoundTriggerHw.hal",
],
diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
index 1cce5a1..1352ca5 100644
--- a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
+++ b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
@@ -67,6 +67,7 @@
EXPECT_TRUE(hidlReturn.isOk());
EXPECT_EQ(-ENOSYS, hidlReturn);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundTriggerHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, SoundTriggerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)),
diff --git a/soundtrigger/2.3/Android.bp b/soundtrigger/2.3/Android.bp
index 3253a86..480df4d 100644
--- a/soundtrigger/2.3/Android.bp
+++ b/soundtrigger/2.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.soundtrigger@2.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISoundTriggerHw.hal",
diff --git a/tests/baz/1.0/.hidl_for_test b/tests/baz/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/baz/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/baz/1.0/IBase.hal b/tests/baz/1.0/IBase.hal
index 0c1b61f..7b60a8a 100644
--- a/tests/baz/1.0/IBase.hal
+++ b/tests/baz/1.0/IBase.hal
@@ -101,6 +101,8 @@
DoubleThreeDim double3;
};
+ isJava() generates (bool isJava);
+
someBaseMethod();
someBoolMethod(bool x) generates (bool y);
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 7855446..8be1d61 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -94,7 +94,7 @@
int8_t[7] array;
string oneString;
vec<string> vectorOfStrings;
- IBase dummy;
+ interface iface;
};
oneway doThis(float param);
diff --git a/tests/baz/1.0/default/Baz.cpp b/tests/baz/1.0/default/Baz.cpp
index 2ce096c..0c3a59e 100644
--- a/tests/baz/1.0/default/Baz.cpp
+++ b/tests/baz/1.0/default/Baz.cpp
@@ -43,6 +43,12 @@
}
// Methods from ::android::hardware::tests::baz::V1_0::IBase follow.
+Return<bool> Baz::isJava() {
+ LOG(INFO) << "Baz::isJava";
+
+ return false;
+}
+
Return<void> Baz::someBaseMethod() {
LOG(INFO) << "Baz::someBaseMethod";
@@ -331,7 +337,7 @@
Return<IBaz::SomeEnum> Baz::useAnEnum(IBaz::SomeEnum zzz) {
LOG(INFO) << "useAnEnum " << (int)zzz;
- return SomeEnum::goober;
+ return SomeEnum::quux;
}
Return<void> Baz::haveSomeStrings(const hidl_array<hidl_string, 3>& array,
diff --git a/tests/baz/1.0/default/Baz.h b/tests/baz/1.0/default/Baz.h
index 1e24d52..38bbcad 100644
--- a/tests/baz/1.0/default/Baz.h
+++ b/tests/baz/1.0/default/Baz.h
@@ -27,6 +27,7 @@
struct Baz : public IBaz {
// Methods from ::android::hardware::tests::baz::V1_0::IBase follow.
+ Return<bool> isJava() override;
Return<void> someBaseMethod() override;
Return<bool> someBoolMethod(bool x) override;
Return<void> someBoolArrayMethod(const hidl_array<bool, 3>& x,
diff --git a/tests/expression/1.0/.hidl_for_test b/tests/expression/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/expression/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/extension/light/2.0/.hidl_for_test b/tests/extension/light/2.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/extension/light/2.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/foo/1.0/.hidl_for_test b/tests/foo/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/foo/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4c54427..e242616 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -21,6 +21,7 @@
import ISimple;
import ITheirTypes.FloatArray;
+@SensitiveData // for test
interface IFoo {
enum SomeBaseEnum : uint8_t {
diff --git a/tests/hash/1.0/.hidl_for_test b/tests/hash/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/hash/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/inheritance/1.0/.hidl_for_test b/tests/inheritance/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/inheritance/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/lazy/1.0/.hidl_for_test b/tests/lazy/1.0/.hidl_for_system_ext
similarity index 100%
rename from tests/lazy/1.0/.hidl_for_test
rename to tests/lazy/1.0/.hidl_for_system_ext
diff --git a/tests/lazy/1.0/.hidl_for_test b/tests/lazy/1.1/.hidl_for_system_ext
similarity index 100%
copy from tests/lazy/1.0/.hidl_for_test
copy to tests/lazy/1.1/.hidl_for_system_ext
diff --git a/tests/lazy/1.1/Android.bp b/tests/lazy/1.1/Android.bp
new file mode 100644
index 0000000..ccedd8d
--- /dev/null
+++ b/tests/lazy/1.1/Android.bp
@@ -0,0 +1,15 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.tests.lazy@1.1",
+ root: "android.hardware",
+ system_ext_specific: true,
+ srcs: [
+ "ILazy.hal",
+ ],
+ interfaces: [
+ "android.hardware.tests.lazy@1.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/tests/lazy/1.1/ILazy.hal
similarity index 73%
rename from tests/safeunion/1.0/IOtherInterface.hal
rename to tests/lazy/1.1/ILazy.hal
index cdaf847..a15e0e3 100644
--- a/tests/safeunion/1.0/IOtherInterface.hal
+++ b/tests/lazy/1.1/ILazy.hal
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-package android.hardware.tests.safeunion@1.0;
+package android.hardware.tests.lazy@1.1;
-interface IOtherInterface {
- concatTwoStrings(string a, string b) generates (string result);
-};
+import android.hardware.tests.lazy@1.0;
+
+interface ILazy extends @1.0::ILazy {};
diff --git a/tests/libhwbinder/1.0/.hidl_for_test b/tests/libhwbinder/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/libhwbinder/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/libhwbinder/aidl/.hidl_for_test b/tests/libhwbinder/aidl/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/libhwbinder/aidl/.hidl_for_test
+++ /dev/null
diff --git a/tests/memory/1.0/.hidl_for_test b/tests/memory/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/memory/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/memory/2.0/.hidl_for_test b/tests/memory/2.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/memory/2.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/msgq/1.0/.hidl_for_test b/tests/msgq/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/msgq/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index 112270a..bd10237 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -31,7 +31,7 @@
*
* @return ret True if the setup is successful.
*/
- configureFmqSyncReadWrite(fmq_sync<uint16_t> mqDesc) generates(bool ret);
+ configureFmqSyncReadWrite(fmq_sync<int32_t> mqDesc) generates(bool ret);
/**
* This method requests the service to return an MQDescriptor to
@@ -46,7 +46,7 @@
* @return mqDesc This structure describes the unsynchronized FMQ that was
* set up by the service. Client can use it to set up the FMQ at its end.
*/
- getFmqUnsyncWrite(bool configureFmq) generates(bool ret, fmq_unsync<uint16_t> mqDesc);
+ getFmqUnsyncWrite(bool configureFmq) generates(bool ret, fmq_unsync<int32_t> mqDesc);
/**
* This method request the service to write into the synchronized read/write
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index e6408aa..6e7cd44 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -19,7 +19,7 @@
relative_install_path: "hw",
srcs: [
"TestMsgQ.cpp",
- "BenchmarkMsgQ.cpp"
+ "BenchmarkMsgQ.cpp",
],
shared_libs: [
"libbase",
@@ -34,7 +34,7 @@
// libs should be used on device.
static_libs: [
"android.hardware.tests.msgq@1.0",
- ]
+ ],
}
cc_test {
@@ -49,7 +49,7 @@
"libhidlbase",
"liblog",
"libutils",
- "android.hardware.tests.msgq@1.0"
+ "android.hardware.tests.msgq@1.0",
],
test_suites: ["general-tests"],
}
@@ -67,14 +67,36 @@
"libhidlbase",
"liblog",
"libutils",
+ "libbinder_ndk",
],
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ auto_gen_config: false,
+
// Allow dlsym'ing self for statically linked passthrough implementations
ldflags: ["-rdynamic"],
// These are static libs only for testing purposes and portability. Shared
// libs should be used on device.
- static_libs: ["android.hardware.tests.msgq@1.0"],
- whole_static_libs: ["android.hardware.tests.msgq@1.0-impl"],
- test_suites: ["general-tests"],
+ static_libs: [
+ "android.hardware.tests.msgq@1.0",
+ "android.fmq.test-ndk_platform",
+ "android.hardware.common.fmq-unstable-ndk_platform",
+ ],
+ whole_static_libs: [
+ "android.hardware.tests.msgq@1.0-impl",
+ "android.fmq.test-impl",
+ ],
}
diff --git a/tests/msgq/1.0/default/TestMsgQ.cpp b/tests/msgq/1.0/default/TestMsgQ.cpp
index ba665c9..4473737 100644
--- a/tests/msgq/1.0/default/TestMsgQ.cpp
+++ b/tests/msgq/1.0/default/TestMsgQ.cpp
@@ -25,7 +25,7 @@
// Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
Return<bool> TestMsgQ::configureFmqSyncReadWrite(
- const android::hardware::MQDescriptorSync<uint16_t>& mqDesc) {
+ const android::hardware::MQDescriptorSync<int32_t>& mqDesc) {
mFmqSynchronized.reset(new (std::nothrow) MessageQueueSync(mqDesc));
if ((mFmqSynchronized == nullptr) || (mFmqSynchronized->isValid() == false)) {
return false;
@@ -56,7 +56,7 @@
}
Return<bool> TestMsgQ::requestWriteFmqSync(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
for (int i = 0; i < count; i++) {
data[i] = i;
}
@@ -65,14 +65,14 @@
}
Return<bool> TestMsgQ::requestReadFmqSync(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
bool result = mFmqSynchronized->read(&data[0], count)
&& verifyData(&data[0], count);
return result;
}
Return<bool> TestMsgQ::requestWriteFmqUnsync(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
for (int i = 0; i < count; i++) {
data[i] = i;
}
@@ -81,14 +81,14 @@
}
Return<bool> TestMsgQ::requestReadFmqUnsync(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
bool result =
mFmqUnsynchronized->read(&data[0], count) && verifyData(&data[0], count);
return result;
}
Return<void> TestMsgQ::requestBlockingRead(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
bool result = mFmqSynchronized->readBlocking(
&data[0],
count,
@@ -103,7 +103,7 @@
}
Return<void> TestMsgQ::requestBlockingReadDefaultEventFlagBits(int32_t count) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
bool result = mFmqSynchronized->readBlocking(
&data[0],
count);
@@ -116,7 +116,7 @@
}
Return<void> TestMsgQ::requestBlockingReadRepeat(int32_t count, int32_t numIter) {
- std::vector<uint16_t> data(count);
+ std::vector<int32_t> data(count);
for (int i = 0; i < numIter; i++) {
bool result = mFmqSynchronized->readBlocking(
&data[0],
diff --git a/tests/msgq/1.0/default/TestMsgQ.h b/tests/msgq/1.0/default/TestMsgQ.h
index f9fcddd..8a204b7 100644
--- a/tests/msgq/1.0/default/TestMsgQ.h
+++ b/tests/msgq/1.0/default/TestMsgQ.h
@@ -49,13 +49,13 @@
using android::hardware::MessageQueue;
struct TestMsgQ : public ITestMsgQ {
- typedef MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
- typedef MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+ typedef MessageQueue<int32_t, kSynchronizedReadWrite> MessageQueueSync;
+ typedef MessageQueue<int32_t, kUnsynchronizedWrite> MessageQueueUnsync;
TestMsgQ() : mFmqSynchronized(nullptr), mFmqUnsynchronized(nullptr) {}
// Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
- Return<bool> configureFmqSyncReadWrite(const MQDescriptorSync<uint16_t>& mqDesc) override;
+ Return<bool> configureFmqSyncReadWrite(const MQDescriptorSync<int32_t>& mqDesc) override;
Return<void> getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) override;
Return<bool> requestWriteFmqSync(int32_t count) override;
Return<bool> requestReadFmqSync(int32_t count) override;
@@ -73,7 +73,7 @@
/*
* Utility function to verify data read from the fast message queue.
*/
- bool verifyData(uint16_t* data, int count) {
+ bool verifyData(int32_t* data, int count) {
for (int i = 0; i < count; i++) {
if (data[i] != i) return false;
}
diff --git a/tests/msgq/1.0/default/mq_test_service.cpp b/tests/msgq/1.0/default/mq_test_service.cpp
index b5cb662..72ffe41 100644
--- a/tests/msgq/1.0/default/mq_test_service.cpp
+++ b/tests/msgq/1.0/default/mq_test_service.cpp
@@ -16,13 +16,32 @@
#define LOG_TAG "FMQ_UnitTests"
+#include <TestAidlMsgQ.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
+using aidl::android::fmq::test::TestAidlMsgQ;
+
#include <hidl/LegacySupport.h>
using android::hardware::tests::msgq::V1_0::ITestMsgQ;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
- return defaultPassthroughServiceImplementation<ITestMsgQ>();
+ android::hardware::details::setTrebleTestingOverride(true);
+ // Register AIDL service
+ ABinderProcess_startThreadPool();
+ std::shared_ptr<TestAidlMsgQ> store = ndk::SharedRefBase::make<TestAidlMsgQ>();
+
+ const std::string instance = std::string() + TestAidlMsgQ::descriptor + "/default";
+ LOG(INFO) << "instance: " << instance;
+ CHECK(AServiceManager_addService(store->asBinder().get(), instance.c_str()) == STATUS_OK);
+
+ // Register HIDL service
+ CHECK(defaultPassthroughServiceImplementation<ITestMsgQ>() == android::OK);
+ ABinderProcess_joinThreadPool();
+
+ return EXIT_FAILURE; // should not reach
}
diff --git a/tests/multithread/1.0/.hidl_for_test b/tests/multithread/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/multithread/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/safeunion/1.0/.hidl_for_test b/tests/safeunion/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/safeunion/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
index 2937832..f1ec267 100644
--- a/tests/safeunion/1.0/Android.bp
+++ b/tests/safeunion/1.0/Android.bp
@@ -4,7 +4,6 @@
name: "android.hardware.tests.safeunion@1.0",
root: "android.hardware",
srcs: [
- "IOtherInterface.hal",
"ISafeUnion.hal",
],
interfaces: [
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
index 58c08c6..01e1727 100644
--- a/tests/safeunion/1.0/ISafeUnion.hal
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -16,8 +16,6 @@
package android.hardware.tests.safeunion@1.0;
-import IOtherInterface;
-
import android.hidl.safe_union@1.0::Monostate;
interface ISafeUnion {
@@ -73,7 +71,7 @@
uint32_t a;
int8_t[7] b;
- IOtherInterface c;
+ interface c;
string d;
vec<string> e;
handle f;
@@ -107,7 +105,7 @@
newInterfaceTypeSafeUnion() generates (InterfaceTypeSafeUnion myUnion);
setInterfaceA(InterfaceTypeSafeUnion myUnion, uint32_t a) generates (InterfaceTypeSafeUnion myUnion);
setInterfaceB(InterfaceTypeSafeUnion myUnion, int8_t[7] b) generates (InterfaceTypeSafeUnion myUnion);
- setInterfaceC(InterfaceTypeSafeUnion myUnion, IOtherInterface c) generates (InterfaceTypeSafeUnion myUnion);
+ setInterfaceC(InterfaceTypeSafeUnion myUnion, interface c) generates (InterfaceTypeSafeUnion myUnion);
setInterfaceD(InterfaceTypeSafeUnion myUnion, string d) generates (InterfaceTypeSafeUnion myUnion);
setInterfaceE(InterfaceTypeSafeUnion myUnion, vec<string> e) generates (InterfaceTypeSafeUnion myUnion);
setInterfaceF(InterfaceTypeSafeUnion myUnion, handle f) generates (InterfaceTypeSafeUnion myUnion);
diff --git a/tests/safeunion/1.0/default/SafeUnion.cpp b/tests/safeunion/1.0/default/SafeUnion.cpp
index 4fb0974..667da6e 100644
--- a/tests/safeunion/1.0/default/SafeUnion.cpp
+++ b/tests/safeunion/1.0/default/SafeUnion.cpp
@@ -202,7 +202,9 @@
return Void();
}
-Return<void> SafeUnion::setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) {
+Return<void> SafeUnion::setInterfaceC(const InterfaceTypeSafeUnion& myUnion,
+ const sp<::android::hidl::base::V1_0::IBase>& c,
+ setInterfaceC_cb _hidl_cb) {
LOG(INFO) << "SERVER(SafeUnion) setInterfaceC(myUnion, " << toString(c) << ")";
InterfaceTypeSafeUnion myNewUnion = myUnion;
diff --git a/tests/safeunion/1.0/default/SafeUnion.h b/tests/safeunion/1.0/default/SafeUnion.h
index ee3a954..b10575c 100644
--- a/tests/safeunion/1.0/default/SafeUnion.h
+++ b/tests/safeunion/1.0/default/SafeUnion.h
@@ -54,7 +54,9 @@
Return<void> newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) override;
Return<void> setInterfaceA(const InterfaceTypeSafeUnion& myUnion, uint32_t a, setInterfaceA_cb _hidl_cb) override;
Return<void> setInterfaceB(const InterfaceTypeSafeUnion& myUnion, const hidl_array<int8_t, 7>& b, setInterfaceB_cb _hidl_cb) override;
- Return<void> setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) override;
+ Return<void> setInterfaceC(const InterfaceTypeSafeUnion& myUnion,
+ const sp<::android::hidl::base::V1_0::IBase>& c,
+ setInterfaceC_cb _hidl_cb) override;
Return<void> setInterfaceD(const InterfaceTypeSafeUnion& myUnion, const hidl_string& d, setInterfaceD_cb _hidl_cb) override;
Return<void> setInterfaceE(const InterfaceTypeSafeUnion& myUnion, const hidl_vec<hidl_string>& e, setInterfaceE_cb _hidl_cb) override;
Return<void> setInterfaceF(const InterfaceTypeSafeUnion& myUnion, const hidl_handle& f,
diff --git a/tests/safeunion/cpp/1.0/.hidl_for_test b/tests/safeunion/cpp/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/safeunion/cpp/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/trie/1.0/.hidl_for_test b/tests/trie/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/trie/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
index 321224a..e774048 100644
--- a/tetheroffload/config/1.0/Android.bp
+++ b/tetheroffload/config/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tetheroffload.config@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IOffloadConfig.hal",
],
diff --git a/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
index 02fe96f..6fd9a6f 100644
--- a/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
+++ b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
@@ -176,6 +176,7 @@
ASSERT_TRUE(ret.isOk());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OffloadConfigHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, OffloadConfigHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IOffloadConfig::descriptor)),
diff --git a/tetheroffload/control/1.0/Android.bp b/tetheroffload/control/1.0/Android.bp
index f894448..4bcaed2 100644
--- a/tetheroffload/control/1.0/Android.bp
+++ b/tetheroffload/control/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tetheroffload.control@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IOffloadControl.hal",
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
index c51dd8b..c397df4 100644
--- a/tetheroffload/control/1.0/vts/functional/Android.bp
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -15,10 +15,18 @@
cc_test {
name: "VtsHalTetheroffloadControlV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalTetheroffloadControlV1_0TargetTest.cpp"],
+ local_include_dirs: ["include"],
+ srcs: [
+ "VtsHalTetheroffloadControlV1_0TargetTest.cpp",
+ "OffloadControlTestBase.cpp",
+ "OffloadControlTestUtils.cpp",
+ ],
static_libs: [
"android.hardware.tetheroffload.config@1.0",
"android.hardware.tetheroffload.control@1.0",
],
- test_suites: ["general-tests", "vts"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
diff --git a/tetheroffload/control/1.0/vts/functional/OffloadControlTestBase.cpp b/tetheroffload/control/1.0/vts/functional/OffloadControlTestBase.cpp
new file mode 100644
index 0000000..bd0dad7
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/OffloadControlTestBase.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <OffloadControlTestBase.h>
+
+void OffloadControlTestBase::TearDown() {
+ // For good measure, the teardown should try stopOffload() once more, since
+ // different HAL call test cycles might enter this function. Also the
+ // return code cannot be actually expected for all cases, hence ignore it.
+ stopOffload(ExpectBoolean::Ignored);
+}
+
+// The IOffloadConfig HAL is tested more thoroughly elsewhere. Here the class
+// just setup everything correctly and verify basic readiness.
+void OffloadControlTestBase::setupConfigHal() {
+ config = IOffloadConfig::getService(std::get<0>(GetParam()));
+ ASSERT_NE(nullptr, config.get()) << "Could not get HIDL instance";
+
+ unique_fd fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY));
+ if (fd1.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
+ nativeHandle1->data[0] = fd1.release();
+ hidl_handle h1;
+ h1.setTo(nativeHandle1, true);
+
+ unique_fd fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
+ if (fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ FAIL();
+ }
+ native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
+ nativeHandle2->data[0] = fd2.release();
+ hidl_handle h2;
+ h2.setTo(nativeHandle2, true);
+
+ const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
+ ASSERT_TRUE(ret.isOk());
+}
+
+void OffloadControlTestBase::prepareControlHal() {
+ control = createControl(std::get<1>(GetParam()));
+ ASSERT_NE(nullptr, control.get()) << "Could not get HIDL instance";
+
+ control_cb = new TetheringOffloadCallback();
+ ASSERT_NE(nullptr, control_cb.get()) << "Could not get get offload callback";
+}
+
+void OffloadControlTestBase::initOffload(const bool expected_result) {
+ auto init_cb = [&](bool success, std::string errMsg) {
+ std::string msg = StringPrintf("Unexpectedly %s to init offload: %s",
+ success ? "succeeded" : "failed", errMsg.c_str());
+ ASSERT_EQ(expected_result, success) << msg;
+ };
+ const Return<void> ret = control->initOffload(control_cb, init_cb);
+ ASSERT_TRUE(ret.isOk());
+}
+
+void OffloadControlTestBase::setupControlHal() {
+ prepareControlHal();
+ initOffload(true);
+}
+
+void OffloadControlTestBase::stopOffload(const ExpectBoolean value) {
+ auto cb = [&](bool success, const hidl_string& errMsg) {
+ switch (value) {
+ case ExpectBoolean::False:
+ ASSERT_EQ(false, success) << "Unexpectedly able to stop offload: " << errMsg;
+ break;
+ case ExpectBoolean::True:
+ ASSERT_EQ(true, success) << "Unexpectedly failed to stop offload: " << errMsg;
+ break;
+ case ExpectBoolean::Ignored:
+ break;
+ }
+ };
+ const Return<void> ret = control->stopOffload(cb);
+ ASSERT_TRUE(ret.isOk());
+}
diff --git a/tetheroffload/control/1.0/vts/functional/OffloadControlTestUtils.cpp b/tetheroffload/control/1.0/vts/functional/OffloadControlTestUtils.cpp
new file mode 100644
index 0000000..c784fe1
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/OffloadControlTestUtils.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <OffloadControlTestUtils.h>
+#include <android-base/unique_fd.h>
+
+using android::base::unique_fd;
+
+inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr) {
+ return reinterpret_cast<const sockaddr*>(nladdr);
+}
+
+int conntrackSocket(unsigned groups) {
+ unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
+ if (s.get() < 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (::bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) < 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
\ No newline at end of file
diff --git a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
index b422b2f..ad4ef12 100644
--- a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
+++ b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
@@ -16,215 +16,24 @@
#define LOG_TAG "VtsOffloadControlV1_0TargetTest"
-#include <VtsHalHidlTargetCallbackBase.h>
+#include <OffloadControlTestV1_0.h>
#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
-#include <android/hardware/tetheroffload/control/1.0/IOffloadControl.h>
-#include <android/hardware/tetheroffload/control/1.0/types.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netlink.h>
-#include <log/log.h>
#include <net/if.h>
#include <sys/socket.h>
-#include <unistd.h>
-#include <set>
using android::base::StringPrintf;
-using android::base::unique_fd;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_string;
-using android::hardware::hidl_vec;
using android::hardware::Return;
using android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
using android::hardware::tetheroffload::control::V1_0::IOffloadControl;
-using android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair;
-using android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
-using android::hardware::tetheroffload::control::V1_0::OffloadCallbackEvent;
-using android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate;
-using android::hardware::tetheroffload::control::V1_0::NetworkProtocol;
using android::hardware::Void;
-using android::sp;
-
-enum class ExpectBoolean {
- Ignored = -1,
- False = 0,
- True = 1,
-};
constexpr const char* TEST_IFACE = "rmnet_data0";
-// We use #defines here so as to get local lamba captures and error message line numbers
-#define ASSERT_TRUE_CALLBACK \
- [&](bool success, std::string errMsg) { \
- std::string msg = StringPrintf("unexpected error: %s", errMsg.c_str()); \
- ASSERT_TRUE(success) << msg; \
- }
-
-#define ASSERT_FALSE_CALLBACK \
- [&](bool success, std::string errMsg) { \
- std::string msg = StringPrintf("expected error: %s", errMsg.c_str()); \
- ASSERT_FALSE(success) << msg; \
- }
-
-#define ASSERT_ZERO_BYTES_CALLBACK \
- [&](uint64_t rxBytes, uint64_t txBytes) { \
- EXPECT_EQ(0ULL, rxBytes); \
- EXPECT_EQ(0ULL, txBytes); \
- }
-
-inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr) {
- return reinterpret_cast<const sockaddr*>(nladdr);
-}
-
-int conntrackSocket(unsigned groups) {
- unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
- if (s.get() < 0) {
- return -errno;
- }
-
- const struct sockaddr_nl bind_addr = {
- .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
- };
- if (::bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) < 0) {
- return -errno;
- }
-
- const struct sockaddr_nl kernel_addr = {
- .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
- };
- if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
- return -errno;
- }
-
- return s.release();
-}
-
-constexpr char kCallbackOnEvent[] = "onEvent";
-constexpr char kCallbackUpdateTimeout[] = "updateTimeout";
-
-class TetheringOffloadCallbackArgs {
- public:
- OffloadCallbackEvent last_event;
- NatTimeoutUpdate last_params;
-};
-
-class OffloadControlHidlTestBase
- : public testing::TestWithParam<std::tuple<std::string, std::string>> {
- public:
- virtual void SetUp() override {
- setupConfigHal();
- prepareControlHal();
- }
-
- virtual void TearDown() override {
- // For good measure, we should try stopOffload() once more. Since we
- // don't know where we are in HAL call test cycle we don't know what
- // return code to actually expect, so we just ignore it.
- stopOffload(ExpectBoolean::Ignored);
- }
-
- // The IOffloadConfig HAL is tested more thoroughly elsewhere. He we just
- // setup everything correctly and verify basic readiness.
- void setupConfigHal() {
- config = IOffloadConfig::getService(std::get<0>(GetParam()));
- ASSERT_NE(nullptr, config.get()) << "Could not get HIDL instance";
-
- unique_fd fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY));
- if (fd1.get() < 0) {
- ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
- FAIL();
- }
- native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
- nativeHandle1->data[0] = fd1.release();
- hidl_handle h1;
- h1.setTo(nativeHandle1, true);
-
- unique_fd fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
- if (fd2.get() < 0) {
- ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
- FAIL();
- }
- native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
- nativeHandle2->data[0] = fd2.release();
- hidl_handle h2;
- h2.setTo(nativeHandle2, true);
-
- const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
- ASSERT_TRUE(ret.isOk());
- }
-
- void prepareControlHal() {
- control = IOffloadControl::getService(std::get<1>(GetParam()));
- ASSERT_NE(nullptr, control.get()) << "Could not get HIDL instance";
-
- control_cb = new TetheringOffloadCallback();
- ASSERT_NE(nullptr, control_cb.get()) << "Could not get get offload callback";
- }
-
- void initOffload(const bool expected_result) {
- auto init_cb = [&](bool success, std::string errMsg) {
- std::string msg = StringPrintf("Unexpectedly %s to init offload: %s",
- success ? "succeeded" : "failed", errMsg.c_str());
- ASSERT_EQ(expected_result, success) << msg;
- };
- const Return<void> ret = control->initOffload(control_cb, init_cb);
- ASSERT_TRUE(ret.isOk());
- }
-
- void setupControlHal() {
- prepareControlHal();
- initOffload(true);
- }
-
- void stopOffload(const ExpectBoolean value) {
- auto cb = [&](bool success, const hidl_string& errMsg) {
- switch (value) {
- case ExpectBoolean::False:
- ASSERT_EQ(false, success) << "Unexpectedly able to stop offload: " << errMsg;
- break;
- case ExpectBoolean::True:
- ASSERT_EQ(true, success) << "Unexpectedly failed to stop offload: " << errMsg;
- break;
- case ExpectBoolean::Ignored:
- break;
- }
- };
- const Return<void> ret = control->stopOffload(cb);
- ASSERT_TRUE(ret.isOk());
- }
-
- // Callback class for both events and NAT timeout updates.
- class TetheringOffloadCallback
- : public testing::VtsHalHidlTargetCallbackBase<TetheringOffloadCallbackArgs>,
- public ITetheringOffloadCallback {
- public:
- TetheringOffloadCallback() = default;
- virtual ~TetheringOffloadCallback() = default;
-
- Return<void> onEvent(OffloadCallbackEvent event) override {
- const TetheringOffloadCallbackArgs args{.last_event = event};
- NotifyFromCallback(kCallbackOnEvent, args);
- return Void();
- };
-
- Return<void> updateTimeout(const NatTimeoutUpdate& params) override {
- const TetheringOffloadCallbackArgs args{.last_params = params};
- NotifyFromCallback(kCallbackUpdateTimeout, args);
- return Void();
- };
- };
-
- sp<IOffloadConfig> config;
- sp<IOffloadControl> control;
- sp<TetheringOffloadCallback> control_cb;
-};
-
// Call initOffload() multiple times. Check that non-first initOffload() calls return false.
-TEST_P(OffloadControlHidlTestBase, AdditionalInitsWithoutStopReturnFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, AdditionalInitsWithoutStopReturnFalse) {
initOffload(true);
initOffload(false);
initOffload(false);
@@ -232,7 +41,7 @@
}
// Check that calling stopOffload() without first having called initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, MultipleStopsWithoutInitReturnFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, MultipleStopsWithoutInitReturnFalse) {
stopOffload(ExpectBoolean::False);
stopOffload(ExpectBoolean::False);
stopOffload(ExpectBoolean::False);
@@ -251,7 +60,7 @@
}
// Check that calling stopOffload() after a complete init/stop cycle returns false.
-TEST_P(OffloadControlHidlTestBase, AdditionalStopsWithInitReturnFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, AdditionalStopsWithInitReturnFalse) {
initOffload(true);
// Call setUpstreamParameters() so that "offload" can be reasonably said
// to be both requested and operational.
@@ -273,7 +82,7 @@
}
// Check that calling setLocalPrefixes() without first having called initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, SetLocalPrefixesWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, SetLocalPrefixesWithoutInitReturnsFalse) {
const vector<hidl_string> prefixes{hidl_string("2001:db8::/64")};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
EXPECT_TRUE(ret.isOk());
@@ -281,14 +90,14 @@
// Check that calling getForwardedStats() without first having called initOffload()
// returns zero bytes statistics.
-TEST_P(OffloadControlHidlTestBase, GetForwardedStatsWithoutInitReturnsZeroValues) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, GetForwardedStatsWithoutInitReturnsZeroValues) {
const hidl_string upstream(TEST_IFACE);
const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
EXPECT_TRUE(ret.isOk());
}
// Check that calling setDataLimit() without first having called initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, SetDataLimitWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, SetDataLimitWithoutInitReturnsFalse) {
const hidl_string upstream(TEST_IFACE);
const uint64_t limit = 5000ULL;
const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_FALSE_CALLBACK);
@@ -297,7 +106,7 @@
// Check that calling setUpstreamParameters() without first having called initOffload()
// returns false.
-TEST_P(OffloadControlHidlTestBase, SetUpstreamParametersWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, SetUpstreamParametersWithoutInitReturnsFalse) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("192.0.2.0/24");
const hidl_string v4Gw("192.0.2.1");
@@ -309,7 +118,7 @@
// Check that calling addDownstream() with an IPv4 prefix without first having called
// initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, AddIPv4DownstreamWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, AddIPv4DownstreamWithoutInitReturnsFalse) {
const hidl_string iface(TEST_IFACE);
const hidl_string prefix("192.0.2.0/24");
const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
@@ -318,7 +127,7 @@
// Check that calling addDownstream() with an IPv6 prefix without first having called
// initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, AddIPv6DownstreamWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, AddIPv6DownstreamWithoutInitReturnsFalse) {
const hidl_string iface(TEST_IFACE);
const hidl_string prefix("2001:db8::/64");
const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
@@ -327,7 +136,7 @@
// Check that calling removeDownstream() with an IPv4 prefix without first having called
// initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, RemoveIPv4DownstreamWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, RemoveIPv4DownstreamWithoutInitReturnsFalse) {
const hidl_string iface(TEST_IFACE);
const hidl_string prefix("192.0.2.0/24");
const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
@@ -336,48 +145,33 @@
// Check that calling removeDownstream() with an IPv6 prefix without first having called
// initOffload() returns false.
-TEST_P(OffloadControlHidlTestBase, RemoveIPv6DownstreamWithoutInitReturnsFalse) {
+TEST_P(OffloadControlTestV1_0_HalNotStarted, RemoveIPv6DownstreamWithoutInitReturnsFalse) {
const hidl_string iface(TEST_IFACE);
const hidl_string prefix("2001:db8::/64");
const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
EXPECT_TRUE(ret.isOk());
}
-class OffloadControlHidlTest : public OffloadControlHidlTestBase {
- public:
- virtual void SetUp() override {
- setupConfigHal();
- setupControlHal();
- }
-
- virtual void TearDown() override {
- // For good measure, we should try stopOffload() once more. Since we
- // don't know where we are in HAL call test cycle we don't know what
- // return code to actually expect, so we just ignore it.
- stopOffload(ExpectBoolean::Ignored);
- }
-};
-
/*
* Tests for IOffloadControl::setLocalPrefixes().
*/
// Test setLocalPrefixes() accepts an IPv4 address.
-TEST_P(OffloadControlHidlTest, SetLocalPrefixesIPv4AddressOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetLocalPrefixesIPv4AddressOk) {
const vector<hidl_string> prefixes{hidl_string("192.0.2.1")};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
EXPECT_TRUE(ret.isOk());
}
// Test setLocalPrefixes() accepts an IPv6 address.
-TEST_P(OffloadControlHidlTest, SetLocalPrefixesIPv6AddressOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetLocalPrefixesIPv6AddressOk) {
const vector<hidl_string> prefixes{hidl_string("fe80::1")};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
EXPECT_TRUE(ret.isOk());
}
// Test setLocalPrefixes() accepts both IPv4 and IPv6 prefixes.
-TEST_P(OffloadControlHidlTest, SetLocalPrefixesIPv4v6PrefixesOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetLocalPrefixesIPv4v6PrefixesOk) {
const vector<hidl_string> prefixes{hidl_string("192.0.2.0/24"), hidl_string("fe80::/64")};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_TRUE_CALLBACK);
EXPECT_TRUE(ret.isOk());
@@ -386,14 +180,14 @@
// Test that setLocalPrefixes() fails given empty input. There is always
// a non-empty set of local prefixes; when all networking interfaces are down
// we still apply {127.0.0.0/8, ::1/128, fe80::/64} here.
-TEST_P(OffloadControlHidlTest, SetLocalPrefixesEmptyFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetLocalPrefixesEmptyFails) {
const vector<hidl_string> prefixes{};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
EXPECT_TRUE(ret.isOk());
}
// Test setLocalPrefixes() fails on incorrectly formed input strings.
-TEST_P(OffloadControlHidlTest, SetLocalPrefixesInvalidFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetLocalPrefixesInvalidFails) {
const vector<hidl_string> prefixes{hidl_string("192.0.2.0/24"), hidl_string("invalid")};
const Return<void> ret = control->setLocalPrefixes(prefixes, ASSERT_FALSE_CALLBACK);
EXPECT_TRUE(ret.isOk());
@@ -404,7 +198,7 @@
*/
// Test that getForwardedStats() for a non-existent upstream yields zero bytes statistics.
-TEST_P(OffloadControlHidlTest, GetForwardedStatsInvalidUpstreamIface) {
+TEST_P(OffloadControlTestV1_0_HalStarted, GetForwardedStatsInvalidUpstreamIface) {
const hidl_string upstream("invalid");
const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
EXPECT_TRUE(ret.isOk());
@@ -412,7 +206,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, GetForwardedStatsDummyIface) {
+TEST_P(OffloadControlTestV1_0_HalStarted, GetForwardedStatsDummyIface) {
const hidl_string upstream(TEST_IFACE);
const Return<void> ret = control->getForwardedStats(upstream, ASSERT_ZERO_BYTES_CALLBACK);
EXPECT_TRUE(ret.isOk());
@@ -423,7 +217,7 @@
*/
// Test that setDataLimit() for an empty interface name fails.
-TEST_P(OffloadControlHidlTest, SetDataLimitEmptyUpstreamIfaceFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetDataLimitEmptyUpstreamIfaceFails) {
const hidl_string upstream("");
const uint64_t limit = 5000ULL;
const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_FALSE_CALLBACK);
@@ -432,7 +226,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetDataLimitNonZeroOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetDataLimitNonZeroOk) {
const hidl_string upstream(TEST_IFACE);
const uint64_t limit = 5000ULL;
const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_TRUE_CALLBACK);
@@ -441,7 +235,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetDataLimitZeroOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetDataLimitZeroOk) {
const hidl_string upstream(TEST_IFACE);
const uint64_t limit = 0ULL;
const Return<void> ret = control->setDataLimit(upstream, limit, ASSERT_TRUE_CALLBACK);
@@ -454,7 +248,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersIPv6OnlyOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersIPv6OnlyOk) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("");
const hidl_string v4Gw("");
@@ -466,7 +260,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersAlternateIPv6OnlyOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersAlternateIPv6OnlyOk) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr;
const hidl_string v4Gw;
@@ -478,7 +272,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersIPv4OnlyOk) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersIPv4OnlyOk) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("192.0.2.2");
const hidl_string v4Gw("192.0.2.1");
@@ -490,7 +284,7 @@
// TEST_IFACE is presumed to exist on the device and be up. No packets
// are ever actually caused to be forwarded.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersIPv4v6Ok) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersIPv4v6Ok) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("192.0.2.2");
const hidl_string v4Gw("192.0.2.1");
@@ -501,7 +295,7 @@
}
// Test that setUpstreamParameters() fails when all parameters are empty.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersEmptyFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersEmptyFails) {
const hidl_string iface("");
const hidl_string v4Addr("");
const hidl_string v4Gw("");
@@ -512,7 +306,7 @@
}
// Test that setUpstreamParameters() fails when given empty or non-existent interface names.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersBogusIfaceFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersBogusIfaceFails) {
const hidl_string v4Addr("192.0.2.2");
const hidl_string v4Gw("192.0.2.1");
const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
@@ -526,7 +320,7 @@
}
// Test that setUpstreamParameters() fails when given unparseable IPv4 addresses.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersInvalidIPv4AddrFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersInvalidIPv4AddrFails) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Gw("192.0.2.1");
const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
@@ -540,7 +334,7 @@
}
// Test that setUpstreamParameters() fails when given unparseable IPv4 gateways.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersInvalidIPv4GatewayFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersInvalidIPv4GatewayFails) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("192.0.2.2");
const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1")};
@@ -554,7 +348,7 @@
}
// Test that setUpstreamParameters() fails when given unparseable IPv6 gateways.
-TEST_P(OffloadControlHidlTest, SetUpstreamParametersBadIPv6GatewaysFail) {
+TEST_P(OffloadControlTestV1_0_HalStarted, SetUpstreamParametersBadIPv6GatewaysFail) {
const hidl_string iface(TEST_IFACE);
const hidl_string v4Addr("192.0.2.2");
const hidl_string v4Gw("192.0.2.1");
@@ -572,7 +366,7 @@
*/
// Test addDownstream() works given an IPv4 prefix.
-TEST_P(OffloadControlHidlTest, AddDownstreamIPv4) {
+TEST_P(OffloadControlTestV1_0_HalStarted, AddDownstreamIPv4) {
const hidl_string iface("dummy0");
const hidl_string prefix("192.0.2.0/24");
const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
@@ -580,7 +374,7 @@
}
// Test addDownstream() works given an IPv6 prefix.
-TEST_P(OffloadControlHidlTest, AddDownstreamIPv6) {
+TEST_P(OffloadControlTestV1_0_HalStarted, AddDownstreamIPv6) {
const hidl_string iface("dummy0");
const hidl_string prefix("2001:db8::/64");
const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
@@ -588,7 +382,7 @@
}
// Test addDownstream() fails given all empty parameters.
-TEST_P(OffloadControlHidlTest, AddDownstreamEmptyFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, AddDownstreamEmptyFails) {
const hidl_string iface("");
const hidl_string prefix("");
const Return<void> ret = control->addDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
@@ -596,7 +390,7 @@
}
// Test addDownstream() fails given empty or non-existent interface names.
-TEST_P(OffloadControlHidlTest, AddDownstreamInvalidIfaceFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, AddDownstreamInvalidIfaceFails) {
const hidl_string prefix("192.0.2.0/24");
for (const auto& bogus : {"", "invalid"}) {
SCOPED_TRACE(StringPrintf("iface='%s'", bogus));
@@ -607,7 +401,7 @@
}
// Test addDownstream() fails given unparseable prefix arguments.
-TEST_P(OffloadControlHidlTest, AddDownstreamBogusPrefixFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, AddDownstreamBogusPrefixFails) {
const hidl_string iface("dummy0");
for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
SCOPED_TRACE(StringPrintf("prefix='%s'", bogus));
@@ -622,7 +416,7 @@
*/
// Test removeDownstream() works given an IPv4 prefix.
-TEST_P(OffloadControlHidlTest, RemoveDownstreamIPv4) {
+TEST_P(OffloadControlTestV1_0_HalStarted, RemoveDownstreamIPv4) {
const hidl_string iface("dummy0");
const hidl_string prefix("192.0.2.0/24");
// First add the downstream, otherwise removeDownstream logic can reasonably
@@ -634,7 +428,7 @@
}
// Test removeDownstream() works given an IPv6 prefix.
-TEST_P(OffloadControlHidlTest, RemoveDownstreamIPv6) {
+TEST_P(OffloadControlTestV1_0_HalStarted, RemoveDownstreamIPv6) {
const hidl_string iface("dummy0");
const hidl_string prefix("2001:db8::/64");
// First add the downstream, otherwise removeDownstream logic can reasonably
@@ -646,7 +440,7 @@
}
// Test removeDownstream() fails given all empty parameters.
-TEST_P(OffloadControlHidlTest, RemoveDownstreamEmptyFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, RemoveDownstreamEmptyFails) {
const hidl_string iface("");
const hidl_string prefix("");
const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_FALSE_CALLBACK);
@@ -654,7 +448,7 @@
}
// Test removeDownstream() fails given empty or non-existent interface names.
-TEST_P(OffloadControlHidlTest, RemoveDownstreamBogusIfaceFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, RemoveDownstreamBogusIfaceFails) {
const hidl_string prefix("192.0.2.0/24");
for (const auto& bogus : {"", "invalid"}) {
SCOPED_TRACE(StringPrintf("iface='%s'", bogus));
@@ -665,7 +459,7 @@
}
// Test removeDownstream() fails given unparseable prefix arguments.
-TEST_P(OffloadControlHidlTest, RemoveDownstreamBogusPrefixFails) {
+TEST_P(OffloadControlTestV1_0_HalStarted, RemoveDownstreamBogusPrefixFails) {
const hidl_string iface("dummy0");
for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
SCOPED_TRACE(StringPrintf("prefix='%s'", bogus));
@@ -675,21 +469,20 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OffloadControlHidlTestBase);
INSTANTIATE_TEST_CASE_P(
- PerInstance, OffloadControlHidlTestBase,
- testing::Combine(
- testing::ValuesIn(
- android::hardware::getAllHalInstanceNames(IOffloadConfig::descriptor)),
- testing::ValuesIn(
- android::hardware::getAllHalInstanceNames(IOffloadControl::descriptor))),
- android::hardware::PrintInstanceTupleNameToString<>);
+ PerInstance, OffloadControlTestV1_0_HalNotStarted,
+ testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IOffloadConfig::descriptor)),
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IOffloadControl::descriptor))),
+ android::hardware::PrintInstanceTupleNameToString<>);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OffloadControlHidlTest);
INSTANTIATE_TEST_CASE_P(
- PerInstance, OffloadControlHidlTest,
- testing::Combine(
- testing::ValuesIn(
- android::hardware::getAllHalInstanceNames(IOffloadConfig::descriptor)),
- testing::ValuesIn(
- android::hardware::getAllHalInstanceNames(IOffloadControl::descriptor))),
- android::hardware::PrintInstanceTupleNameToString<>);
-
+ PerInstance, OffloadControlTestV1_0_HalStarted,
+ testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IOffloadConfig::descriptor)),
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IOffloadControl::descriptor))),
+ android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestBase.h b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestBase.h
new file mode 100644
index 0000000..004019a
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestBase.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <OffloadControlTestUtils.h>
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+#include <android/hardware/tetheroffload/control/1.0/IOffloadControl.h>
+#include <android/hardware/tetheroffload/control/1.0/types.h>
+#include <gtest/gtest.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <log/log.h>
+
+using android::sp;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
+using android::hardware::tetheroffload::control::V1_0::IOffloadControl;
+using android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+using android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate;
+using android::hardware::tetheroffload::control::V1_0::OffloadCallbackEvent;
+
+constexpr char kCallbackOnEvent[] = "onEvent";
+constexpr char kCallbackUpdateTimeout[] = "updateTimeout";
+
+enum class ExpectBoolean {
+ Ignored = -1,
+ False = 0,
+ True = 1,
+};
+
+class TetheringOffloadCallbackArgs {
+ public:
+ OffloadCallbackEvent last_event;
+ NatTimeoutUpdate last_params;
+};
+
+class OffloadControlTestBase : public testing::TestWithParam<std::tuple<std::string, std::string>> {
+ public:
+ virtual void SetUp() = 0;
+
+ virtual void TearDown();
+
+ // Called once in setup stage to retrieve correct version of
+ // IOffloadControl object.
+ virtual sp<IOffloadControl> createControl(const std::string& serviceName) = 0;
+
+ // The IOffloadConfig HAL is tested more thoroughly elsewhere. Here the
+ // class just setup everything correctly and verify basic readiness.
+ void setupConfigHal();
+
+ void prepareControlHal();
+
+ void initOffload(const bool expected_result);
+
+ void setupControlHal();
+
+ void stopOffload(const ExpectBoolean value);
+
+ // Callback class for both events and NAT timeout updates.
+ class TetheringOffloadCallback
+ : public testing::VtsHalHidlTargetCallbackBase<TetheringOffloadCallbackArgs>,
+ public ITetheringOffloadCallback {
+ public:
+ TetheringOffloadCallback() = default;
+ virtual ~TetheringOffloadCallback() = default;
+
+ Return<void> onEvent(OffloadCallbackEvent event) override {
+ const TetheringOffloadCallbackArgs args{.last_event = event};
+ NotifyFromCallback(kCallbackOnEvent, args);
+ return Void();
+ };
+
+ Return<void> updateTimeout(const NatTimeoutUpdate& params) override {
+ const TetheringOffloadCallbackArgs args{.last_params = params};
+ NotifyFromCallback(kCallbackUpdateTimeout, args);
+ return Void();
+ };
+ };
+
+ sp<IOffloadConfig> config;
+ sp<IOffloadControl> control;
+ sp<TetheringOffloadCallback> control_cb;
+};
\ No newline at end of file
diff --git a/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestUtils.h b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestUtils.h
new file mode 100644
index 0000000..f9e5783
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestUtils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <linux/netlink.h>
+#include <sys/socket.h>
+
+// We use #defines here so as to get local lamba captures and error message line numbers
+#define ASSERT_TRUE_CALLBACK \
+ [&](bool success, std::string errMsg) { \
+ ASSERT_TRUE(success) << "unexpected error: " << errMsg; \
+ }
+
+#define ASSERT_FALSE_CALLBACK \
+ [&](bool success, std::string errMsg) { ASSERT_FALSE(success) << "expected error: " << errMsg; }
+
+#define ASSERT_ZERO_BYTES_CALLBACK \
+ [&](uint64_t rxBytes, uint64_t txBytes) { \
+ EXPECT_EQ(0ULL, rxBytes); \
+ EXPECT_EQ(0ULL, txBytes); \
+ }
+
+inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr);
+
+int conntrackSocket(unsigned groups);
\ No newline at end of file
diff --git a/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestV1_0.h b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestV1_0.h
new file mode 100644
index 0000000..7492f8a
--- /dev/null
+++ b/tetheroffload/control/1.0/vts/functional/include/OffloadControlTestV1_0.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <OffloadControlTestBase.h>
+
+class OffloadControlTestV1_0_HalNotStarted : public OffloadControlTestBase {
+ public:
+ virtual void SetUp() override {
+ setupConfigHal();
+ // Create tether offload control object without calling its initOffload.
+ prepareControlHal();
+ }
+
+ virtual sp<IOffloadControl> createControl(const std::string& serviceName) override {
+ return IOffloadControl::getService(serviceName);
+ }
+};
+
+class OffloadControlTestV1_0_HalStarted : public OffloadControlTestV1_0_HalNotStarted {
+ public:
+ virtual void SetUp() override {
+ setupConfigHal();
+ setupControlHal();
+ }
+};
diff --git a/thermal/1.0/Android.bp b/thermal/1.0/Android.bp
index de168d8..10eeddc 100644
--- a/thermal/1.0/Android.bp
+++ b/thermal/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.thermal@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IThermal.hal",
diff --git a/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp b/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
index aa1c0ce..c2be07a 100644
--- a/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
+++ b/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
@@ -208,6 +208,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ThermalHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IThermal::descriptor)),
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
index f38ed3b..7dc30a3 100644
--- a/thermal/1.1/Android.bp
+++ b/thermal/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.thermal@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IThermal.hal",
"IThermalCallback.hal",
diff --git a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
index bc7b2ee..ec1696f 100644
--- a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
+++ b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
@@ -100,6 +100,7 @@
EXPECT_EQ(kThrottleTemp, res.args->temperature);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ThermalHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IThermal::descriptor)),
diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp
index 1b76f37..3d9cea1 100644
--- a/thermal/2.0/Android.bp
+++ b/thermal/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.thermal@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IThermal.hal",
diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
index 75536a6..2ee91f4 100644
--- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
+++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
@@ -257,6 +257,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ThermalHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IThermal::descriptor)),
diff --git a/tv/cec/1.0/Android.bp b/tv/cec/1.0/Android.bp
index d41a7e7..0e0f284 100644
--- a/tv/cec/1.0/Android.bp
+++ b/tv/cec/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tv.cec@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHdmiCec.hal",
diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp
index 61450ac..5463b6d 100644
--- a/tv/cec/2.0/Android.bp
+++ b/tv/cec/2.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tv.cec@2.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHdmiCec.hal",
diff --git a/tv/input/1.0/Android.bp b/tv/input/1.0/Android.bp
index 1164430..1121f4e 100644
--- a/tv/input/1.0/Android.bp
+++ b/tv/input/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tv.input@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ITvInput.hal",
diff --git a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
index 59c70eb..8092d5e 100644
--- a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
+++ b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
@@ -337,3 +337,6 @@
PerInstance, TvInputHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITvInput::descriptor)),
android::hardware::PrintInstanceNameToString);
+
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TvInputHidlTest);
diff --git a/tv/tuner/1.0/Android.bp b/tv/tuner/1.0/Android.bp
index d78f3f2..e578641 100644
--- a/tv/tuner/1.0/Android.bp
+++ b/tv/tuner/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.tv.tuner@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IDemux.hal",
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 6804f3c..5a23ca5 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -67,6 +67,9 @@
FrontendTests mFrontendTests;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest);
+
class TunerLnbHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -86,6 +89,9 @@
LnbTests mLnbTests;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerLnbHidlTest);
+
class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -109,6 +115,9 @@
FilterTests mFilterTests;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxHidlTest);
+
class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -135,6 +144,9 @@
FilterTests mFilterTests;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest);
+
class TunerBroadcastHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -171,6 +183,9 @@
uint32_t* mLnbId = nullptr;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
+
class TunerPlaybackHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -200,6 +215,9 @@
void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackHidlTest);
+
class TunerRecordHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -237,6 +255,9 @@
uint32_t* mLnbId = nullptr;
};
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest);
+
class TunerDescramblerHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -270,4 +291,7 @@
DescramblerTests mDescramblerTests;
DvrTests mDvrTests;
};
+
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDescramblerHidlTest);
} // namespace
diff --git a/tv/tuner/README.md b/tv/tuner/README.md
index aa1f62d..2a358f5 100644
--- a/tv/tuner/README.md
+++ b/tv/tuner/README.md
@@ -5,8 +5,3 @@
TV specific tuners.
See 1.0/ITuner.hal for an overview.
-
-*** note
-**Warning:** The HALs are not (yet) frozen, as the HAL definition is
-expected to evolve between Android releases.
-***
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
index c0e883f..607d1ac 100644
--- a/usb/1.0/Android.bp
+++ b/usb/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.usb@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IUsb.hal",
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index bba75c8..99ca249 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -298,6 +298,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, UsbHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)),
diff --git a/usb/1.1/Android.bp b/usb/1.1/Android.bp
index 6f2abae..8742e77 100644
--- a/usb/1.1/Android.bp
+++ b/usb/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.usb@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IUsb.hal",
diff --git a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
index d4b2ffd..19830a6 100644
--- a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
+++ b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
@@ -169,6 +169,7 @@
EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.supportedModes);
EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, UsbHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)),
diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp
index b3ba81f..8b9f0fb 100644
--- a/usb/1.2/Android.bp
+++ b/usb/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.usb@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IUsb.hal",
diff --git a/usb/gadget/1.0/Android.bp b/usb/gadget/1.0/Android.bp
index 4921abf..21f152c 100644
--- a/usb/gadget/1.0/Android.bp
+++ b/usb/gadget/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.usb.gadget@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IUsbGadget.hal",
diff --git a/usb/gadget/1.1/Android.bp b/usb/gadget/1.1/Android.bp
index b41eb9c..e510069 100644
--- a/usb/gadget/1.1/Android.bp
+++ b/usb/gadget/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.usb.gadget@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IUsbGadget.hal",
],
diff --git a/vibrator/1.0/Android.bp b/vibrator/1.0/Android.bp
index 792e130..d6321fb 100644
--- a/vibrator/1.0/Android.bp
+++ b/vibrator/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.vibrator@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IVibrator.hal",
diff --git a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
index 2aee338..863bfae 100644
--- a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
+++ b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
@@ -134,6 +134,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VibratorHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVibrator::descriptor)),
diff --git a/vibrator/1.1/Android.bp b/vibrator/1.1/Android.bp
index 0d04a87..0302220 100644
--- a/vibrator/1.1/Android.bp
+++ b/vibrator/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.vibrator@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IVibrator.hal",
diff --git a/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp b/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp
index da94308..e7ec496 100644
--- a/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp
+++ b/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp
@@ -108,6 +108,7 @@
EXPECT_OK(vibrator->perform_1_1(Effect_1_1::CLICK, badStrength, validatePerformEffectBadInput));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorHidlTest_1_1);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VibratorHidlTest_1_1,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVibrator::descriptor)),
diff --git a/vibrator/1.2/Android.bp b/vibrator/1.2/Android.bp
index 290a0cf..1fa0114 100644
--- a/vibrator/1.2/Android.bp
+++ b/vibrator/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.vibrator@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IVibrator.hal",
diff --git a/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp b/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
index 2058e85..b96e269 100644
--- a/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
+++ b/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
@@ -116,6 +116,7 @@
EXPECT_OK(vibrator->perform_1_2(Effect::THUD, badStrength, validatePerformEffectBadInput));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorHidlTest_1_2);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VibratorHidlTest_1_2,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVibrator::descriptor)),
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
index 357ea9a..d742388 100644
--- a/vibrator/1.3/Android.bp
+++ b/vibrator/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.vibrator@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IVibrator.hal",
diff --git a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
index 3cd3430..84a6af0 100644
--- a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
+++ b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
@@ -131,6 +131,7 @@
validatePerformEffectUnsupportedOperation));
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorHidlTest_1_3);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VibratorHidlTest_1_3,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVibrator::descriptor)),
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index b359100..c446afd 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -163,6 +163,10 @@
}
LOG(INFO) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
<< e.scale;
+
+ int32_t durationMs;
+ getPrimitiveDuration(e.primitive, &durationMs);
+ usleep(durationMs * 1000);
}
if (callback != nullptr) {
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 8340517..e51f594 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -34,6 +34,7 @@
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::IVibrator;
+using std::chrono::high_resolution_clock;
const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
android::enum_range<Effect>().end()};
@@ -95,7 +96,7 @@
}
TEST_P(VibratorAidl, OnWithCallback) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
@@ -109,7 +110,7 @@
}
TEST_P(VibratorAidl, OnCallbackNotSupported) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) {
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
}
@@ -442,26 +443,52 @@
}
TEST_P(VibratorAidl, ComposeCallback) {
+ constexpr std::chrono::milliseconds allowedLatency{10};
+
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
- std::promise<void> completionPromise;
- std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
- CompositePrimitive primitive = CompositePrimitive::CLICK;
- CompositeEffect effect;
- std::vector<CompositeEffect> composite;
- int32_t duration;
+ std::vector<CompositePrimitive> supported;
- effect.delayMs = 0;
- effect.primitive = primitive;
- effect.scale = 1.0f;
- composite.emplace_back(effect);
+ ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
- EXPECT_EQ(Status::EX_NONE,
- vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode());
- EXPECT_EQ(completionFuture.wait_for(std::chrono::milliseconds(duration * 2)),
- std::future_status::ready);
+ for (auto primitive : supported) {
+ if (primitive == CompositePrimitive::NOOP) {
+ continue;
+ }
+
+ std::promise<void> completionPromise;
+ std::future<void> completionFuture{completionPromise.get_future()};
+ sp<CompletionCallback> callback =
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ CompositeEffect effect;
+ std::vector<CompositeEffect> composite;
+ int32_t durationMs;
+ std::chrono::milliseconds duration;
+ std::chrono::time_point<high_resolution_clock> start, end;
+ std::chrono::milliseconds elapsed;
+
+ effect.delayMs = 0;
+ effect.primitive = primitive;
+ effect.scale = 1.0f;
+ composite.emplace_back(effect);
+
+ EXPECT_EQ(Status::EX_NONE,
+ vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
+ << toString(primitive);
+ duration = std::chrono::milliseconds(durationMs);
+
+ EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
+ << toString(primitive);
+ start = high_resolution_clock::now();
+
+ EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency),
+ std::future_status::ready)
+ << toString(primitive);
+ end = high_resolution_clock::now();
+
+ elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+ EXPECT_LE(elapsed.count(), (duration + allowedLatency).count()) << toString(primitive);
+ EXPECT_GE(elapsed.count(), (duration - allowedLatency).count()) << toString(primitive);
+ }
}
}
@@ -491,6 +518,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)),
android::PrintInstanceNameToString);
diff --git a/vr/1.0/Android.bp b/vr/1.0/Android.bp
index f91f874..769ee3b 100644
--- a/vr/1.0/Android.bp
+++ b/vr/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.vr@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IVr.hal",
],
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index c08e5ca..049ec73 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -63,6 +63,7 @@
EXPECT_TRUE(vr->setVrMode(false).isOk());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VrHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, VrHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVr::descriptor)),
diff --git a/weaver/1.0/Android.bp b/weaver/1.0/Android.bp
index 7d5b8fe..11fc685 100644
--- a/weaver/1.0/Android.bp
+++ b/weaver/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.weaver@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IWeaver.hal",
diff --git a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp b/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
index ae92c36..66465a9 100644
--- a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
+++ b/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
@@ -336,6 +336,7 @@
EXPECT_EQ(timeout, 0u);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, WeaverHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IWeaver::descriptor)),
diff --git a/wifi/1.0/Android.bp b/wifi/1.0/Android.bp
index 958ff3f..c41864f 100644
--- a/wifi/1.0/Android.bp
+++ b/wifi/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IWifi.hal",
diff --git a/wifi/1.1/Android.bp b/wifi/1.1/Android.bp
index a34ac44..4068b31 100644
--- a/wifi/1.1/Android.bp
+++ b/wifi/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IWifi.hal",
"IWifiChip.hal",
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index c28d09b..5812b82 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IWifi.hal",
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 3719c2b..f4e130a 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IWifi.hal",
diff --git a/wifi/1.4/Android.bp b/wifi/1.4/Android.bp
index 3b94619..5620d03 100644
--- a/wifi/1.4/Android.bp
+++ b/wifi/1.4/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi@1.4",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IWifi.hal",
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index a099c8a..3efb8f4 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -148,6 +148,51 @@
}
/*
+ * Request2SidedRangeMeasurement
+ * This test case tests the two sided ranging - 802.11mc FTM protocol.
+ */
+TEST_P(WifiRttControllerHidlTest, Request2SidedRangeMeasurement) {
+ std::pair<WifiStatus, RttCapabilities> status_and_caps;
+
+ // Get the Capabilities
+ status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_4);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+ if (!status_and_caps.second.rttFtmSupported) {
+ GTEST_SKIP()
+ << "Skipping two sided RTT since driver/fw doesn't support";
+ }
+ std::vector<RttConfig> configs;
+ RttConfig config;
+ int cmdId = 55;
+ // Set the config with test data
+ for (int i = 0; i < 6; i++) {
+ config.addr[i] = i;
+ }
+ config.type = RttType::TWO_SIDED;
+ config.peer = RttPeerType::AP;
+ config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
+ config.channel.centerFreq = 5180;
+ config.channel.centerFreq0 = 5210;
+ config.channel.centerFreq1 = 0;
+ config.bw = RttBw::BW_20MHZ;
+ config.preamble = RttPreamble::HT;
+ config.mustRequestLci = false;
+ config.mustRequestLcr = false;
+ config.burstPeriod = 0;
+ config.numBurst = 0;
+ config.numFramesPerBurst = 8;
+ config.numRetriesPerRttFrame = 0;
+ config.numRetriesPerFtmr = 0;
+ config.burstDuration = 9;
+ // Insert config in the vector
+ configs.push_back(config);
+
+ // Invoke the call
+ const auto& status =
+ HIDL_INVOKE(wifi_rtt_controller_, rangeRequest_1_4, cmdId, configs);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+}
+/*
* rangeRequest_1_4
*/
TEST_P(WifiRttControllerHidlTest, RangeRequest_1_4) {
@@ -156,6 +201,10 @@
// Get the Capabilities
status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_4);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+ if (!status_and_caps.second.rttOneSidedSupported) {
+ GTEST_SKIP()
+ << "Skipping one sided RTT since driver/fw doesn't support";
+ }
// Get the highest support preamble
int preamble = 1;
status_and_caps.second.preambleSupport >>= 1;
diff --git a/wifi/hostapd/1.0/Android.bp b/wifi/hostapd/1.0/Android.bp
index cce1182..b736167 100644
--- a/wifi/hostapd/1.0/Android.bp
+++ b/wifi/hostapd/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.hostapd@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHostapd.hal",
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
index ec7ebee..b4b0ea6 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
@@ -95,6 +95,14 @@
EXPECT_TRUE(res.isOk());
return result_buffer.saved_values;
}
+
+// Invokes |void method| on |object| without arguments.
+template <typename MethodT, typename ObjectT>
+void invokeVoidMethodWithoutArguments(MethodT method, ObjectT object) {
+ const auto& res = ((*object).*method)();
+ EXPECT_TRUE(res.isOk());
+}
+
} // namespace detail
} // namespace
@@ -123,3 +131,9 @@
std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
&std::remove_reference<decltype(*strong_pointer)>::type::method, \
strong_pointer, ##__VA_ARGS__))
+
+// Invokes |void method| on |strong_pointer| without arguments.
+#define HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(strong_pointer, method) \
+ (detail::invokeVoidMethodWithoutArguments( \
+ &std::remove_reference<decltype(*strong_pointer)>::type::method, \
+ strong_pointer))
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
index 5a978ca..bb99ae4 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
@@ -55,7 +55,10 @@
ASSERT_NE(hostapd_.get(), nullptr);
}
- virtual void TearDown() override { stopHostapd(wifi_instance_name_); }
+ virtual void TearDown() override {
+ HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
+ stopHostapd(wifi_instance_name_);
+ }
protected:
std::string getPrimaryWlanIfaceName() {
@@ -142,8 +145,8 @@
stopHostapd(wifi_instance_name_);
startHostapdAndWaitForHidlService(wifi_instance_name_,
hostapd_instance_name_);
- sp<IHostapd> hostapd = IHostapd::getService(hostapd_instance_name_);
- EXPECT_NE(nullptr, hostapd.get());
+ hostapd_ = IHostapd::getService(hostapd_instance_name_);
+ EXPECT_NE(nullptr, hostapd_.get());
}
/**
@@ -262,6 +265,7 @@
*/
TEST_P(HostapdHidlTest, Terminate) { hostapd_->terminate(); }
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, HostapdHidlTest,
testing::Combine(
diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp
index 64fbc93..bba065d 100644
--- a/wifi/hostapd/1.1/Android.bp
+++ b/wifi/hostapd/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.hostapd@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"IHostapd.hal",
"IHostapdCallback.hal",
diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
index 345cf31..d823685 100644
--- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
@@ -58,7 +58,10 @@
ASSERT_NE(hostapd_.get(), nullptr);
}
- virtual void TearDown() override { stopHostapd(wifi_instance_name_); }
+ virtual void TearDown() override {
+ HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
+ stopHostapd(wifi_instance_name_);
+ }
protected:
std::string getPrimaryWlanIfaceName() {
@@ -309,6 +312,7 @@
EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, HostapdHidlTest,
testing::Combine(
diff --git a/wifi/hostapd/1.2/Android.bp b/wifi/hostapd/1.2/Android.bp
index 3dcad71..9b26ece 100644
--- a/wifi/hostapd/1.2/Android.bp
+++ b/wifi/hostapd/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.hostapd@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IHostapd.hal",
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index a39f064..99784a4 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -72,7 +72,10 @@
"wifi_softap_wpa3_sae_supported");
}
- virtual void TearDown() override { stopHostapd(wifi_instance_name_); }
+ virtual void TearDown() override {
+ HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
+ stopHostapd(wifi_instance_name_);
+ }
protected:
bool isWpa3SaeSupport_ = false;
@@ -414,6 +417,7 @@
EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, HostapdHidlTest,
testing::Combine(
diff --git a/wifi/offload/1.0/Android.bp b/wifi/offload/1.0/Android.bp
index 110bb70..91ed476 100644
--- a/wifi/offload/1.0/Android.bp
+++ b/wifi/offload/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.offload@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"IOffload.hal",
diff --git a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
index 83d834c..ffd5149 100644
--- a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
+++ b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
@@ -210,6 +210,7 @@
ASSERT_EQ(true, res.no_timeout);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiOffloadHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, WifiOffloadHidlTest,
testing::ValuesIn(
diff --git a/wifi/supplicant/1.0/Android.bp b/wifi/supplicant/1.0/Android.bp
index d91512f..d46e463 100644
--- a/wifi/supplicant/1.0/Android.bp
+++ b/wifi/supplicant/1.0/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.supplicant@1.0",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISupplicant.hal",
diff --git a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
index 01840e2..b2bdaf1 100644
--- a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
+++ b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
@@ -18,9 +18,6 @@
#include "supplicant_hidl_test_utils.h"
int main(int argc, char** argv) {
- if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
- return 0;
-
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
index 47f0394..ac39a24 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
@@ -212,6 +212,7 @@
}
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index c333c4f..616869b 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -647,6 +647,7 @@
HIDL_INVOKE(p2p_iface_, setWfdDeviceInfo, kTestWfdDeviceInfo).code);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantP2pIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
index ff28754..e4fe52c 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -558,6 +558,7 @@
HIDL_INVOKE(sta_iface_, removeExtRadioWork, kTestRadioWorkId).code);
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
index 295ebfb..7e93c5f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -839,6 +839,7 @@
EXPECT_FALSE(0 == status_and_token.second.size());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index 6d940d1..bc20dca 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.supplicant@1.1",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"ISupplicant.hal",
"ISupplicantStaIface.hal",
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
index 24a7ec3..6ad4290 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp
@@ -33,6 +33,7 @@
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
using ::android::hardware::wifi::supplicant::V1_1::ISupplicant;
+using ::android::hardware::wifi::V1_0::IWifi;
using ::android::sp;
class SupplicantHidlTest : public SupplicantHidlTestBase {
@@ -74,7 +75,7 @@
* AddP2pInterface
*/
TEST_P(SupplicantHidlTest, AddP2pInterface) {
- if (isP2pOn_) return;
+ if (!isP2pOn_) return;
ISupplicant::IfaceInfo iface_info;
iface_info.name = getP2pIfaceName();
iface_info.type = IfaceType::P2P;
@@ -114,7 +115,7 @@
* RemoveP2pInterface
*/
TEST_P(SupplicantHidlTest, RemoveP2pInterface) {
- if (isP2pOn_) return;
+ if (!isP2pOn_) return;
ISupplicant::IfaceInfo iface_info;
iface_info.name = getP2pIfaceName();
iface_info.type = IfaceType::P2P;
@@ -139,20 +140,12 @@
*/
TEST_P(SupplicantHidlTest, Terminate) { supplicant_->terminate(); }
-static std::vector<std::string> get_wifi_instances() {
- std::vector<std::string> instances =
- android::hardware::getAllHalInstanceNames(
- android::hardware::wifi::V1_0::IWifi::descriptor);
- // Also test when wifi instance is not set.
- instances.push_back("");
-
- return instances;
-}
-
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantHidlTest,
testing::Combine(
- testing::ValuesIn(get_wifi_instances()),
+ testing::ValuesIn(
+ android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
android::hardware::wifi::supplicant::V1_1::ISupplicant::
descriptor))),
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 8a1aecc..2fade44 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -140,6 +140,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp
index a4b7d40..bd8a2ab 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -93,6 +93,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp
index 185d2b8..aa2fa7b 100644
--- a/wifi/supplicant/1.2/Android.bp
+++ b/wifi/supplicant/1.2/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.supplicant@1.2",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISupplicant.hal",
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index cab160b..75512d7 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -162,6 +162,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantP2pIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 7377f78..184543b 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -460,6 +460,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp
index 54ceb20..5a2f808 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -222,6 +222,7 @@
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.3/Android.bp b/wifi/supplicant/1.3/Android.bp
index 15c72fe..4268490 100644
--- a/wifi/supplicant/1.3/Android.bp
+++ b/wifi/supplicant/1.3/Android.bp
@@ -3,9 +3,6 @@
hidl_interface {
name: "android.hardware.wifi.supplicant@1.3",
root: "android.hardware",
- vndk: {
- enabled: true,
- },
srcs: [
"types.hal",
"ISupplicant.hal",
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 011a955..504ccc4 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -577,6 +577,7 @@
EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
testing::Combine(
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 5f60746..11c55a6 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -348,6 +348,7 @@
EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkHidlTest);
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,
testing::Combine(