Merge "Update VtsHalEvsV1_1TargetTest"
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
index 7110b45..31459b4 100644
--- a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -14,4 +14,4 @@
interface android.hardware.atrace@1.0::IAtraceDevice default
class early_hal
user system
- group system
+ group system readtracefs
diff --git a/audio/7.1/Android.bp b/audio/7.1/Android.bp
new file mode 100644
index 0000000..cede72a
--- /dev/null
+++ b/audio/7.1/Android.bp
@@ -0,0 +1,31 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+hidl_interface {
+ name: "android.hardware.audio@7.1",
+ root: "android.hardware",
+ srcs: [
+ "types.hal",
+ "IDevice.hal",
+ "IDevicesFactory.hal",
+ "IPrimaryDevice.hal",
+ "IStreamOut.hal",
+ "IStreamOutLatencyModeCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio@7.0",
+ "android.hardware.audio.common@7.0",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: false,
+ gen_java_constants: false,
+}
diff --git a/audio/7.1/IDevice.hal b/audio/7.1/IDevice.hal
new file mode 100644
index 0000000..c158e7e
--- /dev/null
+++ b/audio/7.1/IDevice.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.1;
+
+import android.hardware.audio.common@7.0;
+import @7.0::AudioInOutFlag;
+import @7.0::IDevice;
+import @7.0::Result;
+import IStreamOut;
+
+interface IDevice extends @7.0::IDevice {
+ /**
+ * 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.
+ *
+ * Note: INVALID_ARGUMENTS is returned both in the case when the
+ * HAL can not use the provided config and in the case when
+ * the value of any argument is invalid. In the latter case the
+ * HAL must provide a default initialized suggested 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 the case of rejection of the proposed config,
+ * a config suggested by the HAL.
+ */
+ openOutputStream_7_1(
+ AudioIoHandle ioHandle,
+ DeviceAddress device,
+ AudioConfig config,
+ vec<AudioInOutFlag> flags,
+ SourceMetadata sourceMetadata) generates (
+ Result retval,
+ IStreamOut outStream,
+ AudioConfig suggestedConfig);
+
+ /**
+ * Notifies the device module about the connection state of an input/output
+ * device attached to it. The devicePort identifies the device and may also
+ * provide extra information such as raw audio descriptors.
+ *
+ * @param devicePort audio device port.
+ * @param connected whether the device is connected.
+ * @return retval operation completion status.
+ */
+ setConnectedState_7_1(AudioPort devicePort, bool connected)
+ generates (Result retval);
+};
diff --git a/audio/7.1/IDevicesFactory.hal b/audio/7.1/IDevicesFactory.hal
new file mode 100644
index 0000000..7669614
--- /dev/null
+++ b/audio/7.1/IDevicesFactory.hal
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.1;
+
+import @7.0::IDevicesFactory;
+import @7.0::Result;
+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.
+ */
+interface IDevicesFactory extends @7.0::IDevicesFactory {
+
+ /**
+ * Opens an audio device. To close the device, it is necessary to call
+ * 'close' method on the returned device object.
+ *
+ * Important note: due to rules of HIDL, @7.1::IPrimaryDevice extends
+ * @7.0::IPrimaryDevice, rather than @7.1::IDevice. Thus the returned
+ * IDevice interface can not be up-casted to @7.1::IPrimaryDevice for the
+ * primary device. The client needs to use IPrimaryDevice instead of this
+ * method if it needs full functionality of the IPrimaryDevice interface.
+ *
+ * @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_7_1(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_7_1() generates (Result retval, IPrimaryDevice result);
+};
diff --git a/audio/7.1/IPrimaryDevice.hal b/audio/7.1/IPrimaryDevice.hal
new file mode 100644
index 0000000..1659671
--- /dev/null
+++ b/audio/7.1/IPrimaryDevice.hal
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.1;
+
+import android.hardware.audio.common@7.0;
+import @7.0::IPrimaryDevice;
+import IDevice;
+
+interface IPrimaryDevice extends @7.0::IPrimaryDevice {
+ /**
+ * Retrieve the generic @7.1::IDevice interface.
+ *
+ * Since @7.1::IPrimaryDevice extends @7.0::IPrimaryDevice, the interface
+ * reference can not be downcasted to @7.1::IDevice using standard methods.
+ * For this reason a dedicated interface method is provided.
+ *
+ * @return result the generic part of the interface.
+ */
+ getDevice() generates (IDevice result);
+};
diff --git a/audio/7.1/IStreamOut.hal b/audio/7.1/IStreamOut.hal
new file mode 100644
index 0000000..b2013cf
--- /dev/null
+++ b/audio/7.1/IStreamOut.hal
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.1;
+
+import @7.0::Result;
+import @7.0::IStreamOut;
+
+import IStreamOutLatencyModeCallback;
+
+interface IStreamOut extends @7.0::IStreamOut {
+ /**
+ * Indicates the requested latency mode for this output stream.
+ *
+ * The requested mode can be one of the modes returned by
+ * getRecommendedLatencyModes() API.
+ *
+ * Optional method.
+ * Mandated only on specific spatial audio streams indicated by
+ * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+ *
+ * @return retval operation completion status.
+ */
+ setLatencyMode(LatencyMode mode) generates (Result retval);
+
+ /**
+ * Indicates which latency modes are currently supported on this output stream.
+ * If the transport protocol (e.g Bluetooth A2DP) used by this output stream to reach
+ * the output device supports variable latency modes, the HAL indicates which
+ * modes are currently supported.
+ * The framework can then call setLatencyMode() with one of the supported modes to select
+ * the desired operation mode.
+ *
+ * Optional method.
+ * Mandated only on specific spatial audio streams indicated by
+ * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+ *
+ * @return retval operation completion status.
+ * @return modes currrently supported latency modes.
+ */
+ getRecommendedLatencyModes() generates (Result retval, vec<LatencyMode> modes);
+
+ /**
+ * Set the callback interface for notifying changes in supported latency modes.
+ *
+ * Calling this method with a null pointer will result in releasing
+ * the callback.
+ *
+ * Optional method.
+ * Mandated only on specific spatial audio streams indicated by
+ * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+ *
+ * @return retval operation completion status.
+ */
+ setLatencyModeCallback(IStreamOutLatencyModeCallback callback) generates (Result retval);
+};
diff --git a/audio/7.1/IStreamOutLatencyModeCallback.hal b/audio/7.1/IStreamOutLatencyModeCallback.hal
new file mode 100644
index 0000000..45b453f
--- /dev/null
+++ b/audio/7.1/IStreamOutLatencyModeCallback.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.hardware.audio@7.1;
+
+/**
+ * Callback interface for output stream variable latency mode feature.
+ */
+interface IStreamOutLatencyModeCallback {
+ /**
+ * Called with the new list of supported latency modes when a change occurs.
+ */
+ oneway onRecommendedLatencyModeChanged(vec<LatencyMode> modes);
+};
diff --git a/audio/7.1/config/Android.bp b/audio/7.1/config/Android.bp
new file mode 100644
index 0000000..70c8fd4
--- /dev/null
+++ b/audio/7.1/config/Android.bp
@@ -0,0 +1,31 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+xsd_config {
+ name: "audio_policy_configuration_V7_1",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "android.audio.policy.configuration.V7_1",
+ nullability: true,
+}
+
+xsd_config {
+ name: "audio_policy_configuration_V7_1_enums",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "android.audio.policy.configuration.V7_1",
+ nullability: true,
+ enums_only: true,
+}
+
+xsd_config {
+ name: "audio_policy_configuration_V7_1_parser",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "android.audio.policy.configuration.V7_1",
+ nullability: true,
+ parser_only: true,
+}
diff --git a/audio/7.1/config/api/current.txt b/audio/7.1/config/api/current.txt
new file mode 100644
index 0000000..75fc5c0
--- /dev/null
+++ b/audio/7.1/config/api/current.txt
@@ -0,0 +1,603 @@
+// Signature format: 2.0
+package android.audio.policy.configuration.V7_1 {
+
+ public class AttachedDevices {
+ ctor public AttachedDevices();
+ method @Nullable public java.util.List<java.lang.String> getItem();
+ }
+
+ public enum AudioChannelMask {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_10;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_11;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_12;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_13;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_14;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_15;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_16;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_17;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_18;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_19;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_20;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_21;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_22;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_23;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_24;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_5;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_6;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_7;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_6;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_NONE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT_360RA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_22POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT0POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_BACK;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_6POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT6;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_HAPTIC_AB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_A;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_PENTA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_BACK;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_SIDE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_SURROUND;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_TRI;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_TRI_BACK;
+ }
+
+ public enum AudioContentType {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+ }
+
+ public enum AudioDevice {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_AUX_DIGITAL;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BACK_MIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLE_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BUILTIN_MIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BUS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_DEFAULT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI_EARC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_IP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_LINE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_PROXY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_SPDIF;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_STUB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_TELEPHONY_RX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_TV_TUNER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_ACCESSORY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_DEVICE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_VOICE_CALL;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_WIRED_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_NONE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_BROADCAST;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_SPEAKER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BUS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_DEFAULT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_EARPIECE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_FM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI_EARC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_IP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_LINE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_PROXY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPEAKER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_STUB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_TELEPHONY_TX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_DEVICE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ }
+
+ public enum AudioEncapsulationType {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+ }
+
+ public enum AudioFormat {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADIF;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_ELD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_ERLC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LTP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_MAIN;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_SCALABLE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_SSR;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_XHE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ELD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ERLC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_HE_V1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_HE_V2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_LC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LTP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_MAIN;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_SCALABLE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_SSR;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_XHE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AC3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AC4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_ALAC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_NB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_WB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_HD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_TWSP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_CELT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DEFAULT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DRA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DSD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS_HD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS_UHD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCNW;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCWB;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_E_AC3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_E_AC3_JOC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_FLAC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_HE_AAC_V1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_HE_AAC_V2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_IEC60958;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_IEC61937;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LC3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LDAC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LHDC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LHDC_LL;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_1_0;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_2_0;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_2_1;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MP2;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MP3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_BL_L3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_BL_L4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_LC_L3;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_LC_L4;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_OPUS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_16_BIT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_32_BIT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_8_24_BIT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_8_BIT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_FLOAT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_QCELP;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_SBC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_VORBIS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_WMA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_WMA_PRO;
+ }
+
+ public enum AudioGainMode {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_CHANNELS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_JOINT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_RAMP;
+ }
+
+ public enum AudioInOutFlag {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_FAST;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SPATIALIZER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_ULTRASOUND;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
+ }
+
+ public class AudioPolicyConfiguration {
+ ctor public AudioPolicyConfiguration();
+ method @Nullable public android.audio.policy.configuration.V7_1.GlobalConfiguration getGlobalConfiguration();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Modules> getModules();
+ method @Nullable public android.audio.policy.configuration.V7_1.SurroundSound getSurroundSound();
+ method @Nullable public android.audio.policy.configuration.V7_1.Version getVersion();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Volumes> getVolumes();
+ method public void setGlobalConfiguration(@Nullable android.audio.policy.configuration.V7_1.GlobalConfiguration);
+ method public void setSurroundSound(@Nullable android.audio.policy.configuration.V7_1.SurroundSound);
+ method public void setVersion(@Nullable android.audio.policy.configuration.V7_1.Version);
+ }
+
+ public enum AudioSource {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_CAMCORDER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_DEFAULT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_ECHO_REFERENCE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_FM_TUNER;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_HOTWORD;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_MIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_ULTRASOUND;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_UNPROCESSED;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_CALL;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_DOWNLINK;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_PERFORMANCE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_RECOGNITION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_UPLINK;
+ }
+
+ public enum AudioStreamType {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ACCESSIBILITY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ALARM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ASSISTANT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_BLUETOOTH_SCO;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_CALL_ASSISTANT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_DTMF;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ENFORCED_AUDIBLE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_MUSIC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_NOTIFICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_PATCH;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_REROUTING;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_RING;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_SYSTEM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_TTS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_VOICE_CALL;
+ }
+
+ public enum AudioUsage {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ALARM;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_EMERGENCY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_GAME;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_MEDIA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_SAFETY;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_UNKNOWN;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ }
+
+ public enum DeviceCategory {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+ enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+ enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_HEADSET;
+ enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+ enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+ }
+
+ public class DevicePorts {
+ ctor public DevicePorts();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.DevicePorts.DevicePort> getDevicePort();
+ }
+
+ public static class DevicePorts.DevicePort {
+ ctor public DevicePorts.DevicePort();
+ method @Nullable public String getAddress();
+ method @Nullable public java.util.List<java.lang.String> getEncodedFormats();
+ method @Nullable public android.audio.policy.configuration.V7_1.Gains getGains();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Profile> getProfile();
+ method @Nullable public android.audio.policy.configuration.V7_1.Role getRole();
+ method @Nullable public String getTagName();
+ method @Nullable public String getType();
+ method @Nullable public boolean get_default();
+ method public void setAddress(@Nullable String);
+ method public void setEncodedFormats(@Nullable java.util.List<java.lang.String>);
+ method public void setGains(@Nullable android.audio.policy.configuration.V7_1.Gains);
+ method public void setRole(@Nullable android.audio.policy.configuration.V7_1.Role);
+ method public void setTagName(@Nullable String);
+ method public void setType(@Nullable String);
+ method public void set_default(@Nullable boolean);
+ }
+
+ public enum EngineSuffix {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.EngineSuffix _default;
+ enum_constant public static final android.audio.policy.configuration.V7_1.EngineSuffix configurable;
+ }
+
+ public class Gains {
+ ctor public Gains();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Gains.Gain> getGain();
+ }
+
+ public static class Gains.Gain {
+ ctor public Gains.Gain();
+ method @Nullable public android.audio.policy.configuration.V7_1.AudioChannelMask getChannel_mask();
+ method @Nullable public int getDefaultValueMB();
+ method @Nullable public int getMaxRampMs();
+ method @Nullable public int getMaxValueMB();
+ method @Nullable public int getMinRampMs();
+ method @Nullable public int getMinValueMB();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioGainMode> getMode();
+ method @Nullable public String getName();
+ method @Nullable public int getStepValueMB();
+ method @Nullable public boolean getUseForVolume();
+ method public void setChannel_mask(@Nullable android.audio.policy.configuration.V7_1.AudioChannelMask);
+ method public void setDefaultValueMB(@Nullable int);
+ method public void setMaxRampMs(@Nullable int);
+ method public void setMaxValueMB(@Nullable int);
+ method public void setMinRampMs(@Nullable int);
+ method public void setMinValueMB(@Nullable int);
+ method public void setMode(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioGainMode>);
+ method public void setName(@Nullable String);
+ method public void setStepValueMB(@Nullable int);
+ method public void setUseForVolume(@Nullable boolean);
+ }
+
+ public class GlobalConfiguration {
+ ctor public GlobalConfiguration();
+ method @Nullable public boolean getCall_screen_mode_supported();
+ method @Nullable public android.audio.policy.configuration.V7_1.EngineSuffix getEngine_library();
+ method @Nullable public boolean getSpeaker_drc_enabled();
+ method public void setCall_screen_mode_supported(@Nullable boolean);
+ method public void setEngine_library(@Nullable android.audio.policy.configuration.V7_1.EngineSuffix);
+ method public void setSpeaker_drc_enabled(@Nullable boolean);
+ }
+
+ public enum HalVersion {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.HalVersion _2_0;
+ enum_constant public static final android.audio.policy.configuration.V7_1.HalVersion _3_0;
+ }
+
+ public class MixPorts {
+ ctor public MixPorts();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.MixPorts.MixPort> getMixPort();
+ }
+
+ public static class MixPorts.MixPort {
+ ctor public MixPorts.MixPort();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioInOutFlag> getFlags();
+ method @Nullable public android.audio.policy.configuration.V7_1.Gains getGains();
+ method @Nullable public long getMaxActiveCount();
+ method @Nullable public long getMaxOpenCount();
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioUsage> getPreferredUsage();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Profile> getProfile();
+ method @Nullable public long getRecommendedMuteDurationMs();
+ method @Nullable public android.audio.policy.configuration.V7_1.Role getRole();
+ method public void setFlags(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioInOutFlag>);
+ method public void setGains(@Nullable android.audio.policy.configuration.V7_1.Gains);
+ method public void setMaxActiveCount(@Nullable long);
+ method public void setMaxOpenCount(@Nullable long);
+ method public void setName(@Nullable String);
+ method public void setPreferredUsage(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioUsage>);
+ method public void setRecommendedMuteDurationMs(@Nullable long);
+ method public void setRole(@Nullable android.audio.policy.configuration.V7_1.Role);
+ }
+
+ public enum MixType {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.MixType mix;
+ enum_constant public static final android.audio.policy.configuration.V7_1.MixType mux;
+ }
+
+ public class Modules {
+ ctor public Modules();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Modules.Module> getModule();
+ }
+
+ public static class Modules.Module {
+ ctor public Modules.Module();
+ method @Nullable public android.audio.policy.configuration.V7_1.AttachedDevices getAttachedDevices();
+ method @Nullable public String getDefaultOutputDevice();
+ method @Nullable public android.audio.policy.configuration.V7_1.DevicePorts getDevicePorts();
+ method @Nullable public android.audio.policy.configuration.V7_1.HalVersion getHalVersion();
+ method @Nullable public android.audio.policy.configuration.V7_1.MixPorts getMixPorts();
+ method @Nullable public String getName();
+ method @Nullable public android.audio.policy.configuration.V7_1.Routes getRoutes();
+ method public void setAttachedDevices(@Nullable android.audio.policy.configuration.V7_1.AttachedDevices);
+ method public void setDefaultOutputDevice(@Nullable String);
+ method public void setDevicePorts(@Nullable android.audio.policy.configuration.V7_1.DevicePorts);
+ method public void setHalVersion(@Nullable android.audio.policy.configuration.V7_1.HalVersion);
+ method public void setMixPorts(@Nullable android.audio.policy.configuration.V7_1.MixPorts);
+ method public void setName(@Nullable String);
+ method public void setRoutes(@Nullable android.audio.policy.configuration.V7_1.Routes);
+ }
+
+ public class Profile {
+ ctor public Profile();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioChannelMask> getChannelMasks();
+ method @Nullable public android.audio.policy.configuration.V7_1.AudioEncapsulationType getEncapsulationType();
+ method @Nullable public String getFormat();
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
+ method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioChannelMask>);
+ method public void setEncapsulationType(@Nullable android.audio.policy.configuration.V7_1.AudioEncapsulationType);
+ method public void setFormat(@Nullable String);
+ method public void setName(@Nullable String);
+ method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
+ }
+
+ public class Reference {
+ ctor public Reference();
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<java.lang.String> getPoint();
+ method public void setName(@Nullable String);
+ }
+
+ public enum Role {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.Role sink;
+ enum_constant public static final android.audio.policy.configuration.V7_1.Role source;
+ }
+
+ public class Routes {
+ ctor public Routes();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Routes.Route> getRoute();
+ }
+
+ public static class Routes.Route {
+ ctor public Routes.Route();
+ method @Nullable public String getSink();
+ method @Nullable public String getSources();
+ method @Nullable public android.audio.policy.configuration.V7_1.MixType getType();
+ method public void setSink(@Nullable String);
+ method public void setSources(@Nullable String);
+ method public void setType(@Nullable android.audio.policy.configuration.V7_1.MixType);
+ }
+
+ public class SurroundFormats {
+ ctor public SurroundFormats();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.SurroundFormats.Format> getFormat();
+ }
+
+ public static class SurroundFormats.Format {
+ ctor public SurroundFormats.Format();
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<java.lang.String> getSubformats();
+ method public void setName(@Nullable String);
+ method public void setSubformats(@Nullable java.util.List<java.lang.String>);
+ }
+
+ public class SurroundSound {
+ ctor public SurroundSound();
+ method @Nullable public android.audio.policy.configuration.V7_1.SurroundFormats getFormats();
+ method public void setFormats(@Nullable android.audio.policy.configuration.V7_1.SurroundFormats);
+ }
+
+ public enum Version {
+ method @NonNull public String getRawName();
+ enum_constant public static final android.audio.policy.configuration.V7_1.Version _7_0;
+ enum_constant public static final android.audio.policy.configuration.V7_1.Version _7_1;
+ }
+
+ public class Volume {
+ ctor public Volume();
+ method @Nullable public android.audio.policy.configuration.V7_1.DeviceCategory getDeviceCategory();
+ method @Nullable public java.util.List<java.lang.String> getPoint();
+ method @Nullable public String getRef();
+ method @Nullable public android.audio.policy.configuration.V7_1.AudioStreamType getStream();
+ method public void setDeviceCategory(@Nullable android.audio.policy.configuration.V7_1.DeviceCategory);
+ method public void setRef(@Nullable String);
+ method public void setStream(@Nullable android.audio.policy.configuration.V7_1.AudioStreamType);
+ }
+
+ public class Volumes {
+ ctor public Volumes();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Reference> getReference();
+ method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Volume> getVolume();
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method @Nullable public static android.audio.policy.configuration.V7_1.AudioPolicyConfiguration read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/audio/7.1/config/api/last_current.txt b/audio/7.1/config/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/7.1/config/api/last_current.txt
diff --git a/audio/7.1/config/api/last_removed.txt b/audio/7.1/config/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/7.1/config/api/last_removed.txt
diff --git a/audio/7.1/config/api/removed.txt b/audio/7.1/config/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/7.1/config/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/7.1/config/audio_policy_configuration.xsd b/audio/7.1/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..7e1da90
--- /dev/null
+++ b/audio/7.1/config/audio_policy_configuration.xsd
@@ -0,0 +1,825 @@
+<?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="7.0"/>
+ <xs:enumeration value="7.1"/>
+ </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_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_SPATIALIZER" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_ULTRASOUND" />
+ <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:enumeration value="AUDIO_INPUT_FLAG_ULTRASOUND" />
+ </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:attribute name="recommendedMuteDurationMs" type="xs:unsignedInt"/>
+ </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_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_EARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <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_BLE_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_BROADCAST"/>
+ <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_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <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_HDMI_EARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLE_HEADSET"/>
+ <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. Vendors must namespace their names to avoid conflicts. The
+ namespace part must only use capital latin characters and decimal digits and
+ consist of at least 3 characters. The part of the extension name after the
+ namespace may in addition include underscores. Example for a hypothetical
+ Google virtual reality device:
+
+ <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink" />
+ -->
+ <xs:restriction base="xs:string">
+ <xs:pattern value="VX_[A-Z0-9]{3,}_[_A-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_XHE"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+ <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+ <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_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_AAC_ADTS_XHE"/>
+ <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_MAT"/>
+ <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_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:enumeration value="AUDIO_FORMAT_LC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_MPEGH_BL_L3"/>
+ <xs:enumeration value="AUDIO_FORMAT_MPEGH_BL_L4"/>
+ <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L3"/>
+ <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L4"/>
+ <xs:enumeration value="AUDIO_FORMAT_IEC60958"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_UHD"/>
+ <xs:enumeration value="AUDIO_FORMAT_DRA"/>
+ </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_NOTIFICATION_EVENT" />
+ <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:enumeration value="AUDIO_CONTENT_TYPE_ULTRASOUND"/>
+ </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_NONE"/>
+ <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_TRI"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_TRI_BACK"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT1"/>
+ <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_9POINT1POINT4"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT6"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT_360RA"/>
+ <xs:enumeration value="AUDIO_CHANNEL_OUT_22POINT2"/>
+ <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:simpleType name="audioEncapsulationType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+ </xs:restriction>
+ </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:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/>
+ </xs:complexType>
+ <xs:simpleType name="audioGainMode">
+ <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:simpleType name="audioGainModeMaskUnrestricted">
+ <xs:list itemType="audioGainMode" />
+ </xs:simpleType>
+ <xs:simpleType name='audioGainModeMask'>
+ <xs:restriction base='audioGainModeMaskUnrestricted'>
+ <xs:minLength value='1' />
+ </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="audioGainModeMask" 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:enumeration value="AUDIO_STREAM_CALL_ASSISTANT"/>
+ </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:enumeration value="AUDIO_SOURCE_ULTRASOUND"/>
+ </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="extendableAudioFormat" />
+ </xs:simpleType>
+ <xs:complexType name="surroundFormats">
+ <xs:sequence>
+ <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="extendableAudioFormat" 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.1/types.hal b/audio/7.1/types.hal
new file mode 100644
index 0000000..9d8ee4d
--- /dev/null
+++ b/audio/7.1/types.hal
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio@7.1;
+
+/**
+ * Latency modes used for the variable latency feature on output streams.
+ * Used by setLatencyMode() and getRecommendedLatencyModes() methods.
+ */
+
+@export(name="audio_latency_mode_t", value_prefix="AUDIO_LATENCY_MODE_")
+enum LatencyMode : int32_t {
+ /** No specific constraint on the latency */
+ FREE = 0,
+ /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
+ LOW = 1,
+};
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
new file mode 100644
index 0000000..6a0cfa5
--- /dev/null
+++ b/audio/aidl/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.audio.common",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/audio/common/PlaybackTrackMetadata.aidl",
+ "android/hardware/audio/common/RecordTrackMetadata.aidl",
+ "android/hardware/audio/common/SinkMetadata.aidl",
+ "android/hardware/audio/common/SourceMetadata.aidl",
+ ],
+ imports: [
+ "android.media.audio.common.types",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ platform_apis: true,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth",
+ ],
+ min_sdk_version: "31",
+ },
+ },
+ versions: [
+ ],
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..8fe8696
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable PlaybackTrackMetadata {
+ android.media.audio.common.AudioUsage usage = android.media.audio.common.AudioUsage.INVALID;
+ android.media.audio.common.AudioContentType contentType = android.media.audio.common.AudioContentType.UNKNOWN;
+ float gain;
+ @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..50330ef
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable RecordTrackMetadata {
+ android.media.audio.common.AudioSource source = android.media.audio.common.AudioSource.SYS_RESERVED_INVALID;
+ float gain;
+ @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..270147d
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SinkMetadata {
+ android.hardware.audio.common.RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..2d4a982
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SourceMetadata {
+ android.hardware.audio.common.PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..28a2f32
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.media.audio.common.AudioContentType;
+import android.media.audio.common.AudioUsage;
+
+/**
+ * Metadata of a playback track for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable PlaybackTrackMetadata {
+ AudioUsage usage = AudioUsage.INVALID;
+ AudioContentType contentType = AudioContentType.UNKNOWN;
+ /**
+ * Non-negative linear gain (scaling) applied to track samples.
+ * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+ */
+ float gain;
+ /**
+ * Tags from AudioTrack audio attributes. Tag is an additional use case
+ * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+ * vendor specific applications and must be prefixed by "VX_". Vendor must
+ * namespace their tag names to avoid conflicts, for example:
+ * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+ * namespace.
+ */
+ @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..9a59b41
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.media.audio.common.AudioSource;
+
+/**
+ * Metadata of a record track for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable RecordTrackMetadata {
+ AudioSource source = AudioSource.SYS_RESERVED_INVALID;
+ /**
+ * Non-negative linear gain (scaling) applied to track samples.
+ * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+ */
+ float gain;
+ /**
+ * Tags from AudioRecord audio attributes. Tag is an additional use case
+ * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+ * vendor specific applications and must be prefixed by "VX_". Vendor must
+ * namespace their tag names to avoid conflicts, for example:
+ * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+ * namespace.
+ */
+ @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..188c847
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.audio.common.RecordTrackMetadata;
+
+/**
+ * Metadata of record tracks for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SinkMetadata {
+ RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..e9f23c6
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.audio.common.PlaybackTrackMetadata;
+
+/**
+ * Metadata of playback tracks for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SourceMetadata {
+ PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/common/7.1/Android.bp b/audio/common/7.1/Android.bp
new file mode 100644
index 0000000..a257510
--- /dev/null
+++ b/audio/common/7.1/Android.bp
@@ -0,0 +1,23 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+ name: "android.hardware.audio.common@7.1-enums",
+ vendor_available: true,
+ generated_headers: ["audio_policy_configuration_V7_1_enums"],
+ generated_sources: ["audio_policy_configuration_V7_1_enums"],
+ header_libs: ["libxsdc-utils"],
+ export_generated_headers: ["audio_policy_configuration_V7_1_enums"],
+ export_header_lib_headers: ["libxsdc-utils"],
+ export_include_dirs: ["enums/include"],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+}
diff --git a/audio/common/7.1/enums/OWNERS b/audio/common/7.1/enums/OWNERS
new file mode 100644
index 0000000..24071af
--- /dev/null
+++ b/audio/common/7.1/enums/OWNERS
@@ -0,0 +1,2 @@
+elaurent@google.com
+mnaganov@google.com
diff --git a/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h
new file mode 100644
index 0000000..6f6a0ca
--- /dev/null
+++ b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
+#define ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
+
+#include <sys/types.h>
+#include <regex>
+#include <string>
+
+#include <android_audio_policy_configuration_V7_1_enums.h>
+
+namespace android::audio::policy::configuration::V7_1 {
+
+static inline size_t getChannelCount(AudioChannelMask mask) {
+ switch (mask) {
+ case AudioChannelMask::AUDIO_CHANNEL_NONE:
+ return 0;
+ 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_OUT_TRI:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_TRI_BACK:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3:
+ return 3;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2:
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1:
+ 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_OUT_13POINT_360RA:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
+ return 13;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT4:
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
+ return 14;
+ case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15:
+ return 15;
+ case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT6:
+ 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_OUT_22POINT2:
+ 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_HDMI_EARC:
+ 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_BLE_HEADSET:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLE_SPEAKER:
+ case AudioDevice::AUDIO_DEVICE_OUT_BLE_BROADCAST:
+ 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_HDMI_EARC:
+ case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
+ case AudioDevice::AUDIO_DEVICE_IN_BLE_HEADSET:
+ 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));
+}
+
+static inline bool isTelephonyDevice(AudioDevice device) {
+ return device == AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX ||
+ device == AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX;
+}
+
+static inline bool isTelephonyDevice(const std::string& device) {
+ return isTelephonyDevice(stringToAudioDevice(device));
+}
+
+static inline bool maybeVendorExtension(const std::string& s) {
+ // Only checks whether the string starts with the "vendor prefix".
+ static const std::string vendorPrefix = "VX_";
+ return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
+static inline bool isVendorExtension(const std::string& s) {
+ // Must be the same as the "vendorExtension" rule from the XSD file.
+ static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+ return std::regex_match(s.begin(), s.end(), vendorExtension);
+}
+
+static inline bool isUnknownAudioChannelMask(const std::string& mask) {
+ return stringToAudioChannelMask(mask) == AudioChannelMask::UNKNOWN;
+}
+
+static inline bool isUnknownAudioContentType(const std::string& contentType) {
+ return stringToAudioContentType(contentType) == AudioContentType::UNKNOWN;
+}
+
+static inline bool isUnknownAudioDevice(const std::string& device) {
+ return stringToAudioDevice(device) == AudioDevice::UNKNOWN && !isVendorExtension(device);
+}
+
+static inline bool isUnknownAudioFormat(const std::string& format) {
+ return stringToAudioFormat(format) == AudioFormat::UNKNOWN && !isVendorExtension(format);
+}
+
+static inline bool isUnknownAudioGainMode(const std::string& mode) {
+ return stringToAudioGainMode(mode) == AudioGainMode::UNKNOWN;
+}
+
+static inline bool isUnknownAudioInOutFlag(const std::string& flag) {
+ return stringToAudioInOutFlag(flag) == AudioInOutFlag::UNKNOWN;
+}
+
+static inline bool isUnknownAudioSource(const std::string& source) {
+ return stringToAudioSource(source) == AudioSource::UNKNOWN;
+}
+
+static inline bool isUnknownAudioStreamType(const std::string& streamType) {
+ return stringToAudioStreamType(streamType) == AudioStreamType::UNKNOWN;
+}
+
+static inline bool isUnknownAudioUsage(const std::string& usage) {
+ return stringToAudioUsage(usage) == AudioUsage::UNKNOWN;
+}
+
+static inline bool isLinearPcm(AudioFormat format) {
+ switch (format) {
+ case AudioFormat::AUDIO_FORMAT_PCM_16_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_8_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_32_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_8_24_BIT:
+ case AudioFormat::AUDIO_FORMAT_PCM_FLOAT:
+ case AudioFormat::AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool isLinearPcm(const std::string& format) {
+ return isLinearPcm(stringToAudioFormat(format));
+}
+
+static inline bool isUnknownAudioEncapsulationType(const std::string& encapsulationType) {
+ return stringToAudioEncapsulationType(encapsulationType) == AudioEncapsulationType::UNKNOWN;
+}
+
+} // namespace android::audio::policy::configuration::V7_1
+
+#endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index 5a5b5d2..0fd2947 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -21,7 +21,7 @@
#define LOG_TAG "HidlUtils"
#include <log/log.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include <common/all-versions/HidlSupport.h>
#include <common/all-versions/VersionUtils.h>
@@ -31,11 +31,11 @@
namespace hardware {
namespace audio {
namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
namespace implementation {
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
#define CONVERT_CHECKED(expr, result) \
@@ -485,8 +485,12 @@
status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
if (halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST ||
halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT ||
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED) {
+#else
halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED ||
halUsage == AUDIO_USAGE_NOTIFICATION_EVENT) {
+#endif
halUsage = AUDIO_USAGE_NOTIFICATION;
}
*usage = audio_usage_to_string(halUsage);
@@ -1151,7 +1155,7 @@
}
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace COMMON_TYPES_CPP_VERSION
} // namespace common
} // namespace audio
} // namespace hardware
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 8f55744..9543674 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -157,6 +157,28 @@
],
}
+cc_library {
+ name: "android.hardware.audio.common@7.1-util",
+ defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [
+ "7.0/HidlUtils.cpp",
+ "HidlUtilsCommon.cpp",
+ "UuidUtils.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "libbase",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
// Note: this isn't a VTS test, but rather a unit test
// to verify correctness of conversion utilities.
cc_test {
@@ -189,6 +211,8 @@
name: "android.hardware.audio.common@7.0-util_tests",
defaults: ["android.hardware.audio.common-util_default"],
+ tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
srcs: ["tests/hidlutils_tests.cpp"],
// Use static linking to allow running in presubmit on
@@ -214,3 +238,37 @@
test_suites: ["device-tests"],
}
+
+cc_test {
+ name: "android.hardware.audio.common@7.1-util_tests",
+ defaults: ["android.hardware.audio.common-util_default"],
+
+ tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
+ srcs: ["tests/hidlutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.1.
+ static_libs: [
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio.common@7.0",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index 98ecc07..ad9dee2 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -17,7 +17,9 @@
#ifndef android_hardware_audio_Hidl_Utils_H_
#define android_hardware_audio_Hidl_Utils_H_
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
#include <memory>
#include <string>
@@ -29,11 +31,11 @@
namespace hardware {
namespace audio {
namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
namespace implementation {
using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
struct HidlUtils {
static status_t audioConfigFromHal(const audio_config_t& halConfig, bool isInput,
@@ -267,7 +269,7 @@
#endif // MAJOR_VERSION <= 6
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace COMMON_TYPES_CPP_VERSION
} // namespace common
} // namespace audio
} // namespace hardware
diff --git a/audio/common/all-versions/default/HidlUtilsCommon.cpp b/audio/common/all-versions/default/HidlUtilsCommon.cpp
index d2da193..bc3d870 100644
--- a/audio/common/all-versions/default/HidlUtilsCommon.cpp
+++ b/audio/common/all-versions/default/HidlUtilsCommon.cpp
@@ -20,7 +20,7 @@
namespace hardware {
namespace audio {
namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
namespace implementation {
status_t HidlUtils::audioPortConfigsFromHal(unsigned int numHalConfigs,
@@ -51,7 +51,7 @@
}
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace COMMON_TYPES_CPP_VERSION
} // namespace common
} // namespace audio
} // namespace hardware
diff --git a/audio/common/all-versions/default/TEST_MAPPING b/audio/common/all-versions/default/TEST_MAPPING
index c965113..780beea 100644
--- a/audio/common/all-versions/default/TEST_MAPPING
+++ b/audio/common/all-versions/default/TEST_MAPPING
@@ -5,6 +5,9 @@
},
{
"name": "android.hardware.audio.common@7.0-util_tests"
+ },
+ {
+ "name": "android.hardware.audio.common@7.1-util_tests"
}
]
}
diff --git a/audio/common/all-versions/default/UuidUtils.h b/audio/common/all-versions/default/UuidUtils.h
index cd04fb0..4a64f0a 100644
--- a/audio/common/all-versions/default/UuidUtils.h
+++ b/audio/common/all-versions/default/UuidUtils.h
@@ -20,7 +20,7 @@
#include <string>
// clang-format off
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
#include <system/audio.h>
@@ -32,7 +32,7 @@
namespace CPP_VERSION {
namespace implementation {
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
class UuidUtils {
public:
diff --git a/audio/common/all-versions/default/VersionUtils.h b/audio/common/all-versions/default/VersionUtils.h
index 9bfca0c..9771374 100644
--- a/audio/common/all-versions/default/VersionUtils.h
+++ b/audio/common/all-versions/default/VersionUtils.h
@@ -17,7 +17,30 @@
#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
#define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// A workaround for b/216149583 (vendor code having its own copy of VersionMacro.h)
+#ifndef COMMON_TYPES_MINOR_VERSION
+#define COMMON_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+#ifndef CORE_TYPES_MINOR_VERSION
+#define CORE_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+#ifndef COMMON_TYPES_FILE_VERSION
+#define COMMON_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., COMMON_TYPES_MINOR_VERSION)
+#endif
+#ifndef CORE_TYPES_FILE_VERSION
+#define CORE_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., CORE_TYPES_MINOR_VERSION)
+#endif
+#ifndef COMMON_TYPES_CPP_VERSION
+#define COMMON_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, COMMON_TYPES_MINOR_VERSION)
+#endif
+#ifndef CORE_TYPES_CPP_VERSION
+#define CORE_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, CORE_TYPES_MINOR_VERSION)
+#endif
+// End of workaround
+
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
namespace android {
namespace hardware {
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 1bd6abe..9890be2 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -52,6 +52,7 @@
shared_libs: [
"libcutils",
"libbinder",
+ "libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 89585b0..fbf6165 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,8 +20,10 @@
#include <string>
#include <vector>
+#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
+#include <dlfcn.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/LegacySupport.h>
#include <hwbinder/ProcessState.h>
@@ -45,6 +47,31 @@
return false;
}
+static bool registerExternalServiceImplementation(const std::string& libName,
+ const std::string& funcName) {
+ constexpr int dlMode = RTLD_LAZY;
+ void* handle = nullptr;
+ dlerror(); // clear
+ auto libPath = libName + ".so";
+ handle = dlopen(libPath.c_str(), dlMode);
+ if (handle == nullptr) {
+ const char* error = dlerror();
+ ALOGE("Failed to dlopen %s: %s", libPath.c_str(),
+ error != nullptr ? error : "unknown error");
+ return false;
+ }
+ binder_status_t (*factoryFunction)();
+ *(void**)(&factoryFunction) = dlsym(handle, funcName.c_str());
+ if (!factoryFunction) {
+ const char* error = dlerror();
+ ALOGE("Factory function %s not found in libName %s: %s", funcName.c_str(), libPath.c_str(),
+ error != nullptr ? error : "unknown error");
+ dlclose(handle);
+ return false;
+ }
+ return ((*factoryFunction)() == STATUS_OK);
+}
+
int main(int /* argc */, char* /* argv */ []) {
signal(SIGPIPE, SIG_IGN);
@@ -52,6 +79,9 @@
// start a threadpool for vndbinder interactions
::android::ProcessState::self()->startThreadPool();
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
const int32_t defaultValue = -1;
int32_t value =
property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
@@ -66,6 +96,7 @@
const std::vector<InterfacesList> mandatoryInterfaces = {
{
"Audio Core API",
+ "android.hardware.audio@7.1::IDevicesFactory",
"android.hardware.audio@7.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
"android.hardware.audio@5.0::IDevicesFactory",
@@ -100,6 +131,13 @@
"android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload"
}
};
+
+ const std::vector<std::pair<std::string,std::string>> optionalInterfaceSharedLibs = {
+ {
+ "android.hardware.bluetooth.audio-impl",
+ "createIBluetoothAudioProviderFactory",
+ },
+ };
// clang-format on
for (const auto& listIter : mandatoryInterfaces) {
@@ -116,5 +154,15 @@
"Could not register %s", interfaceFamilyName.c_str());
}
+ for (const auto& interfacePair : optionalInterfaceSharedLibs) {
+ const std::string& libraryName = interfacePair.first;
+ const std::string& interfaceLoaderFuncName = interfacePair.second;
+ if (registerExternalServiceImplementation(libraryName, interfaceLoaderFuncName)) {
+ ALOGI("%s() from %s success", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+ } else {
+ ALOGW("%s() from %s failed", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+ }
+ }
+
joinRpcThreadpool();
}
diff --git a/audio/common/all-versions/default/tests/hidlutils6_tests.cpp b/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
index 3a24e75..ca59b9d 100644
--- a/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
@@ -23,14 +23,14 @@
#include <system/audio.h>
using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
// Not generated automatically because DeviceAddress contains
// an union.
//
// operator== must be defined in the same namespace as the data type.
-namespace android::hardware::audio::common::CPP_VERSION {
+namespace android::hardware::audio::common::COMMON_TYPES_CPP_VERSION {
inline bool operator==(const DeviceAddress& lhs, const DeviceAddress& rhs) {
if (lhs.device != rhs.device) return false;
@@ -49,7 +49,7 @@
return lhs.busAddress == rhs.busAddress;
}
-} // namespace android::hardware::audio::common::CPP_VERSION
+} // namespace android::hardware::audio::common::COMMON_TYPES_CPP_VERSION
static void ConvertDeviceAddress(const DeviceAddress& device) {
audio_devices_t halDeviceType;
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index c9e6fac..ec16b02 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -23,16 +23,16 @@
#include <log/log.h>
#include <HidlUtils.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include <system/audio.h>
#include <xsdc/XsdcSupport.h>
using namespace android;
using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
diff --git a/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h b/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
index dc54cee..875e167 100644
--- a/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
+++ b/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
@@ -21,6 +21,14 @@
#error "MAJOR_VERSION and MINOR_VERSION must be defined"
#endif
+#ifndef COMMON_TYPES_MINOR_VERSION
+#define COMMON_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+
+#ifndef CORE_TYPES_MINOR_VERSION
+#define CORE_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+
/** Allows macro expansion for x and add surrounding `<>`.
* Is intended to be used for version dependant includes as
* `#include` do not macro expand if starting with < or "
@@ -34,10 +42,30 @@
#define EXPAND_CONCAT_3(a, b, c) CONCAT_3(a, b, c)
/** The directory name of the version: <major>.<minor> */
#define FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., MINOR_VERSION)
+#define COMMON_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., COMMON_TYPES_MINOR_VERSION)
+#define CORE_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., CORE_TYPES_MINOR_VERSION)
#define CONCAT_4(a, b, c, d) a##b##c##d
#define EXPAND_CONCAT_4(a, b, c, d) CONCAT_4(a, b, c, d)
/** The c++ namespace of the version: V<major>_<minor> */
#define CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, MINOR_VERSION)
+#define COMMON_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, COMMON_TYPES_MINOR_VERSION)
+#define CORE_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, CORE_TYPES_MINOR_VERSION)
+
+/* Gluing these file names from macros is non-trivial due to "illegal tokens"
+ occurring during expansion. The XSD and enums always use the minor version. */
+// clang-format off
+#if MAJOR_VERSION >= 7
+#if MINOR_VERSION == 0
+#define APM_XSD_H_FILENAME android_audio_policy_configuration_V7_0.h
+#define APM_XSD_ENUMS_H_FILENAME android_audio_policy_configuration_V7_0-enums.h
+#elif MINOR_VERSION == 1
+#define APM_XSD_H_FILENAME android_audio_policy_configuration_V7_1.h
+#define APM_XSD_ENUMS_H_FILENAME android_audio_policy_configuration_V7_1-enums.h
+#else
+#error "Unsupported minor version"
+#endif
+#endif
+// clang-format on
#endif // ANDROID_HARDWARE_VERSION_MACRO_H
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 8fb7111..3536561 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -48,6 +48,8 @@
"libhidlbase",
"liblog",
"libmedia_helper",
+ "libmediautils_vendor",
+ "libmemunreachable",
"libutils",
"android.hardware.audio.common-util",
],
@@ -159,3 +161,29 @@
name: "android.hardware.audio@7.0-impl",
defaults: ["android.hardware.audio@7.0-impl_default"],
}
+
+cc_defaults {
+ name: "android.hardware.audio@7.1-impl_default",
+ defaults: ["android.hardware.audio-impl_default"],
+ shared_libs: [
+ "android.hardware.audio@7.0",
+ "android.hardware.audio@7.1",
+ "android.hardware.audio@7.1-util",
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "libbase",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio@7.1-impl",
+ defaults: ["android.hardware.audio@7.1-impl_default"],
+}
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 130dfba..b954fcd 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -30,6 +30,8 @@
#include <algorithm>
#include <android/log.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
#include <HidlUtils.h>
@@ -39,7 +41,10 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}
@@ -82,7 +87,7 @@
if (mDevice->set_master_volume == NULL) {
return Result::NOT_SUPPORTED;
}
- if (!isGainNormalized(volume)) {
+ if (!util::isGainNormalized(volume)) {
ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
@@ -148,7 +153,7 @@
return Void();
}
-std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle,
+std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamCore(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const AudioOutputFlags& flags,
@@ -185,7 +190,7 @@
return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
}
-std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
+std::tuple<Result, sp<IStreamIn>> Device::openInputStreamCore(
int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
const AudioInputFlags& flags, AudioSource source, AudioConfig* suggestedConfig) {
audio_config_t halConfig;
@@ -228,7 +233,7 @@
openOutputStream_cb _hidl_cb) {
AudioConfig suggestedConfig;
auto [result, streamOut] =
- openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
+ openOutputStreamCore(ioHandle, device, config, flags, &suggestedConfig);
_hidl_cb(result, streamOut, suggestedConfig);
return Void();
}
@@ -238,12 +243,36 @@
AudioSource source, openInputStream_cb _hidl_cb) {
AudioConfig suggestedConfig;
auto [result, streamIn] =
- openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
+ openInputStreamCore(ioHandle, device, config, flags, source, &suggestedConfig);
_hidl_cb(result, streamIn, suggestedConfig);
return Void();
}
#elif MAJOR_VERSION >= 4
+std::tuple<Result, sp<IStreamOut>, AudioConfig> Device::openOutputStreamImpl(
+ int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+ const SourceMetadata& sourceMetadata,
+#if MAJOR_VERSION <= 6
+ AudioOutputFlags flags) {
+ if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
+ status != NO_ERROR) {
+#else
+ const AudioOutputFlags& flags) {
+ if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
+ false /*ignoreNonVendorTags*/, nullptr);
+ status != NO_ERROR) {
+#endif
+ return {analyzeStatus("sourceMetadataToHal", status), nullptr, {}};
+ }
+ AudioConfig suggestedConfig;
+ auto [result, streamOut] =
+ openOutputStreamCore(ioHandle, device, config, flags, &suggestedConfig);
+ if (streamOut) {
+ streamOut->updateSourceMetadata(sourceMetadata);
+ }
+ return {result, streamOut, suggestedConfig};
+}
+
Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config,
#if MAJOR_VERSION <= 6
@@ -253,27 +282,46 @@
#endif
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
-#if MAJOR_VERSION <= 6
- if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
- status != NO_ERROR) {
-#else
- if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
- false /*ignoreNonVendorTags*/, nullptr);
- status != NO_ERROR) {
-#endif
- _hidl_cb(analyzeStatus("sourceMetadataToHal", status), nullptr, AudioConfig{});
- return Void();
- }
- AudioConfig suggestedConfig;
- auto [result, streamOut] =
- openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
- if (streamOut) {
- streamOut->updateSourceMetadata(sourceMetadata);
- }
+ auto [result, streamOut, suggestedConfig] =
+ openOutputStreamImpl(ioHandle, device, config, sourceMetadata, flags);
_hidl_cb(result, streamOut, suggestedConfig);
return Void();
}
+std::tuple<Result, sp<IStreamIn>, AudioConfig> Device::openInputStreamImpl(
+ int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+#if MAJOR_VERSION <= 6
+ AudioInputFlags flags,
+#else
+ const AudioInputFlags& flags,
+#endif
+ const SinkMetadata& sinkMetadata) {
+ if (sinkMetadata.tracks.size() == 0) {
+ // This should never happen, the framework must not create as stream
+ // if there is no client
+ ALOGE("openInputStream called without tracks connected");
+ return {Result::INVALID_ARGUMENTS, nullptr, AudioConfig{}};
+ }
+#if MAJOR_VERSION <= 6
+ if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
+#else
+ if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+ false /*ignoreNonVendorTags*/, nullptr);
+ status != NO_ERROR) {
+#endif
+ return {analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{}};
+ }
+ // Pick the first one as the main.
+ AudioSource source = sinkMetadata.tracks[0].source;
+ AudioConfig suggestedConfig;
+ auto [result, streamIn] =
+ openInputStreamCore(ioHandle, device, config, flags, source, &suggestedConfig);
+ if (streamIn) {
+ streamIn->updateSinkMetadata(sinkMetadata);
+ }
+ return {result, streamIn, suggestedConfig};
+}
+
Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config,
#if MAJOR_VERSION <= 6
@@ -283,36 +331,25 @@
#endif
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) {
- if (sinkMetadata.tracks.size() == 0) {
- // This should never happen, the framework must not create as stream
- // if there is no client
- ALOGE("openInputStream called without tracks connected");
- _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig{});
- return Void();
- }
-#if MAJOR_VERSION <= 6
- if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
-#else
- if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
- false /*ignoreNonVendorTags*/, nullptr);
- status != NO_ERROR) {
-#endif
- _hidl_cb(analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{});
- return Void();
- }
- // Pick the first one as the main.
- AudioSource source = sinkMetadata.tracks[0].source;
- AudioConfig suggestedConfig;
- auto [result, streamIn] =
- openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
- if (streamIn) {
- streamIn->updateSinkMetadata(sinkMetadata);
- }
+ auto [result, streamIn, suggestedConfig] =
+ openInputStreamImpl(ioHandle, device, config, flags, sinkMetadata);
_hidl_cb(result, streamIn, suggestedConfig);
return Void();
}
#endif /* MAJOR_VERSION */
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<void> Device::openOutputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
+ const AudioConfig& config, const AudioOutputFlags& flags,
+ const SourceMetadata& sourceMetadata,
+ openOutputStream_7_1_cb _hidl_cb) {
+ auto [result, streamOut, suggestedConfig] =
+ openOutputStreamImpl(ioHandle, device, config, sourceMetadata, flags);
+ _hidl_cb(result, streamOut, suggestedConfig);
+ return Void();
+}
+#endif // V7.1
+
Return<bool> Device::supportsAudioPatches() {
return version() >= AUDIO_DEVICE_API_VERSION_3_0;
}
@@ -456,9 +493,32 @@
}
#endif
-Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
- analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+ const int fd0 = fd->data[0];
+ bool dumpMem = false;
+ bool unreachableMemory = false;
+ for (const auto& option : options) {
+ if (option == "-m") {
+ dumpMem = true;
+ } else if (option == "--unreachable") {
+ unreachableMemory = true;
+ }
+ }
+
+ if (dumpMem) {
+ dprintf(fd0, "\nDumping memory:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+ if (unreachableMemory) {
+ dprintf(fd0, "\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+
+ analyzeStatus("dump", mDevice->dump(mDevice, fd0));
}
return Void();
}
@@ -546,6 +606,21 @@
#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<Result> Device::setConnectedState_7_1(const AudioPort& devicePort, bool connected) {
+ if (version() >= AUDIO_DEVICE_API_VERSION_3_2 &&
+ mDevice->set_device_connected_state_v7 != nullptr) {
+ audio_port_v7 halPort;
+ if (status_t status = HidlUtils::audioPortToHal(devicePort, &halPort); status != NO_ERROR) {
+ return analyzeStatus("audioPortToHal", status);
+ }
+ return analyzeStatus("set_device_connected_state_v7",
+ mDevice->set_device_connected_state_v7(mDevice, &halPort, connected));
+ }
+ return Result::NOT_SUPPORTED;
+}
+#endif
+
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
diff --git a/audio/core/all-versions/default/DevicesFactory.cpp b/audio/core/all-versions/default/DevicesFactory.cpp
index 729f18c..f44daf0 100644
--- a/audio/core/all-versions/default/DevicesFactory.cpp
+++ b/audio/core/all-versions/default/DevicesFactory.cpp
@@ -47,22 +47,54 @@
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
return Void();
}
+
+Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
+ return openDevice<implementation::Device>(moduleName, _hidl_cb);
+}
#elif MAJOR_VERSION >= 4
Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
}
- return openDevice(moduleName.c_str(), _hidl_cb);
+ return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
}
Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
}
#endif
-Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
- return openDevice<implementation::Device>(moduleName, _hidl_cb);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<void> DevicesFactory::openDevice_7_1(const hidl_string& moduleName,
+ openDevice_7_1_cb _hidl_cb) {
+ if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
+ Result result;
+ sp<IPrimaryDevice> primary;
+ auto ret = openDevice<PrimaryDevice>(
+ AUDIO_HARDWARE_MODULE_ID_PRIMARY,
+ [&result, &primary](Result r, const sp<IPrimaryDevice>& p) {
+ result = r;
+ primary = p;
+ });
+ if (ret.isOk() && result == Result::OK && primary != nullptr) {
+ auto getDeviceRet = primary->getDevice();
+ if (getDeviceRet.isOk()) {
+ _hidl_cb(result, getDeviceRet);
+ } else {
+ _hidl_cb(Result::NOT_INITIALIZED, nullptr);
+ }
+ } else {
+ _hidl_cb(result, nullptr);
+ }
+ return Void();
+ }
+ return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
}
+Return<void> DevicesFactory::openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb) {
+ return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
+}
+#endif // V7.1
+
template <class DeviceShim, class Callback>
Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
audio_hw_device_t* halDevice;
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index 4d53645..e21eff2 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
namespace implementation {
/** Converts a status_t in Result according to the rules of AudioParameter::get*
@@ -168,7 +168,7 @@
}
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace CORE_TYPES_CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
diff --git a/audio/core/all-versions/default/PrimaryDevice.cpp b/audio/core/all-versions/default/PrimaryDevice.cpp
index fe56177..cf162f1 100644
--- a/audio/core/all-versions/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/PrimaryDevice.cpp
@@ -29,6 +29,10 @@
namespace CPP_VERSION {
namespace implementation {
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
+
PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
PrimaryDevice::~PrimaryDevice() {
@@ -195,7 +199,7 @@
// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
- if (!isGainNormalized(volume)) {
+ if (!util::isGainNormalized(volume)) {
ALOGW("Can not set a voice volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
@@ -326,7 +330,7 @@
return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz));
}
Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
- if (!isGainNormalized(volume)) {
+ if (!util::isGainNormalized(volume)) {
ALOGW("Can not set BT HFP volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 7e32573..8e85a8b 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -37,8 +37,12 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::splitString;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
Stream::Stream(bool isInput, audio_stream_t* stream) : mIsInput(isInput), mStream(stream) {
(void)mIsInput; // prevent 'unused field' warnings in pre-V7 versions.
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index 2aeee43..2bea425 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -37,7 +37,11 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
namespace {
@@ -348,7 +352,7 @@
}
Return<Result> StreamIn::setGain(float gain) {
- if (!isGainNormalized(gain)) {
+ if (!util::isGainNormalized(gain)) {
ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
return Result::INVALID_ARGUMENTS;
}
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index d027231..09df4ed 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -39,7 +39,11 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
namespace {
@@ -334,7 +338,7 @@
if (mStream->set_volume == NULL) {
return Result::NOT_SUPPORTED;
}
- if (!isGainNormalized(left)) {
+ if (!util::isGainNormalized(left)) {
ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
return Result::INVALID_ARGUMENTS;
}
@@ -757,6 +761,73 @@
ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
return 0;
}
+
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<Result> StreamOut::setLatencyMode(LatencyMode mode) {
+ return mStream->set_latency_mode != nullptr
+ ? Stream::analyzeStatus(
+ "set_latency_mode",
+ mStream->set_latency_mode(mStream,
+ static_cast<audio_latency_mode_t>(mode)))
+ : Result::NOT_SUPPORTED;
+};
+
+Return<void> StreamOut::getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) {
+ Result retval = Result::NOT_SUPPORTED;
+ hidl_vec<LatencyMode> hidlModes;
+ size_t num_modes = AUDIO_LATENCY_MODE_CNT;
+ audio_latency_mode_t modes[AUDIO_LATENCY_MODE_CNT];
+
+ if (mStream->get_recommended_latency_modes != nullptr &&
+ mStream->get_recommended_latency_modes(mStream, &modes[0], &num_modes) == 0) {
+ if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) {
+ ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes);
+ retval = Result::INVALID_STATE;
+ } else {
+ hidlModes.resize(num_modes);
+ for (size_t i = 0; i < num_modes; ++i) {
+ hidlModes[i] = static_cast<LatencyMode>(modes[i]);
+ }
+ retval = Result::OK;
+ }
+ }
+ _hidl_cb(retval, hidlModes);
+ return Void();
+};
+
+// static
+void StreamOut::latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie) {
+ StreamOut* self = reinterpret_cast<StreamOut*>(cookie);
+ sp<IStreamOutLatencyModeCallback> callback = self->mLatencyModeCallback.load();
+ if (callback.get() == nullptr) return;
+
+ ALOGV("%s", __func__);
+
+ if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) {
+ ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes);
+ return;
+ }
+
+ hidl_vec<LatencyMode> hidlModes(num_modes);
+ for (size_t i = 0; i < num_modes; ++i) {
+ hidlModes[i] = static_cast<LatencyMode>(modes[i]);
+ }
+ Return<void> result = callback->onRecommendedLatencyModeChanged(hidlModes);
+ ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
+}
+
+Return<Result> StreamOut::setLatencyModeCallback(
+ const sp<IStreamOutLatencyModeCallback>& callback) {
+ if (mStream->set_latency_mode_callback == nullptr) return Result::NOT_SUPPORTED;
+ int result = mStream->set_latency_mode_callback(mStream, StreamOut::latencyModeCallback, this);
+ if (result == 0) {
+ mLatencyModeCallback = callback;
+ }
+ return Stream::analyzeStatus("set_latency_mode_callback", result, {ENOSYS} /*ignore*/);
+};
+
+#endif
+
#endif
} // namespace implementation
diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING
index 1e29440..07e98f3 100644
--- a/audio/core/all-versions/default/TEST_MAPPING
+++ b/audio/core/all-versions/default/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "android.hardware.audio@7.0-util_tests"
},
{
+ "name": "android.hardware.audio@7.1-util_tests"
+ },
+ {
"name": "HalAudioV6_0GeneratorTest"
},
{
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 94cad53..0696f97 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -44,7 +44,10 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::ParametersUtil;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
using AudioInputFlags = CoreUtils::AudioInputFlags;
using AudioOutputFlags = CoreUtils::AudioOutputFlags;
@@ -63,14 +66,32 @@
Return<void> getInputBufferSize(const AudioConfig& config,
getInputBufferSize_cb _hidl_cb) override;
- std::tuple<Result, sp<IStreamOut>> openOutputStreamImpl(int32_t ioHandle,
+ std::tuple<Result, sp<IStreamOut>> openOutputStreamCore(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const AudioOutputFlags& flags,
AudioConfig* suggestedConfig);
- std::tuple<Result, sp<IStreamIn>> openInputStreamImpl(
+ std::tuple<Result, sp<IStreamIn>> openInputStreamCore(
int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
const AudioInputFlags& flags, AudioSource source, AudioConfig* suggestedConfig);
+#if MAJOR_VERSION >= 4
+ std::tuple<Result, sp<IStreamOut>, AudioConfig> openOutputStreamImpl(
+ int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+ const SourceMetadata& sourceMetadata,
+#if MAJOR_VERSION <= 6
+ AudioOutputFlags flags);
+#else
+ const AudioOutputFlags& flags);
+#endif
+ std::tuple<Result, sp<IStreamIn>, AudioConfig> openInputStreamImpl(
+ int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+#if MAJOR_VERSION <= 6
+ AudioInputFlags flags,
+#else
+ const AudioInputFlags& flags,
+#endif
+ const SinkMetadata& sinkMetadata);
+#endif // MAJOR_VERSION >= 4
Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config,
@@ -97,6 +118,13 @@
#endif
openInputStream_cb _hidl_cb) override;
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<void> openOutputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
+ const AudioConfig& config, const AudioOutputFlags& flags,
+ const SourceMetadata& sourceMetadata,
+ openOutputStream_7_1_cb _hidl_cb) override;
+#endif
+
Return<bool> supportsAudioPatches() override;
Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
@@ -131,6 +159,9 @@
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) override;
#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<Result> setConnectedState_7_1(const AudioPort& devicePort, bool connected) override;
+#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Utility methods for extending interfaces.
diff --git a/audio/core/all-versions/default/include/core/default/DevicesFactory.h b/audio/core/all-versions/default/include/core/default/DevicesFactory.h
index 9f93a38..566bc8a 100644
--- a/audio/core/all-versions/default/include/core/default/DevicesFactory.h
+++ b/audio/core/all-versions/default/include/core/default/DevicesFactory.h
@@ -44,11 +44,17 @@
Return<void> openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override;
Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<void> openDevice_7_1(const hidl_string& device, openDevice_7_1_cb _hidl_cb) override;
+ Return<void> openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb) override;
+#endif
- private:
+ private:
template <class DeviceShim, class Callback>
Return<void> openDevice(const char* moduleName, Callback _hidl_cb);
+#if MAJOR_VERSION == 2
Return<void> openDevice(const char* moduleName, openDevice_cb _hidl_cb);
+#endif
static int loadAudioInterface(const char* if_name, audio_hw_device_t** dev);
};
diff --git a/audio/core/all-versions/default/include/core/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/default/ParametersUtil.h
index 45d9b21..25c193a 100644
--- a/audio/core/all-versions/default/include/core/default/ParametersUtil.h
+++ b/audio/core/all-versions/default/include/core/default/ParametersUtil.h
@@ -17,7 +17,10 @@
#ifndef ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
#define ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+// clang-format on
#include <functional>
#include <memory>
@@ -28,13 +31,13 @@
namespace android {
namespace hardware {
namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
namespace implementation {
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
class ParametersUtil {
public:
@@ -62,7 +65,7 @@
};
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace CORE_TYPES_CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
diff --git a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
index 5f65acf..8b37e01 100644
--- a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
+++ b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
@@ -36,7 +36,8 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct PrimaryDevice : public IPrimaryDevice {
@@ -135,8 +136,10 @@
Return<Result> setBtHfpVolume(float volume) override;
Return<Result> updateRotation(IPrimaryDevice::Rotation rotation) override;
#endif
-
- private:
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<sp<::android::hardware::audio::V7_1::IDevice>> getDevice() override { return mDevice; }
+#endif
+ private:
sp<Device> mDevice;
virtual ~PrimaryDevice();
diff --git a/audio/core/all-versions/default/include/core/default/Stream.h b/audio/core/all-versions/default/include/core/default/Stream.h
index 66d60e3..4e79884 100644
--- a/audio/core/all-versions/default/include/core/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/default/Stream.h
@@ -17,7 +17,9 @@
#ifndef ANDROID_HARDWARE_AUDIO_STREAM_H
#define ANDROID_HARDWARE_AUDIO_STREAM_H
-#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
+// clang-format off
+#include PATH(android/hardware/audio/COMMON_TYPES_FILE_VERSION/IStream.h)
+// clang-format on
#include "ParametersUtil.h"
@@ -41,10 +43,13 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::ParametersUtil;
#if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+ AudioChannelBitfield;
#endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct Stream : public IStream, public ParametersUtil {
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index a980f3f..4627eec 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -17,7 +17,9 @@
#ifndef ANDROID_HARDWARE_AUDIO_STREAMIN_H
#define ANDROID_HARDWARE_AUDIO_STREAMIN_H
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamIn.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
+// clang-format on
#include "Device.h"
#include "Stream.h"
@@ -42,7 +44,8 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct StreamIn : public IStreamIn {
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index 0b07972..ce5253f 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -43,7 +43,8 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct StreamOut : public IStreamOut {
@@ -152,6 +153,12 @@
Result doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
#if MAJOR_VERSION >= 7
Result doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<Result> setLatencyMode(LatencyMode mode) override;
+ Return<void> getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) override;
+ Return<Result> setLatencyModeCallback(
+ const sp<IStreamOutLatencyModeCallback>& callback) override;
+#endif
#endif
#endif // MAJOR_VERSION >= 4
@@ -162,6 +169,9 @@
mediautils::atomic_sp<IStreamOutCallback> mCallback; // for non-blocking write and drain
#if MAJOR_VERSION >= 6
mediautils::atomic_sp<IStreamOutEventCallback> mEventCallback;
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ mediautils::atomic_sp<IStreamOutLatencyModeCallback> mLatencyModeCallback;
+#endif
#endif
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
@@ -176,6 +186,9 @@
#if MAJOR_VERSION >= 6
static int asyncEventCallback(stream_event_callback_type_t event, void* param, void* cookie);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ static void latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie);
+#endif
#endif
};
diff --git a/audio/core/all-versions/default/include/core/default/Util.h b/audio/core/all-versions/default/include/core/default/Util.h
index 78ae03e..abf5317 100644
--- a/audio/core/all-versions/default/include/core/default/Util.h
+++ b/audio/core/all-versions/default/include/core/default/Util.h
@@ -17,7 +17,9 @@
#ifndef ANDROID_HARDWARE_AUDIO_UTIL_H
#define ANDROID_HARDWARE_AUDIO_UTIL_H
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+// clang-format on
#include <algorithm>
#include <vector>
@@ -27,19 +29,19 @@
namespace android {
namespace hardware {
namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
namespace implementation {
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
+
+namespace util {
/** @return true if gain is between 0 and 1 included. */
constexpr bool isGainNormalized(float gain) {
return gain >= 0.0 && gain <= 1.0;
}
-namespace util {
-
template <typename T>
inline bool element_in(T e, const std::vector<T>& v) {
return std::find(v.begin(), v.end(), e) != v.end();
@@ -72,7 +74,7 @@
} // namespace util
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace CORE_TYPES_CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
index 7caf18d..b96f2d2 100644
--- a/audio/core/all-versions/default/util/Android.bp
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -112,6 +112,25 @@
],
}
+cc_library {
+ name: "android.hardware.audio@7.1-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio@7.1",
+ "libbase",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
// Note: this isn't a VTS test, but rather a unit test
// to verify correctness of conversion utilities.
cc_test {
@@ -145,3 +164,37 @@
test_suites: ["device-tests"],
}
+
+cc_test {
+ name: "android.hardware.audio@7.1-util_tests",
+ defaults: ["android.hardware.audio-util_default"],
+
+ srcs: ["tests/coreutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.1.
+ static_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio@7.1",
+ "android.hardware.audio@7.1-util",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
index 773be21..8e83ea1 100644
--- a/audio/core/all-versions/default/util/CoreUtils.cpp
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -15,24 +15,24 @@
*/
#if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#endif
#include <HidlUtils.h>
#include <log/log.h>
#include "util/CoreUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
#if MAJOR_VERSION >= 7
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
#endif
namespace android {
namespace hardware {
namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
namespace implementation {
#define CONVERT_CHECKED(expr, result) \
@@ -389,7 +389,7 @@
#if MAJOR_VERSION >= 7
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
status_t CoreUtils::audioInputFlagsFromHal(audio_input_flags_t halFlagMask,
@@ -470,7 +470,7 @@
#endif
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace CORE_TYPES_CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
diff --git a/audio/core/all-versions/default/util/include/util/CoreUtils.h b/audio/core/all-versions/default/util/include/util/CoreUtils.h
index 1e5272a..dc35772 100644
--- a/audio/core/all-versions/default/util/include/util/CoreUtils.h
+++ b/audio/core/all-versions/default/util/include/util/CoreUtils.h
@@ -17,7 +17,7 @@
#pragma once
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
// clang-format off
#include <vector>
@@ -30,13 +30,13 @@
namespace android {
namespace hardware {
namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
namespace implementation {
using ::android::hardware::audio::common::utils::EnumBitfield;
using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
struct CoreUtils {
// Note: the converters for DeviceAddress have to be in CoreUtils for HAL V4
@@ -93,8 +93,8 @@
return NO_ERROR;
}
#else
- using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
- using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+ using AudioInputFlags = hidl_vec<::android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>;
+ using AudioOutputFlags = hidl_vec<::android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>;
static status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags);
static status_t audioInputFlagsToHal(const AudioInputFlags& flags, audio_input_flags_t* halFlagMask);
static status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags);
diff --git a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
index 0c18482..0e15960 100644
--- a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
+++ b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
@@ -22,18 +22,18 @@
#define LOG_TAG "CoreUtils_Test"
#include <log/log.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include <system/audio.h>
#include <util/CoreUtils.h>
#include <xsdc/XsdcSupport.h>
using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
diff --git a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
index 1cffd41..dd80dd6 100644
--- a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
@@ -14,16 +14,18 @@
* limitations under the License.
*/
+// clang-format off
#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
#include <hidl/HidlSupport.h>
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioFormat;
using ::android::hardware::audio::CPP_VERSION::IStream;
using ::android::hardware::audio::CPP_VERSION::ParameterValue;
using ::android::hardware::audio::CPP_VERSION::Result;
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 787654b..7f4a777 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -17,7 +17,7 @@
#include "AudioPrimaryHidlHalTest.h"
#if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_H_FILENAME)
#include <xsdc/XsdcSupport.h>
using android::xsdc_enum_range;
@@ -28,17 +28,36 @@
if (getDeviceName() != DeviceManager::kPrimaryDevice) {
GTEST_SKIP() << "No primary device on this factory"; // returns
}
+ EXPECT_TRUE(DeviceManager::getInstance().resetPrimary(getFactoryName()));
- { // Scope for device SPs
- sp<IDevice> baseDevice =
- DeviceManager::getInstance().get(getFactoryName(), DeviceManager::kPrimaryDevice);
- ASSERT_TRUE(baseDevice != nullptr);
- Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+ // Must use IDevicesFactory directly because DeviceManager always uses
+ // the latest interfaces version and corresponding methods for opening
+ // them. However, in minor package uprevs IPrimaryDevice does not inherit
+ // IDevice from the same package and thus IDevice can not be upcasted
+ // (see the interfaces in V7.1).
+ auto factory = DevicesFactoryManager::getInstance().get(getFactoryName());
+ ASSERT_TRUE(factory != nullptr);
+ sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> baseDevice;
+ Result result;
+ auto ret = factory->openDevice(DeviceManager::kPrimaryDevice, returnIn(result, baseDevice));
+ ASSERT_TRUE(ret.isOk()) << ret.description();
+ ASSERT_EQ(Result::OK, result);
+ ASSERT_TRUE(baseDevice != nullptr);
+ {
+ Return<sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>>
+ primaryDevice = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice::
+ castFrom(baseDevice);
EXPECT_TRUE(primaryDevice.isOk());
- EXPECT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+ EXPECT_TRUE(sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>(
+ primaryDevice) != nullptr);
}
- EXPECT_TRUE(
- DeviceManager::getInstance().reset(getFactoryName(), DeviceManager::kPrimaryDevice));
+#if MAJOR_VERSION < 6
+ baseDevice.clear();
+ DeviceManager::waitForInstanceDestruction();
+#else
+ auto closeRet = baseDevice->close();
+ EXPECT_TRUE(closeRet.isOk());
+#endif
}
//////////////////////////////////////////////////////////////////////////////
@@ -183,7 +202,7 @@
areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
: testSetDevices(stream.get(), address))
-static void checkGetHwAVSync(IDevice* device) {
+static void checkGetHwAVSync(::android::hardware::audio::CPP_VERSION::IDevice* device) {
Result res;
AudioHwSync sync;
ASSERT_OK(device->getHwAvSync(returnIn(res, sync)));
@@ -215,7 +234,7 @@
ASSERT_OK(stream->updateSinkMetadata(initMetadata));
#elif MAJOR_VERSION >= 7
- xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioSource> range;
+ xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioSource> range;
// Test all possible track configuration
for (auto source : range) {
for (float volume : {0.0, 0.5, 1.0}) {
@@ -272,8 +291,9 @@
// Restore initial
ASSERT_OK(stream->updateSourceMetadata(initMetadata));
#elif MAJOR_VERSION >= 7
- xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioUsage> usageRange;
- xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioContentType> contentRange;
+ xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioUsage> usageRange;
+ xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioContentType>
+ contentRange;
// Test all possible track configuration
for (auto usage : usageRange) {
for (auto content : contentRange) {
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 81a1f7b..83ca9eb 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
@@ -14,33 +14,36 @@
* limitations under the License.
*/
-#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
#include <hidl/HidlSupport.h>
using ::android::hardware::hidl_bitfield;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
-using ::android::hardware::audio::CPP_VERSION::IStream;
-using ::android::hardware::audio::CPP_VERSION::ParameterValue;
-using ::android::hardware::audio::CPP_VERSION::Result;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioFormat;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStream;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::ParameterValue;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
using namespace ::android::hardware::audio::common::test::utility;
-using Rotation = ::android::hardware::audio::CPP_VERSION::IPrimaryDevice::Rotation;
-using ::android::hardware::audio::common::CPP_VERSION::AudioContentType;
-using ::android::hardware::audio::common::CPP_VERSION::AudioUsage;
-using ::android::hardware::audio::CPP_VERSION::MicrophoneInfo;
+using Rotation = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice::Rotation;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioContentType;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioUsage;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::MicrophoneInfo;
#if MAJOR_VERSION < 5
using ::android::hardware::audio::CPP_VERSION::SinkMetadata;
using ::android::hardware::audio::CPP_VERSION::SourceMetadata;
#else
-using ::android::hardware::audio::common::CPP_VERSION::SinkMetadata;
-using ::android::hardware::audio::common::CPP_VERSION::SourceMetadata;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata;
#endif
struct Parameters {
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 8af4c78..aef94da 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -59,7 +59,8 @@
testAccessors<OPTIONAL>(&OutputStreamTest::getStream, "dual mono mode",
Initial{DualMonoMode::OFF},
{DualMonoMode::LR, DualMonoMode::LL, DualMonoMode::RR},
- &IStreamOut::setDualMonoMode, &IStreamOut::getDualMonoMode);
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::setDualMonoMode,
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::getDualMonoMode);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DualMonoModeAccessorHidlTest);
@@ -73,7 +74,8 @@
testAccessors<OPTIONAL>(
&OutputStreamTest::getStream, "audio description mix level",
Initial{-std::numeric_limits<float>::infinity()}, {-48.0f, -1.0f, 0.0f, 1.0f, 48.0f},
- &IStreamOut::setAudioDescriptionMixLevel, &IStreamOut::getAudioDescriptionMixLevel,
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::setAudioDescriptionMixLevel,
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::getAudioDescriptionMixLevel,
{48.5f, 1000.0f, std::numeric_limits<float>::infinity()});
}
@@ -105,7 +107,8 @@
PlaybackRate{0.5f, 0.5f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::FAIL}},
- &IStreamOut::setPlaybackRateParameters, &IStreamOut::getPlaybackRateParameters,
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::setPlaybackRateParameters,
+ &::android::hardware::audio::CPP_VERSION::IStreamOut::getPlaybackRateParameters,
{PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
TimestretchFallbackMode::FAIL},
PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE,
diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.cpp b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
index e3b98c9..dafd326 100644
--- a/audio/core/all-versions/vts/functional/6.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
@@ -21,8 +21,8 @@
#include "PolicyConfig.h"
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
// Forward declaration for functions that are substituted
@@ -30,7 +30,7 @@
const PolicyConfig& getCachedPolicyConfig();
const std::vector<DeviceParameter>& getDeviceParameters();
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 2759801..f25c391 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -53,9 +53,9 @@
TEST_P(AudioHidlDeviceTest, SetConnectedStateInvalidDeviceAddress) {
doc::test("Check that invalid device address is rejected by IDevice::setConnectedState");
- EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+ EXPECT_RESULT(invalidArgsOrNotSupported,
getDevice()->setConnectedState(getInvalidDeviceAddress(), true));
- EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+ EXPECT_RESULT(invalidArgsOrNotSupported,
getDevice()->setConnectedState(getInvalidDeviceAddress(), false));
}
@@ -381,13 +381,13 @@
"IDevice::open{Input|Output}Stream method.");
AudioConfig suggestedConfig{};
if (isParamForInputStream()) {
- sp<IStreamIn> stream;
+ sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> stream;
ASSERT_OK(getDevice()->openInputStream(AudioIoHandle{}, getDeviceAddress(), getConfig(),
getFlags(), getSinkMetadata(),
returnIn(res, stream, suggestedConfig)));
ASSERT_TRUE(stream == nullptr);
} else {
- sp<IStreamOut> stream;
+ sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamOut> stream;
ASSERT_OK(getDevice()->openOutputStream(AudioIoHandle{}, getDeviceAddress(), getConfig(),
getFlags(), getSourceMetadata(),
returnIn(res, stream, suggestedConfig)));
@@ -551,13 +551,15 @@
}
void releasePatchIfNeeded() {
- if (areAudioPatchesSupported()) {
- if (mHasPatch) {
+ if (getDevice()) {
+ if (areAudioPatchesSupported() && mHasPatch) {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
- EXPECT_OK(stream->setDevices({address}));
+ if (stream) {
+ EXPECT_OK(stream->setDevices({address}));
+ }
}
}
@@ -724,13 +726,15 @@
}
void releasePatchIfNeeded() {
- if (areAudioPatchesSupported()) {
- if (mHasPatch) {
+ if (getDevice()) {
+ if (areAudioPatchesSupported() && mHasPatch) {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
- EXPECT_OK(stream->setDevices({address}));
+ if (stream) {
+ EXPECT_OK(stream->setDevices({address}));
+ }
}
}
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index 42bf1d3..f936d0a 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -20,20 +20,20 @@
#include "7.0/PolicyConfig.h"
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
// Forward declaration for functions that are substituted
// in generator unit tests.
const PolicyConfig& getCachedPolicyConfig();
const std::vector<DeviceParameter>& getDeviceParameters();
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
namespace xsd {
using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
index 2988207..d674403 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
@@ -30,9 +30,9 @@
using ::android::NO_ERROR;
using ::android::OK;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::splitString;
namespace xsd {
using namespace ::android::audio::policy::configuration::CPP_VERSION;
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index f798839..4aea503 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -25,15 +25,15 @@
#include <utils/Errors.h>
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
namespace xsd {
using namespace ::android::audio::policy::configuration::CPP_VERSION;
using Module = Modules::Module;
diff --git a/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..d82d4ad
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// pull in all the <= 7.0 tests
+#include "7.0/AudioPrimaryHidlHalTest.cpp"
+
+TEST_P(AudioHidlDeviceTest, SetConnectedState_7_1) {
+ doc::test("Check that the HAL can be notified of device connection and disconnection");
+ using AD = xsd::AudioDevice;
+ for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
+ SCOPED_TRACE("device=" + toString(deviceType));
+ for (bool state : {true, false}) {
+ SCOPED_TRACE("state=" + ::testing::PrintToString(state));
+ DeviceAddress address = {};
+ address.deviceType = toString(deviceType);
+ if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
+ address.address.alsa({0, 0});
+ }
+ AudioPort devicePort;
+ devicePort.ext.device(address);
+ auto ret = getDevice()->setConnectedState_7_1(devicePort, state);
+ ASSERT_TRUE(ret.isOk());
+ if (ret == Result::NOT_SUPPORTED) {
+ doc::partialTest("setConnectedState_7_1 is not supported");
+ break; // other deviceType might be supported
+ }
+ ASSERT_OK(ret);
+ }
+ }
+
+ // Because there is no way of knowing if the devices were connected before
+ // calling setConnectedState, there is no way to restore the HAL to its
+ // initial state. To workaround this, destroy the HAL at the end of this test.
+ ASSERT_TRUE(resetDevice());
+}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index cfee26a..3007f01 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -48,6 +48,9 @@
cc_test {
name: "VtsHalAudioV2_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
+ tidy_timeout_srcs: [
+ "2.0/AudioPrimaryHidlHalTest.cpp",
+ ],
srcs: [
"2.0/AudioPrimaryHidlHalTest.cpp",
],
@@ -74,6 +77,9 @@
cc_test {
name: "VtsHalAudioV4_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
+ tidy_timeout_srcs: [
+ "4.0/AudioPrimaryHidlHalTest.cpp",
+ ],
srcs: [
"4.0/AudioPrimaryHidlHalTest.cpp",
],
@@ -126,6 +132,9 @@
cc_test {
name: "VtsHalAudioV6_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
+ tidy_timeout_srcs: [
+ "6.0/AudioPrimaryHidlHalTest.cpp",
+ ],
srcs: [
"6.0/AudioPrimaryHidlHalTest.cpp",
"6.0/Generators.cpp",
@@ -153,6 +162,9 @@
cc_test {
name: "VtsHalAudioV7_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
+ tidy_timeout_srcs: [
+ "7.0/AudioPrimaryHidlHalTest.cpp",
+ ],
srcs: [
"7.0/AudioPrimaryHidlHalTest.cpp",
"7.0/Generators.cpp",
@@ -179,6 +191,39 @@
test_config: "VtsHalAudioV7_0TargetTest.xml",
}
+cc_test {
+ name: "VtsHalAudioV7_1TargetTest",
+ defaults: ["VtsHalAudioTargetTest_defaults"],
+ srcs: [
+ "7.1/AudioPrimaryHidlHalTest.cpp",
+ "7.0/Generators.cpp",
+ "7.0/PolicyConfig.cpp",
+ ],
+ generated_headers: ["audio_policy_configuration_V7_1_parser"],
+ generated_sources: ["audio_policy_configuration_V7_1_parser"],
+ static_libs: [
+ "android.hardware.audio@7.0",
+ "android.hardware.audio@7.1",
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+ data: [
+ ":audio_policy_configuration_V7_1",
+ ],
+ // Use test_config for vts suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV7_1TargetTest.xml",
+}
+
// Note: the following aren't VTS tests, but rather unit tests
// to verify correctness of test utilities.
cc_test {
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 340903a..fa3ee7f 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -37,15 +37,17 @@
#include <android-base/logging.h>
#include <system/audio_config.h>
+// clang-format off
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
#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)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
#if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
#endif
+// clang-format on
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
@@ -86,11 +88,12 @@
using ::android::hardware::audio::common::utils::mkEnumBitfield;
using ::android::hardware::details::toHexString;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
-using ReadParameters = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadParameters;
-using ReadStatus = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadStatus;
+using ReadParameters =
+ ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadStatus;
using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
#if MAJOR_VERSION >= 7
@@ -124,6 +127,9 @@
class HidlTest : public ::testing::Test {
public:
+ using IDevice = ::android::hardware::audio::CPP_VERSION::IDevice;
+ using IDevicesFactory = ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
+
virtual ~HidlTest() = default;
// public access to avoid annoyances when using this method in template classes
// derived from test classes
@@ -168,7 +174,8 @@
}
TEST(CheckConfig, audioPolicyConfigurationValidation) {
- const auto factories = ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ const auto factories = ::android::hardware::getAllHalInstanceNames(
+ ::android::hardware::audio::CPP_VERSION::IDevicesFactory::descriptor);
if (factories.size() == 0) {
GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no factory instances "
"are found.";
@@ -198,8 +205,8 @@
const std::vector<DeviceParameter>& getDeviceParameters() {
static std::vector<DeviceParameter> parameters = [] {
std::vector<DeviceParameter> result;
- const auto factories =
- ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ const auto factories = ::android::hardware::getAllHalInstanceNames(
+ ::android::hardware::audio::CPP_VERSION::IDevicesFactory::descriptor);
const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
result.reserve(devices.size());
for (const auto& factoryName : factories) {
@@ -217,8 +224,8 @@
const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
static std::vector<DeviceParameter> parameters = [] {
std::vector<DeviceParameter> result;
- const auto factories =
- ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ const auto factories = ::android::hardware::getAllHalInstanceNames(
+ ::android::hardware::audio::CPP_VERSION::IDevicesFactory::descriptor);
for (const auto& factoryName : factories) {
result.emplace_back(factoryName,
DeviceManager::getInstance().getPrimary(factoryName) != nullptr
@@ -288,6 +295,8 @@
// Test audio devices factory
class AudioHidlTest : public AudioHidlTestWithDeviceParameter {
public:
+ using IPrimaryDevice = ::android::hardware::audio::CPP_VERSION::IPrimaryDevice;
+
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
ASSERT_TRUE(getDevicesFactory() != nullptr);
@@ -301,7 +310,7 @@
TEST_P(AudioHidlTest, OpenDeviceInvalidParameter) {
doc::test("Test passing an invalid parameter to openDevice");
Result result;
- sp<IDevice> device;
+ sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> device;
#if MAJOR_VERSION == 2
auto invalidDevice = IDevicesFactory::Device(-1);
#elif MAJOR_VERSION >= 4
@@ -572,8 +581,8 @@
[](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));
+ return ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::
+ toString<T>(hidl_bitfield<T>(arg));
},
std::get<PARAM_FLAGS>(info.param)));
#elif MAJOR_VERSION >= 7
@@ -890,6 +899,8 @@
class StreamWriter : public StreamWorker<StreamWriter> {
public:
+ using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
+
StreamWriter(IStreamOut* stream, size_t bufferSize)
: mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
~StreamWriter() {
@@ -998,7 +1009,8 @@
EventFlag* mEfGroup = nullptr;
};
-class OutputStreamTest : public OpenStreamTest<IStreamOut> {
+class OutputStreamTest
+ : public OpenStreamTest<::android::hardware::audio::CPP_VERSION::IStreamOut> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
@@ -1012,9 +1024,12 @@
[&](AudioIoHandle handle, AudioConfig config, auto cb) {
#if MAJOR_VERSION == 2
return getDevice()->openOutputStream(handle, address, config, flags, cb);
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
return getDevice()->openOutputStream(handle, address, config, flags,
initMetadata, cb);
+#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ return getDevice()->openOutputStream_7_1(handle, address, config, flags,
+ initMetadata, cb);
#endif
},
config);
@@ -1075,6 +1090,8 @@
class StreamReader : public StreamWorker<StreamReader> {
public:
+ using IStreamIn = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn;
+
StreamReader(IStreamIn* stream, size_t bufferSize)
: mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
~StreamReader() {
@@ -1188,7 +1205,8 @@
EventFlag* mEfGroup = nullptr;
};
-class InputStreamTest : public OpenStreamTest<IStreamIn> {
+class InputStreamTest
+ : public OpenStreamTest<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
@@ -1584,7 +1602,9 @@
"InputStream::setGain");
}
-static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForReading(
+ ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn* stream, uint32_t frameSize,
+ uint32_t framesCount) {
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
@@ -1655,7 +1675,8 @@
"setVolume");
}
-static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForWriting(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
+ uint32_t frameSize, uint32_t framesCount) {
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
@@ -1682,6 +1703,8 @@
}
struct Capability {
+ using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
+
Capability(IStreamOut* stream) {
EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
drain = extract(stream->supportsDrain());
@@ -1725,7 +1748,7 @@
Return<void> onError() override { return {}; }
};
-static bool isAsyncModeSupported(IStreamOut* stream) {
+static bool isAsyncModeSupported(::android::hardware::audio::CPP_VERSION::IStreamOut* stream) {
auto res = stream->setCallback(new MockOutCallbacks);
stream->clearCallback(); // try to restore the no callback state, ignore
// any error
@@ -1780,7 +1803,8 @@
ASSERT_RESULT(Result::INVALID_STATE, stream->pause());
}
-static void testDrain(IStreamOut* stream, AudioDrain type) {
+static void testDrain(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
+ AudioDrain type) {
if (!Capability(stream).drain) {
doc::partialTest("The output stream does not support drain");
return;
@@ -1866,7 +1890,8 @@
}
using TtyModeAccessorPrimaryHidlTest =
- AccessorHidlTest<IPrimaryDevice::TtyMode, AudioPrimaryHidlTest>;
+ AccessorHidlTest<::android::hardware::audio::CPP_VERSION::IPrimaryDevice::TtyMode,
+ AudioPrimaryHidlTest>;
TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
doc::test("Query and set the TTY mode state");
testAccessors<OPTIONAL>(
diff --git a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
index aa67630..802b87b 100644
--- a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
+++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
@@ -22,8 +22,8 @@
#include <vector>
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME };
@@ -34,14 +34,14 @@
#if MAJOR_VERSION <= 6
enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
enum { INDEX_INPUT, INDEX_OUTPUT };
-using DeviceConfigParameter =
- std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
- std::variant<android::hardware::audio::common::CPP_VERSION::AudioInputFlag,
- android::hardware::audio::common::CPP_VERSION::AudioOutputFlag>>;
+using DeviceConfigParameter = std::tuple<
+ DeviceParameter, android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
+ std::variant<android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioInputFlag,
+ android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
using DeviceConfigParameter =
std::tuple<DeviceParameter, std::string,
- android::hardware::audio::common::CPP_VERSION::AudioConfig,
- std::vector<android::hardware::audio::CPP_VERSION::AudioInOutFlag>>;
+ android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
+ std::vector<android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>>;
#endif
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index a2bb1ee..e4008cf 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -21,8 +21,8 @@
#include "PolicyConfig.h"
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
using ::android::hardware::audio::common::utils::EnumBitfield;
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index 6db78a7..6bb39ed 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -22,19 +22,21 @@
#include <android-base/logging.h>
#include <hwbinder/IPCThreadState.h>
+#include <system/audio.h>
// clang-format off
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
#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)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
#include "utility/ReturnIn.h"
using ::android::sp;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
@@ -94,29 +96,81 @@
}
};
-using FactoryAndDevice = std::tuple<std::string, std::string>;
-class DeviceManager : public InterfaceManager<DeviceManager, FactoryAndDevice, IDevice> {
+namespace impl {
+
+class PrimaryDeviceManager
+ : public InterfaceManager<PrimaryDeviceManager, std::string, IPrimaryDevice> {
public:
- static DeviceManager& getInstance() {
- static DeviceManager instance;
- return instance;
+ static sp<IPrimaryDevice> createInterfaceInstance(const std::string& factoryName) {
+ sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
+ return openPrimaryDevice(factory);
}
+
+ bool reset(const std::string& factoryName) __attribute__((warn_unused_result)) {
+#if MAJOR_VERSION <= 5
+ return InterfaceManager::reset(factoryName, true);
+#elif MAJOR_VERSION >= 6
+ {
+ sp<IPrimaryDevice> device = getExisting(factoryName);
+ if (device != nullptr) {
+ auto ret = device->close();
+ ALOGE_IF(!ret.isOk(), "PrimaryDevice %s close failed: %s", factoryName.c_str(),
+ ret.description().c_str());
+ }
+ }
+ return InterfaceManager::reset(factoryName, false);
+#endif
+ }
+
+ private:
+ static sp<IPrimaryDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
+ if (factory == nullptr) return {};
+ Result result;
+ sp<IPrimaryDevice> primaryDevice;
+#if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
+ sp<IDevice> device;
+#if MAJOR_VERSION == 2
+ auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
+ if (ret.isOk() && result == Result::OK && device != nullptr) {
+ primaryDevice = IPrimaryDevice::castFrom(device);
+ }
+#elif MAJOR_VERSION >= 4
+ auto ret = factory->openPrimaryDevice(returnIn(result, device));
+ if (ret.isOk() && result == Result::OK && device != nullptr) {
+ primaryDevice = IPrimaryDevice::castFrom(device);
+ }
+#endif
+ if (!ret.isOk() || result != Result::OK || primaryDevice == nullptr) {
+ ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
+ ret.description().c_str(), result, device.get());
+ return nullptr;
+ }
+#else // V7.1
+ auto ret = factory->openPrimaryDevice_7_1(returnIn(result, primaryDevice));
+ if (!ret.isOk() || result != Result::OK) {
+ ALOGW("Primary device can not be opened, transaction: %s, result %d",
+ ret.description().c_str(), result);
+ return nullptr;
+ }
+#endif
+ return primaryDevice;
+ }
+};
+
+using FactoryAndDevice = std::tuple<std::string, std::string>;
+class RegularDeviceManager
+ : public InterfaceManager<RegularDeviceManager, FactoryAndDevice, IDevice> {
+ public:
static sp<IDevice> createInterfaceInstance(const FactoryAndDevice& factoryAndDevice) {
auto [factoryName, name] = factoryAndDevice;
sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
- return name == kPrimaryDevice ? openPrimaryDevice(factory) : openDevice(factory, name);
+ return openDevice(factory, name);
}
- using InterfaceManager::reset;
-
- static constexpr const char* kPrimaryDevice = "primary";
sp<IDevice> get(const std::string& factoryName, const std::string& name) {
return InterfaceManager::get(std::make_tuple(factoryName, name));
}
- sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
- sp<IDevice> device = get(factoryName, kPrimaryDevice);
- return device != nullptr ? IPrimaryDevice::castFrom(device) : nullptr;
- }
+
bool reset(const std::string& factoryName, const std::string& name)
__attribute__((warn_unused_result)) {
#if MAJOR_VERSION <= 5
@@ -133,42 +187,92 @@
return InterfaceManager::reset(std::make_tuple(factoryName, name), false);
#endif
}
- bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
- return reset(factoryName, kPrimaryDevice);
- }
private:
static sp<IDevice> openDevice(const sp<IDevicesFactory>& factory, const std::string& name) {
if (factory == nullptr) return nullptr;
- sp<IDevice> device;
-#if MAJOR_VERSION >= 4
Result result;
+ sp<IDevice> device;
+#if MAJOR_VERSION == 2
+ IDevicesFactory::Device dev = IDevicesFactory::IDevicesFactory::Device(-1);
+ if (name == AUDIO_HARDWARE_MODULE_ID_A2DP) {
+ dev = IDevicesFactory::Device::A2DP;
+ } else if (name == AUDIO_HARDWARE_MODULE_ID_USB) {
+ dev = IDevicesFactory::Device::USB;
+ } else if (name == AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX) {
+ dev = IDevicesFactory::Device::R_SUBMIX;
+ } else if (name == AUDIO_HARDWARE_MODULE_ID_STUB) {
+ dev = IDevicesFactory::Device::STUB;
+ }
+ auto ret = factory->openDevice(dev, returnIn(result, device));
+#elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
auto ret = factory->openDevice(name, returnIn(result, device));
+#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ auto ret = factory->openDevice_7_1(name, returnIn(result, device));
+#endif
if (!ret.isOk() || result != Result::OK || device == nullptr) {
ALOGW("Device %s can not be opened, transaction: %s, result %d, device %p",
name.c_str(), ret.description().c_str(), result, device.get());
return nullptr;
}
-#else
- (void)name;
-#endif
return device;
}
+};
+
+} // namespace impl
+
+class DeviceManager {
+ public:
+ static DeviceManager& getInstance() {
+ static DeviceManager instance;
+ return instance;
+ }
- static sp<IDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
- if (factory == nullptr) return nullptr;
- Result result;
- sp<IDevice> device;
-#if MAJOR_VERSION == 2
- auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
-#elif MAJOR_VERSION >= 4
- auto ret = factory->openPrimaryDevice(returnIn(result, device));
-#endif
- if (!ret.isOk() || result != Result::OK || device == nullptr) {
- ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
- ret.description().c_str(), result, device.get());
+ static constexpr const char* kPrimaryDevice = "primary";
+
+ sp<IDevice> get(const std::string& factoryName, const std::string& name) {
+ if (name == kPrimaryDevice) {
+ auto primary = getPrimary(factoryName);
+ return primary ? deviceFromPrimary(primary) : nullptr;
+ }
+ return mDevices.get(factoryName, name);
+ }
+
+ sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
+ return mPrimary.get(factoryName);
+ }
+
+ bool reset(const std::string& factoryName, const std::string& name)
+ __attribute__((warn_unused_result)) {
+ return name == kPrimaryDevice ? resetPrimary(factoryName)
+ : mDevices.reset(factoryName, name);
+ }
+
+ bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
+ return mPrimary.reset(factoryName);
+ }
+
+ static void waitForInstanceDestruction() {
+ // Does not matter which device manager to use.
+ impl::RegularDeviceManager::waitForInstanceDestruction();
+ }
+
+ private:
+ sp<IDevice> deviceFromPrimary(const sp<IPrimaryDevice>& primary) {
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ auto ret = primary->getDevice();
+ if (ret.isOk()) {
+ return ret;
+ } else {
+ ALOGW("Error retrieving IDevice from primary: transaction: %s, primary %p",
+ ret.description().c_str(), primary.get());
return nullptr;
}
- return device;
+#else
+ return primary;
+#endif
}
+
+ impl::PrimaryDeviceManager mPrimary;
+ impl::RegularDeviceManager mDevices;
};
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
index f035baf..ae57125 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
@@ -34,5 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalAudioV6_0TargetTest" />
+ <option name="native-test-timeout" value="5m" />
</test>
</configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
index 6635f31..55dbaf1 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
@@ -34,5 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalAudioV7_0TargetTest" />
+ <option name="native-test-timeout" value="5m" />
</test>
</configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml
new file mode 100644
index 0000000..7b33a8f
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalAudioV7_1TargetTest.">
+ <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_1TargetTest->/data/local/tmp/VtsHalAudioV7_1TargetTest" />
+ <option name="push" value="audio_policy_configuration_V7_1.xsd->/data/local/tmp/audio_policy_configuration_V7_1.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_1TargetTest" />
+ <option name="native-test-timeout" value="5m" />
+ </test>
+</configuration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 3fdd8e6..76bf93e 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -33,7 +33,7 @@
#endif
using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
#if MAJOR_VERSION == 7
namespace xsd {
using namespace ::android::audio::policy::configuration::CPP_VERSION;
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index ccfc6b2..49f6bf2 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -42,9 +42,10 @@
namespace implementation {
#if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+ AudioChannelBitfield;
#endif
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
namespace {
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index d5218f7..f9a6796 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -48,9 +48,10 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
#if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioDeviceBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+ AudioDeviceBitfield;
#endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct Effect : public IEffect {
diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp
index eb1cb49..e93ad89 100644
--- a/audio/effect/all-versions/default/EffectsFactory.cpp
+++ b/audio/effect/all-versions/default/EffectsFactory.cpp
@@ -53,7 +53,7 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::UuidUtils;
// static
sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
diff --git a/audio/effect/all-versions/default/EffectsFactory.h b/audio/effect/all-versions/default/EffectsFactory.h
index 0b86836..da16923 100644
--- a/audio/effect/all-versions/default/EffectsFactory.h
+++ b/audio/effect/all-versions/default/EffectsFactory.h
@@ -41,7 +41,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct EffectsFactory : public IEffectsFactory {
diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
index 9694b5d..001774d 100644
--- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
+++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
@@ -43,7 +43,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect {
diff --git a/audio/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/EqualizerEffect.h
index 7a6bc0a..c4d76c1 100644
--- a/audio/effect/all-versions/default/EqualizerEffect.h
+++ b/audio/effect/all-versions/default/EqualizerEffect.h
@@ -43,7 +43,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct EqualizerEffect : public IEqualizerEffect {
diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
index 6d80207..122ec36 100644
--- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
+++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
@@ -39,7 +39,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
index 6cc45b9..96b9ecf 100644
--- a/audio/effect/all-versions/default/NoiseSuppressionEffect.h
+++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
@@ -41,7 +41,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct NoiseSuppressionEffect : public INoiseSuppressionEffect {
diff --git a/audio/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/PresetReverbEffect.h
index eb55e20..9d82c08 100644
--- a/audio/effect/all-versions/default/PresetReverbEffect.h
+++ b/audio/effect/all-versions/default/PresetReverbEffect.h
@@ -39,7 +39,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct PresetReverbEffect : public IPresetReverbEffect {
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.cpp b/audio/effect/all-versions/default/VirtualizerEffect.cpp
index 1dce181..6efc4ea 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.cpp
+++ b/audio/effect/all-versions/default/VirtualizerEffect.cpp
@@ -34,7 +34,7 @@
namespace CPP_VERSION {
namespace implementation {
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
VirtualizerEffect::VirtualizerEffect(effect_handle_t handle)
: mEffect(new Effect(false /*isInput*/, handle)) {}
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/VirtualizerEffect.h
index 3ed06d1..f26e4fa 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.h
+++ b/audio/effect/all-versions/default/VirtualizerEffect.h
@@ -40,9 +40,10 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
#if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+ AudioChannelBitfield;
#endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct VirtualizerEffect : public IVirtualizerEffect {
diff --git a/audio/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/VisualizerEffect.h
index 3ae4b08..b8424c4 100644
--- a/audio/effect/all-versions/default/VisualizerEffect.h
+++ b/audio/effect/all-versions/default/VisualizerEffect.h
@@ -39,7 +39,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
struct VisualizerEffect : public IVisualizerEffect {
diff --git a/audio/effect/all-versions/default/util/EffectUtils.cpp b/audio/effect/all-versions/default/util/EffectUtils.cpp
index 1156d21..296f84d 100644
--- a/audio/effect/all-versions/default/util/EffectUtils.cpp
+++ b/audio/effect/all-versions/default/util/EffectUtils.cpp
@@ -25,8 +25,8 @@
#include "util/EffectUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::UuidUtils;
using ::android::hardware::audio::common::utils::EnumBitfield;
namespace android {
@@ -36,7 +36,7 @@
namespace CPP_VERSION {
namespace implementation {
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
#define CONVERT_CHECKED(expr, result) \
if (status_t status = (expr); status != NO_ERROR) { \
diff --git a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
index d021fa0..adfa167 100644
--- a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
+++ b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
@@ -27,7 +27,7 @@
#include <xsdc/XsdcSupport.h>
using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
namespace xsd {
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 48d6474..3b15ed4 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -26,6 +26,9 @@
cc_defaults {
name: "VtsHalAudioEffectTargetTest_default",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "VtsHalAudioEffectTargetTest.cpp",
+ ],
srcs: [
"VtsHalAudioEffectTargetTest.cpp",
"ValidateAudioEffectsConfiguration.cpp",
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 23e7786..e59423f 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -50,7 +50,7 @@
using ::android::hardware::audio::common::utils::mkEnumBitfield;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_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.
diff --git a/authsecret/aidl/default/service.cpp b/authsecret/aidl/default/service.cpp
index efecf10..a7d8678 100644
--- a/authsecret/aidl/default/service.cpp
+++ b/authsecret/aidl/default/service.cpp
@@ -28,7 +28,7 @@
const std::string instance = std::string() + AuthSecret::descriptor + "/default";
binder_status_t status = AServiceManager_addService(authsecret->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return -1; // Should never be reached
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index 4acfd82..623097c 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -13,11 +13,17 @@
name: "android.hardware.automotive.audiocontrol",
vendor_available: true,
srcs: ["android/hardware/automotive/audiocontrol/*.aidl"],
+ imports: [
+ "android.media.audio.common.types",
+ "android.hardware.audio.common",
+ ],
stability: "vintf",
backend: {
java: {
- sdk_version: "module_current",
+ platform_apis: true,
},
},
- versions: ["1"],
+ versions: [
+ "1",
+ ],
}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
index 3dc393a..58a3667 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
@@ -1,14 +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.
+ */
///////////////////////////////////////////////////////////////////////////////
// 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.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
new file mode 100644
index 0000000..fb6ac65
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.audiocontrol;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioGainConfigInfo {
+ int zoneId;
+ String devicePortAddress;
+ int volumeIndex;
+}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
index 6d729e2..23abb46 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -1,14 +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.
+ */
///////////////////////////////////////////////////////////////////////////////
// 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.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
@@ -22,4 +38,5 @@
String[] deviceAddressesToDuck;
String[] deviceAddressesToUnduck;
String[] usagesHoldingFocus;
+ @nullable android.hardware.audio.common.PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index bc4162b..8dc5ffe 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -1,14 +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.
+ */
///////////////////////////////////////////////////////////////////////////////
// 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.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
@@ -18,10 +34,16 @@
package android.hardware.automotive.audiocontrol;
@VintfStability
interface IAudioControl {
+ /**
+ * @deprecated use {@link android.hardware.audio.common.PlaybackTrackMetadata} instead.
+ */
oneway void onAudioFocusChange(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange);
oneway void onDevicesToDuckChange(in android.hardware.automotive.audiocontrol.DuckingInfo[] duckingInfos);
oneway void onDevicesToMuteChange(in android.hardware.automotive.audiocontrol.MutingInfo[] mutingInfos);
oneway void registerFocusListener(in android.hardware.automotive.audiocontrol.IFocusListener listener);
oneway void setBalanceTowardRight(in float value);
oneway void setFadeTowardFront(in float value);
+ oneway void onAudioFocusChangeWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange);
+ oneway void setAudioDeviceGainsChanged(in android.hardware.automotive.audiocontrol.Reasons[] reasons, in android.hardware.automotive.audiocontrol.AudioGainConfigInfo[] gains);
+ oneway void registerGainCallback(in android.hardware.automotive.audiocontrol.IAudioGainCallback callback);
}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
new file mode 100644
index 0000000..17a087f
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.audiocontrol;
+@VintfStability
+interface IAudioGainCallback {
+ oneway void onAudioDeviceGainsChanged(in android.hardware.automotive.audiocontrol.Reasons[] reasons, in android.hardware.automotive.audiocontrol.AudioGainConfigInfo[] gains);
+}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
index f00f042..3e17552 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
@@ -1,14 +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.
+ */
///////////////////////////////////////////////////////////////////////////////
// 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.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
@@ -20,4 +36,6 @@
interface IFocusListener {
oneway void abandonAudioFocus(in String usage, in int zoneId);
oneway void requestAudioFocus(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain);
+ oneway void abandonAudioFocusWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId);
+ oneway void requestAudioFocusWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain);
}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
index ab902ec..b25ed0f 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
@@ -1,14 +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.
+ */
///////////////////////////////////////////////////////////////////////////////
// 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.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl
new file mode 100644
index 0000000..c1e22d4
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.audiocontrol;
+@Backing(type="int") @VintfStability
+enum Reasons {
+ FORCED_MASTER_MUTE = 1,
+ REMOTE_MUTE = 2,
+ TCU_MUTE = 4,
+ ADAS_DUCKING = 8,
+ NAV_DUCKING = 16,
+ PROJECTION_DUCKING = 32,
+ THERMAL_LIMITATION = 64,
+ SUSPEND_EXIT_VOL_LIMITATION = 128,
+ EXTERNAL_AMP_VOL_FEEDBACK = 256,
+ OTHER = -2147483648,
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
new file mode 100644
index 0000000..c938296
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.audiocontrol;
+
+/**
+ * NOTE:
+ * Was expecting to reuse android.media.audio types... Limit info to minimum to prevent
+ * duplicating aidl_api. Will follow up if AudioGainConfig is exposed by android.media AIDL API.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioGainConfigInfo {
+ /**
+ * The identifier for the audio zone the audio device port associated to this gain belongs to.
+ *
+ */
+ int zoneId;
+
+ /**
+ * The Audio Output Device Port Address.
+ *
+ * This is the address that can be retrieved at JAVA layer using the introspection
+ * {@link android.media.AudioManager#listAudioDevicePorts} API then
+ * {@link audio.media.AudioDeviceInfo#getAddress} API.
+ *
+ * At HAL layer, it corresponds to audio_port_v7.audio_port_device_ext.address.
+ *
+ * Devices that does not have an address will indicate an empty string "".
+ */
+ String devicePortAddress;
+
+ /**
+ * UI Index of the corresponding AudioGain in AudioPort.gains.
+ */
+ int volumeIndex;
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
index e95fe9b..c30d5f6 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -14,7 +14,9 @@
* limitations under the License.
*/
- package android.hardware.automotive.audiocontrol;
+package android.hardware.automotive.audiocontrol;
+
+import android.hardware.audio.common.PlaybackTrackMetadata;
/**
* The current ducking information for a single audio zone.
@@ -48,7 +50,15 @@
/**
* List of usages currently holding focus for this audio zone.
*
+ * This field was deprecated in version 2.
+ * Use playbackMetaDataHoldingFocus instead.
+ *
* <p> See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
*/
String[] usagesHoldingFocus;
- }
\ No newline at end of file
+
+ /**
+ * List of output stream metadata associated with the current focus holder for this audio zone
+ */
+ @nullable PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index 3a02245..100f1ba 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -20,6 +20,40 @@
import android.hardware.automotive.audiocontrol.DuckingInfo;
import android.hardware.automotive.audiocontrol.MutingInfo;
import android.hardware.automotive.audiocontrol.IFocusListener;
+import android.hardware.automotive.audiocontrol.IAudioGainCallback;
+import android.hardware.automotive.audiocontrol.AudioGainConfigInfo;
+import android.hardware.automotive.audiocontrol.Reasons;
+
+/**
+ * Important note on Metadata:
+ * Metadata qualifies a playback track for an output stream.
+ * This is highly closed to {@link android.media.AudioAttributes}.
+ * It allows to identify the audio stream rendered / requesting / abandonning the focus.
+ *
+ * AudioControl 1.0 was limited to identification through {@code AttributeUsage} listed as
+ * {@code audioUsage} in audio_policy_configuration.xsd.
+ *
+ * Any new OEM needs would not be possible without extension.
+ *
+ * Relying on {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata} allows
+ * to use a combination of {@code AttributeUsage}, {@code AttributeContentType} and
+ * {@code AttributeTags} to identify the use case / routing thanks to
+ * {@link android.media.audiopolicy.AudioProductStrategy}.
+ * The belonging to a strategy is deduced by an AOSP logic (in sync at native and java layer).
+ *
+ * IMPORTANT NOTE ON TAGS:
+ * To limit the possibilies and prevent from confusion, we expect the String to follow
+ * a given formalism that will be enforced.
+ *
+ * 1 / By convention, tags shall be a "key=value" pair.
+ * Vendor must namespace their tag's key (for example com.google.strategy=VR) to avoid conflicts.
+ * vendor specific applications and must be prefixed by "VX_". Vendor must
+ *
+ * 2 / Tags reported here shall be the same as the tags used to define a given
+ * {@link android.media.audiopolicy.AudioProductStrategy} and so in
+ * audio_policy_engine_configuration.xml file.
+ */
+import android.hardware.audio.common.PlaybackTrackMetadata;
/**
* Interacts with the car's audio subsystem to manage audio sources and volumes
@@ -36,8 +70,12 @@
* The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
* is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
*
+ * This method was deprecated in version 2 to allow getting rid of usages limitation.
+ * Use {@link IAudioControl#onAudioFocusChangeWithMetaData} instead.
+ *
* @param usage The audio usage associated with the focus change {@code AttributeUsage}. See
* {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
+ * @deprecated use {@link android.hardware.audio.common.PlaybackTrackMetadata} instead.
* @param zoneId The identifier for the audio zone that the HAL is playing the stream in
* @param focusChange the AudioFocusChange that has occurred.
*/
@@ -99,4 +137,51 @@
* range.
*/
oneway void setFadeTowardFront(in float value);
-}
\ No newline at end of file
+
+ /**
+ * Notifies HAL of changes in audio focus status for focuses requested or abandoned by the HAL.
+ *
+ * This will be called in response to IFocusListener's requestAudioFocus and
+ * abandonAudioFocus, as well as part of any change in focus being held by the HAL due focus
+ * request from other activities or services.
+ *
+ * The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
+ * is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
+ *
+ * @param playbackMetaData The output stream metadata associated with the focus request
+ * @param zoneId The identifier for the audio zone that the HAL is playing the stream in
+ * @param focusChange the AudioFocusChange that has occurred.
+ */
+ oneway void onAudioFocusChangeWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+ in int zoneId, in AudioFocusChange focusChange);
+
+ /**
+ * Notifies HAL of changes in output devices that the HAL should apply gain change to
+ * and the reason(s) why
+ *
+ * This may be called in response to changes in audio focus, and will include a list of
+ * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} objects per audio zone
+ * that experienced a change in audo focus.
+ *
+ * @param reasons List of reasons that triggered the given gains changed.
+ * This must be one or more of the
+ * {@link android.hardware.automotive.audiocontrol.Reasons} constants.
+ *
+ * @param gains List of gains the change is intended to.
+ */
+ oneway void setAudioDeviceGainsChanged(in Reasons[] reasons, in AudioGainConfigInfo[] gains);
+
+ /**
+ * Registers callback to be used by HAL for reporting unexpected gain(s) changed and the
+ * reason(s) why.
+ *
+ * It is expected that there will only ever be a single callback registered. If the
+ * observer dies, the HAL implementation must unregister observer automatically. If called when
+ * a listener is already registered, the existing one should be unregistered and replaced with
+ * the new callback.
+ *
+ * @param callback The {@link android.hardware.automotive.audiocontrol.IAudioGainCallback}
+ * interface.
+ */
+ oneway void registerGainCallback(in IAudioGainCallback callback);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
new file mode 100644
index 0000000..17b4341
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.audiocontrol;
+
+import android.hardware.automotive.audiocontrol.AudioGainConfigInfo;
+import android.hardware.automotive.audiocontrol.Reasons;
+
+/**
+ * Interface definition for a callback to be invoked when the gain(s) of the device port(s) is(are)
+ * updated at HAL layer.
+ *
+ * <p>This defines counter part API of
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#onDevicesToDuckChange},
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#onDevicesToMuteChange} and
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#setAudioDeviceGainsChanged} APIs.
+ *
+ * The previous API defines Mute/Duck order decided by the client (e.g. CarAudioService)
+ * and delegated to AudioControl for application.
+ *
+ * This callback interface defines Mute/Duck notification decided by AudioControl HAL (due to
+ * e.g. - external conditions from Android IVI subsystem
+ * - regulation / need faster decision rather than using
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#onAudioFocusChange} to
+ * report the use case and then waiting for CarAudioService decision to Mute/Duck.
+ */
+@VintfStability
+oneway interface IAudioGainCallback {
+ /**
+ * Used to indicated the one or more audio device port gains have changed unexpectidely, i.e.
+ * initiated by HAL, not by CarAudioService.
+ * This is the counter part of the
+ * {@link android.hardware.automotive.audiocontrol.onDevicesToDuckChange},
+ * {@link android.hardware.automotive.audiocontrol.onDevicesToMuteChange} and
+ * {@link android.hardware.automotive.audiocontrol.setAudioDeviceGainsChanged} APIs.
+ *
+ * Flexibility is given to OEM to mute/duck in HAL or in CarAudioService.
+ * For critical use cases (i.e. when regulation is required), better to handle mute/duck in
+ * HAL layer and informs upper layer.
+ * Non critical use case may report gain and focus and CarAudioService to decide of duck/mute.
+ *
+ * @param reasons List of reasons that triggered the given gains changed.
+ * This must be one or more of the
+ * {@link android.hardware.automotive.audiocontrol.Reasons} constants.
+ * It will define if the port has been muted/ducked or must now affected
+ * by gain limitation that shall be notified/enforced at CarAudioService
+ * layer.
+ *
+ * @param gains List of gains affected by the change.
+ */
+ void onAudioDeviceGainsChanged(in Reasons[] reasons, in AudioGainConfigInfo[] gains);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
index b79295a..1ce1f40 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
@@ -18,10 +18,13 @@
import android.hardware.automotive.audiocontrol.AudioFocusChange;
+import android.hardware.audio.common.PlaybackTrackMetadata;
+
/**
* Callback interface for audio focus listener.
*
* For typical configuration, the listener the car audio service.
+ *
*/
@VintfStability
interface IFocusListener {
@@ -33,6 +36,9 @@
* interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
* before stopping audio playback.
*
+ * Deprecated in version 2 to allow generic interface callback listener.
+ * Use {@link IFocusListener#abandonHalAudioFocusWithMetaData} instead.
+ *
* @param usage The audio usage for which the HAL is abandoning focus {@code AttributeUsage}.
* See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
* @param zoneId The identifier for the audio zone that the HAL abandoning focus
@@ -47,6 +53,9 @@
* interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
* before playing audio.
*
+ * Deprecated in version 2 to allow generic interface callback listener.
+ * Use {@link IFocusListener#requestAudioFocusWithMetaData} instead.
+ *
* @param usage The audio usage associated with the focus request {@code AttributeUsage}. See
* {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
* @param zoneId The identifier for the audio zone where the HAL is requesting focus
@@ -54,4 +63,29 @@
* following: GAIN, GAIN_TRANSIENT, GAIN_TRANSIENT_MAY_DUCK, GAIN_TRANSIENT_EXCLUSIVE.
*/
oneway void requestAudioFocus(in String usage, in int zoneId, in AudioFocusChange focusGain);
-}
\ No newline at end of file
+
+ /**
+ * Used to indicate that the audio output stream associated with
+ * {@link android.hardware.audio.common.PlaybackTrackMetadata} has released
+ * the focus.
+ *
+ * @param playbackMetaData The output stream metadata associated with the focus request
+ * @param zoneId The identifier for the audio zone that the HAL abandoning focus
+ */
+ oneway void abandonAudioFocusWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+ in int zoneId);
+
+ /**
+ * Used to indicate that the audio output stream associated with
+ * {@link android.hardware.audio.common.PlaybackTrackMetadata} has taken the focus.
+ *
+ * @param playbackMetaData The output stream metadata associated with the focus request
+ * @param zoneId The identifier for the audio zone that the HAL abandoning focus
+ * @param focusGain The focus type requested.
+ * This must be one of the
+ * {@link android.hardware.automotive.audiocontrol.AudioFocusChange}
+ * constants.
+ */
+ oneway void requestAudioFocusWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+ in int zoneId, in AudioFocusChange focusGain);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl
new file mode 100644
index 0000000..3d9e8a2
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.audiocontrol;
+
+/**
+ * Enum to identify the reason(s) of
+ * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} changed event
+ */
+@Backing(type="int")
+@VintfStability
+enum Reasons {
+ /**
+ * Magic Key Code (may be SWRC button combination) to force muting all audio sources.
+ * This may be used for example in case of cyber attach to ensure driver can safely drive back
+ * to garage to restore sw.
+ */
+ FORCED_MASTER_MUTE = 0x1,
+ /**
+ * Reports a mute request outside the IVI (Android) system.
+ * It may target to mute the list of
+ * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo}.
+ * A focus request may also be reported in addition if the use case that initiates the mute
+ * has matching {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata}
+ * For regulation issue, the action of mute could be managed by HAL itself.
+ */
+ REMOTE_MUTE = 0x2,
+ /**
+ * Reports a mute initiated by the TCU. It may be applied to all audio source (no
+ * associated {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} reported, or
+ * it may target to mute only the given list of ports.
+ * A focus request may also be reported in addition.
+ * For regulation issue, the action of mute could be managed by HAL itself.
+ */
+ TCU_MUTE = 0x4,
+ /**
+ * Reports a duck due to ADAS use case. A focus request may also be reported in addition.
+ * For regulation issue, the action of duck could be managed by HAL itself.
+ * It gives a chance to CarAudioService to decide whether contextual volume change may be
+ * applied from the ducked index base or not.
+ */
+ ADAS_DUCKING = 0x8,
+ /**
+ * Reports a duck due to navigation use case. It gives a chance to CarAudioService to decide
+ * whether contextual volume change may be applied from the ducked index base or not.
+ */
+ NAV_DUCKING = 0x10,
+ /**
+ * Some device projection stack may send signal to IVI to duck / unduck main audio stream.
+ * In this case, Contextual Volume Policy may be adapted to control the alternate / secondary
+ * audio stream.
+ */
+ PROJECTION_DUCKING = 0x20,
+ /**
+ * When the amplifier is overheating, it may be recovered by limiting the volume.
+ */
+ THERMAL_LIMITATION = 0x40,
+ /**
+ * Before the system enters suspend, it may ensure while exiting suspend or during cold boot
+ * that the volume is limited to prevent from sound explosion.
+ */
+ SUSPEND_EXIT_VOL_LIMITATION = 0x80,
+ /**
+ * When using an external amplifier, it may be required to keep volume in sync and have
+ * asynchronous notification of effective volume change.
+ */
+ EXTERNAL_AMP_VOL_FEEDBACK = 0x100,
+ /**
+ * For other OEM use.
+ */
+ OTHER = 0x80000000,
+}
diff --git a/automotive/audiocontrol/aidl/default/main.cpp b/automotive/audiocontrol/aidl/default/main.cpp
index 9b259fc..cc15ccb 100644
--- a/automotive/audiocontrol/aidl/default/main.cpp
+++ b/automotive/audiocontrol/aidl/default/main.cpp
@@ -31,7 +31,7 @@
const std::string instance = std::string() + AudioControl::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(audioControl->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
std::shared_ptr<PowerPolicyClient> powerPolicyClient =
::ndk::SharedRefBase::make<PowerPolicyClient>(audioControl);
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..05691d9 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -46,13 +46,7 @@
vendor: true,
relative_install_path: "hw",
srcs: [
- "CanBus.cpp",
- "CanBusNative.cpp",
- "CanBusVirtual.cpp",
- "CanBusSlcan.cpp",
- "CanController.cpp",
- "CanSocket.cpp",
- "CloseHandle.cpp",
+ ":automotiveCanV1.0_sources",
"service.cpp",
],
shared_libs: [
@@ -64,4 +58,24 @@
"android.hardware.automotive@libc++fs",
"libnl++",
],
+ vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
+}
+
+filegroup {
+ name: "automotiveCanV1.0_sources",
+ srcs: [
+ "CanBus.cpp",
+ "CanBusNative.cpp",
+ "CanBusVirtual.cpp",
+ "CanBusSlcan.cpp",
+ "CanController.cpp",
+ "CanSocket.cpp",
+ "CloseHandle.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "automotiveCanV1.0_headers",
+ vendor: true,
+ export_include_dirs: ["."],
}
diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
new file mode 100644
index 0000000..2078ce5
--- /dev/null
+++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<manifest version="1.0" type="device" >
+ <hal format="hidl">
+ <name>android.hardware.automotive.can</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.0::ICanController/socketcan</fqname>
+ </hal>
+</manifest>
diff --git a/automotive/can/1.0/default/tests/fuzzer/Android.bp b/automotive/can/1.0/default/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..52b43b0
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_fuzz {
+ name: "automotiveCanV1.0_fuzzer",
+ vendor: true,
+ defaults: ["android.hardware.automotive.can@defaults"],
+ srcs: [
+ "AutomotiveCanV1_0Fuzzer.cpp",
+ ":automotiveCanV1.0_sources",
+ ],
+ header_libs: [
+ "automotiveCanV1.0_headers",
+ "android.hardware.automotive.can@hidl-utils-lib",
+ ],
+ shared_libs: [
+ "android.hardware.automotive.can@1.0",
+ "libhidlbase",
+ ],
+ static_libs: [
+ "android.hardware.automotive.can@libnetdevice",
+ "android.hardware.automotive@libc++fs",
+ "libnl++",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 533764,
+ },
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
new file mode 100644
index 0000000..96110db
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "AutomotiveCanV1_0Fuzzer.h"
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+constexpr CanController::InterfaceType kInterfaceType[] = {CanController::InterfaceType::VIRTUAL,
+ CanController::InterfaceType::SOCKETCAN,
+ CanController::InterfaceType::SLCAN};
+constexpr FilterFlag kFilterFlag[] = {FilterFlag::DONT_CARE, FilterFlag::SET, FilterFlag::NOT_SET};
+constexpr size_t kInterfaceTypeLength = std::size(kInterfaceType);
+constexpr size_t kFilterFlagLength = std::size(kFilterFlag);
+constexpr size_t kMaxCharacters = 30;
+constexpr size_t kMaxPayloadBytes = 64;
+constexpr size_t kMaxFilters = 20;
+constexpr size_t kMaxSerialNumber = 1000;
+constexpr size_t kMaxBuses = 10;
+constexpr size_t kMaxRepeat = 5;
+
+Bus CanFuzzer::makeBus() {
+ ICanController::BusConfig config = {};
+ if (mBusNames.size() > 0 && mLastInterface < mBusNames.size()) {
+ config.name = mBusNames[mLastInterface++];
+ } else {
+ config.name = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+ config.interfaceId.virtualif({mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters)});
+ return Bus(mCanController, config);
+}
+
+void CanFuzzer::getSupportedInterfaceTypes() {
+ hidl_vec<CanController::InterfaceType> iftypesResult;
+ mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult));
+}
+
+hidl_vec<hidl_string> CanFuzzer::getBusNames() {
+ hidl_vec<hidl_string> services = {};
+ if (auto manager = hidl::manager::V1_2::IServiceManager::getService(); manager) {
+ manager->listManifestByInterface(ICanBus::descriptor, hidl_utils::fill(&services));
+ }
+ return services;
+}
+
+void CanFuzzer::invokeUpInterface() {
+ const CanController::InterfaceType iftype =
+ kInterfaceType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kInterfaceTypeLength - 1)];
+ std::string configName;
+
+ if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+ (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+ const size_t busNameIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+ configName = mBusNames[busNameIndex];
+ } else {
+ configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+ const std::string ifname = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+
+ ICanController::BusConfig config = {.name = configName};
+
+ if (iftype == CanController::InterfaceType::SOCKETCAN) {
+ CanController::BusConfig::InterfaceId::Socketcan socketcan = {};
+ if (const bool shouldPassSerialSocket = mFuzzedDataProvider->ConsumeBool();
+ shouldPassSerialSocket) {
+ socketcan.serialno(
+ {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+ } else {
+ socketcan.ifname(ifname);
+ }
+ config.interfaceId.socketcan(socketcan);
+ } else if (iftype == CanController::InterfaceType::SLCAN) {
+ CanController::BusConfig::InterfaceId::Slcan slcan = {};
+ if (const bool shouldPassSerialSlcan = mFuzzedDataProvider->ConsumeBool();
+ shouldPassSerialSlcan) {
+ slcan.serialno(
+ {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+ } else {
+ slcan.ttyname(ifname);
+ }
+ config.interfaceId.slcan(slcan);
+ } else if (iftype == CanController::InterfaceType::VIRTUAL) {
+ config.interfaceId.virtualif({ifname});
+ }
+
+ const size_t numInvocations =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+ for (size_t i = 0; i < numInvocations; ++i) {
+ mCanController->upInterface(config);
+ }
+}
+
+void CanFuzzer::invokeDownInterface() {
+ hidl_string configName;
+ if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+ (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+ const size_t busNameIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+ configName = mBusNames[busNameIndex];
+ } else {
+ configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+
+ const size_t numInvocations =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+ for (size_t i = 0; i < numInvocations; ++i) {
+ mCanController->downInterface(configName);
+ }
+}
+
+void CanFuzzer::invokeController() {
+ getSupportedInterfaceTypes();
+ invokeUpInterface();
+ invokeDownInterface();
+}
+
+void CanFuzzer::invokeBus() {
+ const size_t numBuses = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxBuses);
+ for (size_t i = 0; i < numBuses; ++i) {
+ if (const bool shouldSendMessage = mFuzzedDataProvider->ConsumeBool(); shouldSendMessage) {
+ auto sendingBus = makeBus();
+ CanMessage msg = {.id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>()};
+ uint32_t numPayloadBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxPayloadBytes);
+ hidl_vec<uint8_t> payload(numPayloadBytes);
+ for (uint32_t j = 0; j < numPayloadBytes; ++j) {
+ payload[j] = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ }
+ msg.payload = payload;
+ msg.remoteTransmissionRequest = mFuzzedDataProvider->ConsumeBool();
+ msg.isExtendedId = mFuzzedDataProvider->ConsumeBool();
+ sendingBus.send(msg);
+ } else {
+ auto listeningBus = makeBus();
+ uint32_t numFilters =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxFilters);
+ hidl_vec<CanMessageFilter> filterVector(numFilters);
+ for (uint32_t k = 0; k < numFilters; ++k) {
+ filterVector[k].id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ filterVector[k].mask = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ filterVector[k].rtr =
+ kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kFilterFlagLength - 1)];
+ filterVector[k].extendedFormat =
+ kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kFilterFlagLength - 1)];
+ filterVector[k].exclude = mFuzzedDataProvider->ConsumeBool();
+ }
+ auto listener = listeningBus.listen(filterVector);
+ }
+ }
+}
+
+void CanFuzzer::deInit() {
+ mCanController.clear();
+ if (mFuzzedDataProvider) {
+ delete mFuzzedDataProvider;
+ }
+ mBusNames = {};
+}
+
+void CanFuzzer::process(const uint8_t* data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ invokeController();
+ invokeBus();
+}
+
+bool CanFuzzer::init() {
+ mCanController = sp<CanController>::make();
+ if (!mCanController) {
+ return false;
+ }
+ mBusNames = getBusNames();
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ CanFuzzer canFuzzer;
+ if (canFuzzer.init()) {
+ canFuzzer.process(data, size);
+ }
+ return 0;
+}
+
+} // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
new file mode 100644
index 0000000..930cddd
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#define __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#include <CanController.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl-utils/hidl-utils.h>
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+using ::android::sp;
+
+struct CanMessageListener : public can::V1_0::ICanMessageListener {
+ DISALLOW_COPY_AND_ASSIGN(CanMessageListener);
+
+ CanMessageListener() {}
+
+ virtual Return<void> onReceive(const can::V1_0::CanMessage& msg) override {
+ std::unique_lock<std::mutex> lock(mMessagesGuard);
+ mMessages.push_back(msg);
+ mMessagesUpdated.notify_one();
+ return {};
+ }
+
+ virtual ~CanMessageListener() {
+ if (mCloseHandle) {
+ mCloseHandle->close();
+ }
+ }
+
+ void assignCloseHandle(sp<ICloseHandle> closeHandle) { mCloseHandle = closeHandle; }
+
+ private:
+ sp<ICloseHandle> mCloseHandle;
+
+ std::mutex mMessagesGuard;
+ std::condition_variable mMessagesUpdated GUARDED_BY(mMessagesGuard);
+ std::vector<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+};
+
+struct Bus {
+ DISALLOW_COPY_AND_ASSIGN(Bus);
+
+ Bus(sp<ICanController> controller, const ICanController::BusConfig& config)
+ : mIfname(config.name), mController(controller) {
+ const auto result = controller->upInterface(config);
+ const auto manager = hidl::manager::V1_2::IServiceManager::getService();
+ const auto service = manager->get(ICanBus::descriptor, config.name);
+ mBus = ICanBus::castFrom(service);
+ }
+
+ virtual ~Bus() { reset(); }
+
+ void reset() {
+ mBus.clear();
+ if (mController) {
+ mController->downInterface(mIfname);
+ mController.clear();
+ }
+ }
+
+ ICanBus* operator->() const { return mBus.get(); }
+ sp<ICanBus> get() { return mBus; }
+
+ sp<CanMessageListener> listen(const hidl_vec<CanMessageFilter>& filter) {
+ sp<CanMessageListener> listener = sp<CanMessageListener>::make();
+
+ if (!mBus) {
+ return listener;
+ }
+ Result result;
+ sp<ICloseHandle> closeHandle;
+ mBus->listen(filter, listener, hidl_utils::fill(&result, &closeHandle)).assertOk();
+ listener->assignCloseHandle(closeHandle);
+
+ return listener;
+ }
+
+ void send(const CanMessage& msg) {
+ if (!mBus) {
+ return;
+ }
+ mBus->send(msg);
+ }
+
+ private:
+ const std::string mIfname;
+ sp<ICanController> mController;
+ sp<ICanBus> mBus;
+};
+
+class CanFuzzer {
+ public:
+ ~CanFuzzer() { deInit(); }
+ bool init();
+ void process(const uint8_t* data, size_t size);
+ void deInit();
+
+ private:
+ Bus makeBus();
+ hidl_vec<hidl_string> getBusNames();
+ void getSupportedInterfaceTypes();
+ void invokeBus();
+ void invokeController();
+ void invokeUpInterface();
+ void invokeDownInterface();
+ FuzzedDataProvider* mFuzzedDataProvider = nullptr;
+ sp<CanController> mCanController = nullptr;
+ hidl_vec<hidl_string> mBusNames = {};
+ unsigned mLastInterface = 0;
+};
+} // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
+
+#endif // __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index cbc2150..18687bf 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -25,6 +25,9 @@
cc_test {
name: "VtsHalEvsV1_1TargetTest",
+ tidy_timeout_srcs: [
+ "VtsHalEvsV1_1TargetTest.cpp",
+ ],
srcs: [
"FrameHandler.cpp",
"FrameHandlerUltrasonics.cpp",
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
index 559a372..b973e91 100644
--- a/automotive/evs/OWNERS
+++ b/automotive/evs/OWNERS
@@ -1 +1,3 @@
+ankitarora@google.com
changyeon@google.com
+jwhpryor@google.com
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <fuzzer/FuzzedDataProvider.h>
#include <cmath>
#include <cstdlib>
#include <cstring>
@@ -21,36 +22,43 @@
#include "FormatConvert.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
- if (size < 256) {
+ // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+ if (size < (4 + 16 * 2 * 2)) {
return 0;
}
+ FuzzedDataProvider fdp(data, size);
+ std::size_t image_pixel_size = size - 4;
+ image_pixel_size = (image_pixel_size & INT_MAX) / 2;
- std::srand(std::time(nullptr)); // use current time as seed for random generator
- int random_variable = std::rand() % 10;
- int width = (int)sqrt(size);
- int height = width * ((float)random_variable / 10.0);
+ // API have a requirement that width must be divied by 16 except yuyvtorgb
+ int min_height = 2;
+ int max_height = (image_pixel_size / 16) & ~(1); // must be even number
+ int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+ int width = (image_pixel_size / height) & ~(16); // must be divisible by 16
- uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
- memcpy(src, data, sizeof(uint8_t) * (size));
- uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+ uint8_t* src = (uint8_t*)(data + 4);
+ uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
#ifdef COPY_NV21_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+ width);
#elif COPY_NV21_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YUYV_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+ tgt, width);
#elif COPY_YUYV_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+ tgt, width);
#endif
- free(src);
free(tgt);
return 0;
diff --git a/automotive/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index 1ff3450..e94893c 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -25,6 +25,9 @@
cc_test {
name: "VtsHalSurroundViewV1_0TargetTest",
+ tidy_timeout_srcs: [
+ "VtsHalSurroundViewV1_0TargetTest.cpp",
+ ],
srcs: [
"VtsHalSurroundViewV1_0TargetTest.cpp",
"SurroundViewStreamHandler.cpp",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 869c0c9..ba33098 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -172,6 +172,9 @@
vendor: true,
defaults: ["vhal_v2_0_target_defaults"],
whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+ tidy_timeout_srcs: [
+ "tests/VmsUtils_test.cpp",
+ ],
srcs: [
"tests/RecurrentTimer_test.cpp",
"tests/SubscriptionManager_test.cpp",
@@ -182,6 +185,7 @@
],
shared_libs: [
"libbase",
+ "libcutils",
],
header_libs: ["libbase_headers"],
test_suites: ["general-tests"],
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index c8c89dc..44f9134 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
- class hal
+ class early_hal
user vehicle_network
group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
private:
+ // Set unit test class as friend class to test private functions.
+ friend class VehicleHalManagerTestHelper;
+
using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
// Returns true if needs to call again shortly.
using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
static bool checkCallerHasWritePermissions(int fd);
- static bool safelyParseInt(int fd, int index, std::string s, int* out);
+ template <typename T>
+ static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+ static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+ // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+ // valid hex format, e.g. "0xABCD".
+ static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
void cmdHelp(int fd) const;
void cmdListAllProperties(int fd) const;
void cmdDumpAllProperties(int fd);
void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
- void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
static bool isSubscribable(const VehiclePropConfig& config,
SubscribeFlags flags);
@@ -120,7 +129,18 @@
static float checkSampleRate(const VehiclePropConfig& config,
float sampleRate);
static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+ // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+ // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+ static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop);
+ // Parses the options and get the values for the current option specified by "*index". "*index"
+ // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+ // the current option.
+ static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index);
+
+ private:
VehicleHal* mHal;
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
#include <cmath>
#include <fstream>
+#include <unordered_set>
+#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
+namespace {
+
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
const VehiclePropValue kEmptyValue{};
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+ // integer.
+ "-i",
+ // 64bit integer.
+ "-i64",
+ // float.
+ "-f",
+ // string.
+ "-s",
+ // bytes in hex format, e.g. 0xDEADBEEF.
+ "-b",
+ // Area id in integer.
+ "-a"};
+
+} // namespace
+
/**
* Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
* to store in reusable object pool.
*/
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
} else if (EqualsIgnoreCase(option, "--get")) {
cmdDumpSpecificProperties(fd, options);
} else if (EqualsIgnoreCase(option, "--set")) {
+ if (!checkCallerHasWritePermissions(fd)) {
+ dprintf(fd, "Caller does not have write permission\n");
+ return;
+ }
+ // Ignore the return value for this.
cmdSetOneProperty(fd, options);
} else {
dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
return false;
}
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
if (!android::base::ParseInt(s, out)) {
dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
return false;
@@ -247,19 +274,27 @@
return true;
}
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+ if (!android::base::ParseFloat(s, out)) {
+ dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+ return false;
+ }
+ return true;
+}
+
void VehicleHalManager::cmdHelp(int fd) const {
dprintf(fd, "Usage: \n\n");
dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
dprintf(fd, "--help: shows this help\n");
dprintf(fd, "--list: lists the ids of all supported properties\n");
dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
- // TODO: support other formats (int64, float, bytes)
dprintf(fd,
- "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
- "property PROP, using arbitrary number of key/value parameters (i for int32, "
- "s for string) and an optional area.\n"
- "Notice that the string value can be set just once, while the other can have multiple "
- "values (so they're used in the respective array)\n");
+ "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+ "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+ "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+ "Notice that the string, bytes and area value can be set just once, while the other can"
+ " have multiple values (so they're used in the respective array), "
+ "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n");
}
void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
VehiclePropValue input;
input.prop = prop;
input.areaId = areaId;
- auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+ auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
if (status == StatusCode::OK) {
dprintf(fd, "%s\n", toString(output).c_str());
} else {
dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
}
};
- get(input, callback);
+
+ StatusCode status;
+ auto value = mHal->get(input, &status);
+ callback(status, value.get() ? *value : kEmptyValue);
}
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
- if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
- size_t size = options.size();
-
- // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
- if (size % 2 != 0) {
- dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
- return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ if (!checkArgumentsSize(fd, options, 4)) {
+ dprintf(fd, "Requires at least 4 options, see help\n");
+ return false;
}
- int numberValues = (size - 2) / 2;
- VehiclePropValue prop;
- if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
- prop.timestamp = elapsedRealtimeNano();
- prop.status = VehiclePropertyStatus::AVAILABLE;
-
- // First pass: calculate sizes
- int sizeInt32 = 0;
- int stringIndex = 0;
- int areaIndex = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- std::string type = options[i];
- std::string value = options[i + 1];
- if (EqualsIgnoreCase(type, "i")) {
- sizeInt32++;
- } else if (EqualsIgnoreCase(type, "s")) {
- if (stringIndex != 0) {
- dprintf(fd,
- "defining string value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
- return;
- }
- stringIndex = i;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (areaIndex != 0) {
- dprintf(fd,
- "defining area value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
- return;
- }
- areaIndex = i;
- } else {
- dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
- return;
- }
- i += 2;
- }
- prop.value.int32Values.resize(sizeInt32);
-
- // Second pass: populate it
- int indexInt32 = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- int valueIndex = i + 1;
- std::string type = options[i];
- std::string value = options[valueIndex];
- if (EqualsIgnoreCase(type, "i")) {
- int safeInt;
- if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
- prop.value.int32Values[indexInt32++] = safeInt;
- } else if (EqualsIgnoreCase(type, "s")) {
- prop.value.stringValue = value;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
- }
- i += 2;
+ VehiclePropValue prop = {};
+ if (!parseSetPropOptions(fd, options, &prop)) {
+ return false;
}
ALOGD("Setting prop %s", toString(prop).c_str());
- auto status = set(prop);
+
+ // Do not use VehicleHalManager::set here because we don't want to check write permission.
+ // Caller should be able to use the debug interface to set read-only properties.
+ handlePropertySetEvent(prop);
+ auto status = mHal->set(prop);
+
if (status == StatusCode::OK) {
dprintf(fd, "Set property %s\n", toString(prop).c_str());
- } else {
- dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
- toString(status).c_str());
+ return true;
}
+ dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+ toString(status).c_str());
+ return false;
}
void VehicleHalManager::init() {
ALOGI("VehicleHalManager::init");
- mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+ mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
mBatchingConsumer.run(&mEventQueue,
kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
for (const HalClientValues& cv : clientValues) {
auto vecSize = cv.values.size();
hidl_vec<VehiclePropValue> vec;
- if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+ if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
} else {
vec.resize(vecSize);
@@ -595,6 +577,158 @@
}
}
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index) {
+ std::vector<std::string> values;
+ while (*index < options.size()) {
+ std::string option = options[*index];
+ if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+ return std::move(values);
+ }
+ values.push_back(option);
+ (*index)++;
+ }
+ return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop) {
+ // Options format:
+ // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+ size_t optionIndex = 1;
+ int propValue;
+ if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+ dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+ return false;
+ }
+ prop->prop = propValue;
+ prop->timestamp = elapsedRealtimeNano();
+ prop->status = VehiclePropertyStatus::AVAILABLE;
+ optionIndex++;
+ std::unordered_set<std::string> parsedOptions;
+
+ while (optionIndex < options.size()) {
+ std::string type = options[optionIndex];
+ optionIndex++;
+ size_t currentIndex = optionIndex;
+ std::vector<std::string> values = getOptionValues(options, &optionIndex);
+ if (parsedOptions.find(type) != parsedOptions.end()) {
+ dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+ return false;
+ }
+ parsedOptions.insert(type);
+ if (EqualsIgnoreCase(type, "-i")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i\"\n");
+ return false;
+ }
+ prop->value.int32Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int32_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int32Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-i64")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i64\"\n");
+ return false;
+ }
+ prop->value.int64Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int64_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int64Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-f")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-f\"\n");
+ return false;
+ }
+ prop->value.floatValues.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ float safeFloat;
+ if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+ dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+ return false;
+ }
+ prop->value.floatValues[i] = safeFloat;
+ }
+ } else if (EqualsIgnoreCase(type, "-s")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-s\"\n");
+ return false;
+ }
+ prop->value.stringValue = values[0];
+ } else if (EqualsIgnoreCase(type, "-b")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-b\"\n");
+ return false;
+ }
+ std::vector<uint8_t> bytes;
+ if (!parseHexString(fd, values[0], &bytes)) {
+ dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+ return false;
+ }
+ prop->value.bytes = bytes;
+ } else if (EqualsIgnoreCase(type, "-a")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-a\"\n");
+ return false;
+ }
+ if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+ dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+ return false;
+ }
+ } else {
+ dprintf(fd, "unknown option: %s\n", type.c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+ if (s.size() % 2 != 0) {
+ dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+ return false;
+ }
+ if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+ dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+ return false;
+ }
+ std::string subs = s.substr(2);
+ std::transform(subs.begin(), subs.end(), subs.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ bool highDigit = true;
+ for (size_t i = 0; i < subs.size(); i++) {
+ char c = subs[i];
+ uint8_t v;
+ if (c >= '0' && c <= '9') {
+ v = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ v = c - 'a' + 10;
+ } else {
+ dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+ return false;
+ }
+ if (highDigit) {
+ (*bytes).push_back(v * 16);
+ } else {
+ (*bytes)[bytes->size() - 1] += v;
+ }
+ highDigit = !highDigit;
+ }
+ return true;
+}
+
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index f09d75b..55617be 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -307,6 +307,18 @@
.prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_LEFT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_RIGHT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_LEFT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_RIGHT,
+ }},
},
.initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
{WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
@@ -1025,15 +1037,7 @@
.config =
{
.prop = toInt(VehicleProperty::EPOCH_TIME),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
- .access = VehiclePropertyAccess::READ_WRITE,
+ .access = VehiclePropertyAccess::WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
@@ -1105,6 +1109,42 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_INT,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.int32Values = {0}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_FLOAT,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.floatValues = {0.0f}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.int32Values = {0 /* false */}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_STRING,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.stringValue = {"Test"}},
+ },
#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
// Vendor propetry for E2E ClusterHomeService testing.
{
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index d5f6a18..51251a7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -189,6 +189,19 @@
KeyPress = 100,
};
+/**
+ * These properties are placeholder properties for developers to test new features without
+ * implementing a real property.
+ */
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32;
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT;
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN;
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING;
+
const int32_t kHvacPowerProperties[] = {
toInt(VehicleProperty::HVAC_FAN_SPEED),
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
#include <iostream>
#include <android-base/macros.h>
+#include <cutils/native_handle.h>
#include <utils/SystemClock.h>
#include <gtest/gtest.h>
@@ -32,6 +33,18 @@
namespace vehicle {
namespace V2_0 {
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+ public:
+ VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ return mManager->cmdSetOneProperty(fd, options);
+ }
+
+ public:
+ VehicleHalManager* mManager;
+};
+
namespace {
using namespace std::placeholders;
@@ -57,33 +70,21 @@
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
int32_t areaId = requestedPropValue.areaId;
- switch (property) {
- case VehicleProperty::INFO_MAKE:
- pValue = getValuePool()->obtainString(kCarMake);
- break;
- case VehicleProperty::INFO_FUEL_CAPACITY:
- if (fuelCapacityAttemptsLeft-- > 0) {
- // Emulate property not ready yet.
- *outStatus = StatusCode::TRY_AGAIN;
- } else {
- pValue = getValuePool()->obtainFloat(42.42);
- }
- break;
- default:
- if (requestedPropValue.prop == kCustomComplexProperty) {
- pValue = getValuePool()->obtainComplex();
- pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
- pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
- pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
- pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
- pValue->value.stringValue = kCarMake;
- break;
- }
- auto key = makeKey(toInt(property), areaId);
- if (mValues.count(key) == 0) {
- ALOGW("");
- }
- pValue = getValuePool()->obtain(mValues[key]);
+ if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+ if (fuelCapacityAttemptsLeft-- > 0) {
+ // Emulate property not ready yet.
+ *outStatus = StatusCode::TRY_AGAIN;
+ } else {
+ pValue = getValuePool()->obtainFloat(42.42);
+ }
+ } else {
+ auto key = makeKey(requestedPropValue);
+ if (mValues.count(key) == 0) {
+ ALOGW("key not found\n");
+ *outStatus = StatusCode::INVALID_ARG;
+ return pValue;
+ }
+ pValue = getValuePool()->obtain(mValues[key]);
}
if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
&& mirrorFoldAttemptsLeft-- > 0) {
return StatusCode::TRY_AGAIN;
}
-
mValues[makeKey(propValue)] = propValue;
return StatusCode::OK;
}
@@ -181,6 +181,18 @@
actualStatusCode = refStatus;
}
+ MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+ auto pValue = objectPool->obtainComplex();
+ pValue->prop = kCustomComplexProperty;
+ pValue->areaId = 0;
+ pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+ pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+ pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+ pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+ pValue->value.stringValue = kCarMake;
+ return pValue;
+ }
+
public:
VehiclePropValue actualValue;
StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
}
TEST_F(VehicleHalManagerTest, get_Complex) {
+ ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
invokeGet(kCustomComplexProperty, 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
}
TEST_F(VehicleHalManagerTest, get_StaticString) {
+ auto pValue = objectPool->obtainString(kCarMake);
+ pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+ pValue->areaId = 0;
+ ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
ASSERT_TRUE(clients.isEmpty());
}
+TEST_F(VehicleHalManagerTest, debug) {
+ hidl_handle fd = {};
+ fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+ // Because debug function returns void, so no way to check return value.
+ manager->debug(fd, {});
+ manager->debug(fd, {"--help"});
+ manager->debug(fd, {"--list"});
+ manager->debug(fd, {"--get"});
+ manager->debug(fd, {"--set"});
+ manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+ std::string test_name;
+ const hidl_vec<hidl_string> configs;
+ bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+ public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+ const SetPropTestCase& tc = GetParam();
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ return {
+ {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
+ {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+ {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+ {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+ {"success_set_ints",
+ {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+ true},
+ {"success_set_int64",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+ true},
+ {"success_set_int64s",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+ "9223372036854775807"},
+ true},
+ {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+ {"success_set_floats",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+ true},
+ {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+ {"fail_no_options", {}, false},
+ {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+ {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+ {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+ {"fail_duplicate_string",
+ {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+ false},
+ {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+ {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+ {"fail_duplicate_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+ false},
+ {"fail_multiple_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+ false},
+ {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+ {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+ {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+ {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+ {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+ {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+ {"fail_int64_out_of_range",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+ false},
+ {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+ {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+ {"fail_float_out_of_range",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+ false},
+ {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+ {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+ {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+ {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+ {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+ };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+ testing::ValuesIn(GenSetPropParams()),
+ [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+ return info.param.test_name;
+ });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_TRUE(helper.cmdSetOneProperty(
+ STDERR_FILENO, {"--set", infoMakeProperty, "-s", kCarMake,
+ "-b", "0xdeadbeef", "-i", "2147483647",
+ "0", "-2147483648", "-i64", "-9223372036854775808",
+ "0", "9223372036854775807", "-f", "-3.402823466E+38",
+ "0", "3.402823466E+38", "-a", "123"}));
+ StatusCode status = StatusCode::OK;
+ VehiclePropValue requestProp;
+ requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+ requestProp.areaId = 123;
+ auto value = hal->get(requestProp, &status);
+ ASSERT_EQ(StatusCode::OK, status);
+ ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+ ASSERT_EQ(value->areaId, 123);
+ ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+ uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+ ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+ ASSERT_EQ(3u, value->value.int32Values.size());
+ ASSERT_EQ(2147483647, value->value.int32Values[0]);
+ ASSERT_EQ(0, value->value.int32Values[1]);
+ ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+ ASSERT_EQ(3u, value->value.int64Values.size());
+ // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+ // tokens and the later does not fit in unsigned long long.
+ ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+ ASSERT_EQ(0, value->value.int64Values[1]);
+ ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+ ASSERT_EQ(3u, value->value.floatValues.size());
+ ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+ ASSERT_EQ(0.0f, value->value.floatValues[1]);
+ ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
} // namespace anonymous
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 6bfda32..7c8e1f5 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -487,8 +487,11 @@
* int64Values[3] = rear right ticks
* int64Values[4] = rear left ticks
*
- * configArray is used to indicate the micrometers-per-wheel-tick value and
- * which wheels are supported. configArray is set as follows:
+ * configArray is used to indicate the micrometers-per-wheel-tick values and
+ * which wheels are supported. Each micrometers-per-wheel-tick value is static (i.e. will not
+ * update based on wheel's status) and a best approximation. For example, if a vehicle has
+ * multiple rim/tire size options, the micrometers-per-wheel-tick values are set to those for
+ * the typically expected rim/tire size. configArray is set as follows:
*
* configArray[0], bits [0:3] = supported wheels. Uses enum Wheel.
* configArray[1] = micrometers per front left wheel tick
@@ -1433,17 +1436,29 @@
* This value denotes the number of milliseconds seconds that have
* elapsed since 1/1/1970 UTC.
*
- * Reading this value will give you the system’s time. This can be
- * useful to synchronize other vehicle systems (dash clock etc).
+ * AAOS will write to this value to give VHAL the Android system's time,
+ * if the VHAL supports this property. This can be useful to synchronize
+ * other vehicle systems (dash clock etc) with Android's time.
*
- * Writing this value will update the ‘ExternalTimeSuggestion’
- * value (if enabled). This value may be consumed by the “Time
- * Detector Service”, if other sources do not have a higher
- * priority. For information on how to adjust time source
- * priorities see Time Detector Service documentation.
+ * AAOS writes to this property once during boot, and
+ * will thereafter write only when some time-source changes are propagated.
+ * AAOS will fill in VehiclePropValue.timestamp correctly.
+ * Note that AAOS will not send updates for natural elapse of time.
+ * int64Values[0] = provided Unix time (in milliseconds)
+ *
+ * Note that the property may take >0 ms to get propagated through the stack
+ * and, having a timestamped property helps reduce any time drift. So,
+ * for all writes to the property, the timestamp can be used to negate this
+ * drift:
+ * drift = currentTimeMillis - PropValue.timestamp
+ * effectiveTime = PropValue.value.int64Values[0] + diff
+ *
+ * Aside, this property could have been better named ANDROID_EPOCH_TIME, but it
+ * continues to be called EPOCH_TIME for legacy reasons. We will try to fix
+ * this naming discrepancy when we migrate to AIDL.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
- * @access VehiclePropertyAccess:READ_WRITE
+ * @access VehiclePropertyAccess:WRITE_ONLY
* @unit VehicleUnit:MILLI_SECS
*/
EPOCH_TIME = (
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
index a75ce49..770d447 100644
--- a/automotive/vehicle/2.0/utils/Android.bp
+++ b/automotive/vehicle/2.0/utils/Android.bp
@@ -39,6 +39,9 @@
name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests",
defaults: ["vhal_v2_0_defaults"],
vendor: true,
+ tidy_timeout_srcs: [
+ "tests/UserHalHelper_test.cpp",
+ ],
srcs: [
"tests/UserHalHelper_test.cpp",
],
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
new file mode 100644
index 0000000..429ec39
--- /dev/null
+++ b/automotive/vehicle/OWNERS
@@ -0,0 +1,3 @@
+ericjeong@google.com
+keunyoung@google.com
+shanyu@google.com
diff --git a/biometrics/face/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp
index 80b153e..b7274e3 100644
--- a/biometrics/face/aidl/default/main.cpp
+++ b/biometrics/face/aidl/default/main.cpp
@@ -29,7 +29,7 @@
const std::string instance = std::string(Face::descriptor) + "/default";
binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 0935bf6..68b3360 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalBiometricsFingerprintV2_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
test_suites: ["general-tests", "vts"],
diff --git a/biometrics/fingerprint/aidl/default/main.cpp b/biometrics/fingerprint/aidl/default/main.cpp
index 4690d73..c985201 100644
--- a/biometrics/fingerprint/aidl/default/main.cpp
+++ b/biometrics/fingerprint/aidl/default/main.cpp
@@ -29,7 +29,7 @@
const std::string instance = std::string(Fingerprint::descriptor) + "/default";
binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/bluetooth/audio/2.0/vts/OWNERS b/bluetooth/audio/2.0/vts/OWNERS
deleted file mode 100644
index b266b06..0000000
--- a/bluetooth/audio/2.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/packages/modules/Bluetooth:/OWNERS
-
-cheneyni@google.com
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
index 822f5b3..1175fb3 100644
--- a/bluetooth/audio/2.1/Android.bp
+++ b/bluetooth/audio/2.1/Android.bp
@@ -25,7 +25,7 @@
],
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth.updatable",
+ "com.android.bluetooth",
],
gen_java: false,
}
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
index b0d171a..6e8c1d7 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -41,12 +41,8 @@
BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
LeAudioOutputAudioProvider
BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
-LeAudioOffloadOutputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
LeAudioInputAudioProvider
BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
-LeAudioOffloadInputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
Return<void> BluetoothAudioProvidersFactory::openProvider(
const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
@@ -94,15 +90,9 @@
case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
provider = &leaudio_output_provider_instance_;
break;
- case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
- provider = &leaudio_offload_output_provider_instance_;
- break;
case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
provider = &leaudio_input_provider_instance_;
break;
- case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
- provider = &leaudio_offload_input_provider_instance_;
- break;
default:
status = BluetoothAudioStatus::FAILURE;
}
@@ -157,7 +147,11 @@
audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
}
}
- } else if (sessionType != SessionType::UNKNOWN) {
+ } else if (sessionType !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ sessionType !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ sessionType != SessionType::UNKNOWN) {
std::vector<PcmParameters> db_pcm_capabilities =
android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
if (db_pcm_capabilities.size() == 1) {
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
index f8f557e..714d738 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -56,8 +56,6 @@
static HearingAidAudioProvider hearing_aid_provider_instance_;
static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
static LeAudioInputAudioProvider leaudio_input_provider_instance_;
- static LeAudioOffloadOutputAudioProvider leaudio_offload_output_provider_instance_;
- static LeAudioOffloadInputAudioProvider leaudio_offload_input_provider_instance_;
};
extern "C" IBluetoothAudioProvidersFactory*
diff --git a/bluetooth/audio/2.1/vts/OWNERS b/bluetooth/audio/2.1/vts/OWNERS
deleted file mode 100644
index b266b06..0000000
--- a/bluetooth/audio/2.1/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/packages/modules/Bluetooth:/OWNERS
-
-cheneyni@google.com
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
index 3314a8a..cea7326 100644
--- a/bluetooth/audio/2.1/vts/functional/Android.bp
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -10,6 +10,7 @@
cc_test {
name: "VtsHalBluetoothAudioV2_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
static_libs: [
"android.hardware.audio.common@5.0",
diff --git a/bluetooth/audio/2.2/Android.bp b/bluetooth/audio/2.2/Android.bp
deleted file mode 100644
index 6449c08..0000000
--- a/bluetooth/audio/2.2/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-hidl_interface {
- name: "android.hardware.bluetooth.audio@2.2",
- root: "android.hardware",
- srcs: [
- "types.hal",
- "IBluetoothAudioProvider.hal",
- "IBluetoothAudioProvidersFactory.hal",
- ],
- interfaces: [
- "android.hardware.audio.common@5.0",
- "android.hardware.bluetooth.audio@2.0",
- "android.hardware.bluetooth.audio@2.1",
- "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.2/IBluetoothAudioProvider.hal b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
deleted file mode 100644
index ad8c839..0000000
--- a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2;
-
-import @2.1::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.1::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_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
- generates (Status status, fmq_sync<uint8_t> dataMQ);
-};
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
deleted file mode 100644
index 7fb5b6c..0000000
--- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2;
-
-import IBluetoothAudioProvider;
-import @2.1::IBluetoothAudioProvidersFactory;
-import @2.0::Status;
-import @2.1::SessionType;
-
-/**
- * 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.1::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_2(SessionType sessionType)
- generates (Status status, IBluetoothAudioProvider provider);
-};
diff --git a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
deleted file mode 100644
index 126bc9e..0000000
--- a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-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_ = V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
-}
-
-bool A2dpOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
- return isValid(static_cast<V2_1::SessionType>(sessionType));
-}
-
-bool A2dpOffloadAudioProvider::isValid(const V2_1::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_2_2::OnSessionStarted(session_type_, stack_iface_,
- nullptr, audio_config_);
- _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
- return Void();
-}
-
-} // namespace implementation
-} // namespace V2_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
deleted file mode 100644
index 7ccdedc..0000000
--- a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2 {
-namespace implementation {
-
-class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
- public:
- A2dpOffloadAudioProvider();
-
- bool isValid(const V2_1::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
deleted file mode 100644
index 0d918e1..0000000
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
-
-// Here the buffer size is based on SBC
-static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
-// SBC is 128, and here we choose the LCM of 16, 24, and 32
-static constexpr uint32_t kPcmFrameCount = 96;
-static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
-// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
-// PCM counts, here we just choose a greater number
-static constexpr uint32_t kRtpFrameCount = 10;
-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_ = V2_1::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<V2_1::SessionType>(sessionType));
-}
-
-bool A2dpSoftwareAudioProvider::isValid(const V2_1::SessionType& sessionType) {
- return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
-}
-
-Return<void> A2dpSoftwareAudioProvider::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::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_2_2::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
deleted file mode 100644
index 3d4f0cc..0000000
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2 {
-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 V2_1::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/Android.bp b/bluetooth/audio/2.2/default/Android.bp
deleted file mode 100644
index 7a5ae75..0000000
--- a/bluetooth/audio/2.2/default/Android.bp
+++ /dev/null
@@ -1,37 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_library_shared {
- name: "android.hardware.bluetooth.audio@2.2-impl",
- defaults: ["hidl_defaults"],
- vendor: true,
- relative_install_path: "hw",
- srcs: [
- "BluetoothAudioProvidersFactory.cpp",
- "BluetoothAudioProvider.cpp",
- "A2dpOffloadAudioProvider.cpp",
- "A2dpSoftwareAudioProvider.cpp",
- "HearingAidAudioProvider.cpp",
- "LeAudioAudioProvider.cpp",
- "LeAudioOffloadAudioProvider.cpp",
- ],
- header_libs: ["libhardware_headers"],
- shared_libs: [
- "android.hardware.bluetooth.audio@2.0",
- "android.hardware.bluetooth.audio@2.1",
- "android.hardware.bluetooth.audio@2.2",
- "libbase",
- "libbluetooth_audio_session",
- "libcutils",
- "libfmq",
- "libhidlbase",
- "liblog",
- "libutils",
- ],
-}
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
deleted file mode 100644
index 3655bc0..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-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_(V2_1::SessionType::UNKNOWN),
- audio_config_({}) {}
-
-Return<void> BluetoothAudioProvider::startSession(
- const sp<IBluetoothAudioPort>& hostIf,
- const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
- AudioConfiguration audioConfig_2_2;
-
- if (audioConfig.getDiscriminator() ==
- V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
- audioConfig_2_2.pcmConfig(
- {.sampleRate =
- static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
- .channelMode = audioConfig.pcmConfig().channelMode,
- .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
- .dataIntervalUs = 0});
- } else {
- audioConfig_2_2.codecConfig(audioConfig.codecConfig());
- }
-
- return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> BluetoothAudioProvider::startSession_2_1(
- const sp<IBluetoothAudioPort>& hostIf,
- const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
- AudioConfiguration audioConfig_2_2;
- if (audioConfig.getDiscriminator() ==
- V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
- audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
- audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
- .streamMap = {{
- .streamHandle = 0xFFFF,
- .audioChannelAllocation =
- audioConfig.leAudioCodecConfig().audioChannelAllocation,
- }},
- .peerDelay = 0,
- .lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
- } else if (audioConfig.getDiscriminator() ==
- V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
- audioConfig_2_2.pcmConfig(audioConfig.pcmConfig());
- } else {
- audioConfig_2_2.codecConfig(audioConfig.codecConfig());
- }
-
- return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> BluetoothAudioProvider::startSession_2_2(
- 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_2_2::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_2_2::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_2_2::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
deleted file mode 100644
index b7581ba..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2/IBluetoothAudioProvider.h>
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-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 V2_1::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 V2_1::AudioConfiguration& audioConfig,
- startSession_cb _hidl_cb) override;
- Return<void> startSession_2_2(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_;
-
- V2_1::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
deleted file mode 100644
index 510833d..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-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_;
-LeAudioOffloadOutputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
-LeAudioInputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
-LeAudioOffloadInputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_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 V2_1::SessionType sessionType, openProvider_2_1_cb _hidl_cb) {
- LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
- BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
- BluetoothAudioProvider* provider = nullptr;
-
- switch (sessionType) {
- case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
- provider = &a2dp_software_provider_instance_;
- break;
- case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
- provider = &a2dp_offload_provider_instance_;
- break;
- case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
- provider = &hearing_aid_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
- provider = &leaudio_output_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
- provider = &leaudio_offload_output_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
- provider = &leaudio_input_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
- provider = &leaudio_offload_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::openProvider_2_2(
- const V2_1::SessionType sessionType, openProvider_2_2_cb _hidl_cb) {
- LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
- BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
- BluetoothAudioProvider* provider = nullptr;
-
- switch (sessionType) {
- case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
- provider = &a2dp_software_provider_instance_;
- break;
- case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
- provider = &a2dp_offload_provider_instance_;
- break;
- case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
- provider = &hearing_aid_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
- provider = &leaudio_output_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
- provider = &leaudio_offload_output_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
- provider = &leaudio_input_provider_instance_;
- break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
- provider = &leaudio_offload_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 V2_1::SessionType sessionType,
- getProviderCapabilities_2_1_cb _hidl_cb) {
- hidl_vec<V2_1::AudioCapabilities> audio_capabilities =
- hidl_vec<V2_1::AudioCapabilities>(0);
- if (sessionType == V2_1::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_1::SessionType::UNKNOWN) {
- std::vector<V2_1::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
deleted file mode 100644
index 658249b..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2/IBluetoothAudioProvidersFactory.h>
-
-#include "A2dpOffloadAudioProvider.h"
-#include "A2dpSoftwareAudioProvider.h"
-#include "BluetoothAudioProvider.h"
-#include "HearingAidAudioProvider.h"
-#include "LeAudioAudioProvider.h"
-#include "LeAudioOffloadAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-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 V2_1::SessionType sessionType,
- openProvider_2_1_cb _hidl_cb) override;
-
- Return<void> openProvider_2_2(const V2_1::SessionType sessionType,
- openProvider_2_2_cb _hidl_cb) override;
-
- Return<void> getProviderCapabilities_2_1(
- const V2_1::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_;
- static LeAudioOffloadOutputAudioProvider
- leaudio_offload_output_provider_instance_;
- static LeAudioOffloadInputAudioProvider
- leaudio_offload_input_provider_instance_;
-};
-
-extern "C" IBluetoothAudioProvidersFactory*
-HIDL_FETCH_IBluetoothAudioProvidersFactory(const char* name);
-
-} // namespace implementation
-} // namespace V2_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
deleted file mode 100644
index c79b910..0000000
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-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_ = V2_1::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<V2_1::SessionType>(sessionType));
-}
-
-bool HearingAidAudioProvider::isValid(const V2_1::SessionType& sessionType) {
- return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
-}
-
-Return<void> HearingAidAudioProvider::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::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_2_2::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h b/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
deleted file mode 100644
index 426c443..0000000
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2 {
-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 V2_1::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
deleted file mode 100644
index af6ec99..0000000
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-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_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
-}
-
-LeAudioInputAudioProvider::LeAudioInputAudioProvider()
- : LeAudioAudioProvider() {
- session_type_ = V2_1::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 V2_1::SessionType& sessionType) {
- return (sessionType == session_type_);
-}
-
-Return<void> LeAudioAudioProvider::startSession_2_1(
- const sp<V2_0::IBluetoothAudioPort>& hostIf,
- const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
- if (audioConfig.getDiscriminator() !=
- V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
- LOG(WARNING) << __func__
- << " - Invalid Audio Configuration=" << toString(audioConfig);
- _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
- DataMQ::Descriptor());
- return Void();
- }
-
- AudioConfiguration audioConfig_2_2;
- audioConfig_2_2.pcmConfig(
- {.sampleRate =
- static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
- .channelMode = audioConfig.pcmConfig().channelMode,
- .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
- .dataIntervalUs = 0});
-
- return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> LeAudioAudioProvider::startSession_2_2(
- 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_8000:
- kDataMqSize = 8000;
- break;
- case SampleRate::RATE_16000:
- kDataMqSize = 16000;
- break;
- case SampleRate::RATE_24000:
- kDataMqSize = 24000;
- break;
- case SampleRate::RATE_32000:
- kDataMqSize = 32000;
- break;
- case SampleRate::RATE_44100:
- kDataMqSize = 44100;
- break;
- case SampleRate::RATE_48000:
- kDataMqSize = 48000;
- break;
- default:
- LOG(WARNING) << __func__ << " - Unsupported sampling frequency="
- << toString(audioConfig.pcmConfig());
- _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
- DataMQ::Descriptor());
- return Void();
- }
-
- /* 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_ == V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
- kDataMqSize *= kBufferOutCount;
- else if (session_type_ ==
- V2_1::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_2(hostIf, audioConfig,
- _hidl_cb);
-}
-
-Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
- if (mDataMQ && mDataMQ->isValid()) {
- BluetoothAudioSessionReport_2_2::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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
deleted file mode 100644
index 40c26e0..0000000
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-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 V2_1::SessionType& sessionType) override;
- bool isValid(const V2_0::SessionType& sessionType) override;
-
- Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
- const V2_1::AudioConfiguration& audioConfig,
- startSession_cb _hidl_cb) override;
-
- Return<void> startSession_2_2(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_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
deleted file mode 100644
index 7b70654..0000000
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "BTAudioProviderLeAudioOffload"
-
-#include "LeAudioOffloadAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-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;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
- : LeAudioOffloadAudioProvider() {
- session_type_ =
- V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
-}
-
-LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
- : LeAudioOffloadAudioProvider() {
- session_type_ =
- V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
-}
-
-LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
- : BluetoothAudioProvider() {}
-
-bool LeAudioOffloadAudioProvider::isValid(
- const V2_0::SessionType& sessionType) {
- LOG(ERROR) << __func__
- << ", invalid session type for Offloaded Le Audio provider: "
- << toString(sessionType);
-
- return false;
-}
-
-bool LeAudioOffloadAudioProvider::isValid(
- const V2_1::SessionType& sessionType) {
- return (sessionType == session_type_);
-}
-
-Return<void> LeAudioOffloadAudioProvider::startSession_2_1(
- const sp<V2_0::IBluetoothAudioPort>& hostIf,
- const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
- if (audioConfig.getDiscriminator() !=
- V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
- LOG(WARNING) << __func__
- << " - Invalid Audio Configuration=" << toString(audioConfig);
- _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
- DataMQ::Descriptor());
- return Void();
- }
-
- AudioConfiguration audioConfig_2_2;
- audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
- audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
- .streamMap = {{
- .streamHandle = 0xFFFF,
- .audioChannelAllocation =
- audioConfig.leAudioCodecConfig().audioChannelAllocation,
- }},
- .peerDelay = 0,
- .lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
-
- return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> LeAudioOffloadAudioProvider::startSession_2_2(
- 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::leAudioConfig) {
- LOG(WARNING) << __func__
- << " - Invalid Audio Configuration=" << toString(audioConfig);
- _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
- DataMQ::Descriptor());
- return Void();
- }
-
- if (!android::bluetooth::audio::IsOffloadLeAudioConfigurationValid(
- session_type_, audioConfig.leAudioConfig())) {
- LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
- << toString(audioConfig.leAudioConfig());
- _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
- DataMQ::Descriptor());
- return Void();
- }
-
- return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
- _hidl_cb);
-}
-
-Return<void> LeAudioOffloadAudioProvider::onSessionReady(
- startSession_cb _hidl_cb) {
- BluetoothAudioSessionReport_2_2::OnSessionStarted(session_type_, stack_iface_,
- nullptr, audio_config_);
- _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
- return Void();
-}
-
-} // namespace implementation
-} // namespace V2_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
deleted file mode 100644
index 5620295..0000000
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2/types.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
- public:
- LeAudioOffloadAudioProvider();
-
- bool isValid(const V2_1::SessionType& sessionType) override;
- bool isValid(const V2_0::SessionType& sessionType) override;
-
- Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
- const V2_1::AudioConfiguration& audioConfig,
- startSession_cb _hidl_cb) override;
-
- Return<void> startSession_2_2(const sp<V2_0::IBluetoothAudioPort>& hostIf,
- const AudioConfiguration& audioConfig,
- startSession_cb _hidl_cb) override;
-
- private:
- Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
- public:
- LeAudioOffloadOutputAudioProvider();
-};
-
-class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
- public:
- LeAudioOffloadInputAudioProvider();
-};
-
-} // namespace implementation
-} // namespace V2_2
-} // namespace audio
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
deleted file mode 100644
index d5f8a3f..0000000
--- a/bluetooth/audio/2.2/types.hal
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2;
-
-import @2.1::Lc3Parameters;
-import @2.1::PcmParameters;
-import @2.0::CodecConfiguration;
-
-enum LeAudioMode : uint8_t {
- UNKNOWN = 0x00,
- UNICAST = 0x01,
- BROADCAST = 0x02,
-};
-
-struct UnicastStreamMap {
- /* The connection handle used for a unicast or a broadcast group. */
- uint16_t streamHandle;
- /* Audio channel allocation is a bit field, each enabled bit means that given audio direction,
- * i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
- * bit to the most significant bit. */
- uint32_t audioChannelAllocation;
-};
-
-struct BroadcastStreamMap {
- /* The connection handle used for a unicast or a broadcast group. */
- uint16_t streamHandle;
- /* Audio channel allocation is a bit field, each enabled bit means that given audio direction,
- * i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
- * bit to the most significant bit. */
- uint32_t audioChannelAllocation;
- Lc3Parameters lc3Config;
-};
-
-struct UnicastConfig {
- vec<UnicastStreamMap> streamMap;
- uint32_t peerDelay;
- Lc3Parameters lc3Config;
-};
-
-struct BroadcastConfig {
- vec<BroadcastStreamMap> streamMap;
-};
-
-struct LeAudioConfiguration {
- /* The mode of the LE audio */
- LeAudioMode mode;
- safe_union CodecConfig {
- UnicastConfig unicastConfig;
- BroadcastConfig broadcastConfig;
- } config;
-};
-
-/** Used to configure either a Hardware or Software Encoding session based on session type */
-safe_union AudioConfiguration {
- PcmParameters pcmConfig;
- CodecConfiguration codecConfig;
- LeAudioConfiguration leAudioConfig;
-};
diff --git a/bluetooth/audio/OWNERS b/bluetooth/audio/OWNERS
new file mode 100644
index 0000000..a8e9bda
--- /dev/null
+++ b/bluetooth/audio/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
new file mode 100644
index 0000000..52671b8
--- /dev/null
+++ b/bluetooth/audio/aidl/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.bluetooth.audio",
+ vendor_available: true,
+ srcs: ["android/hardware/bluetooth/audio/*.aidl"],
+ stability: "vintf",
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.common.fmq-V1",
+ "android.hardware.audio.common",
+ ],
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ enabled: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth",
+ ],
+ min_sdk_version: "31",
+ },
+ },
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..899b8ca
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AacCapabilities {
+ android.hardware.bluetooth.audio.AacObjectType[] objectType;
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+ boolean variableBitRateSupported;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..6adef6d
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AacConfiguration {
+ android.hardware.bluetooth.audio.AacObjectType objectType;
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode channelMode;
+ boolean variableBitRateEnabled;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..2148244
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum AacObjectType {
+ MPEG2_LC = 0,
+ MPEG4_LC = 1,
+ MPEG4_LTP = 2,
+ MPEG4_SCALABLE = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
new file mode 100644
index 0000000..4e5dfe6
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveCapabilities {
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.AptxAdaptiveChannelMode[] channelMode;
+ byte[] bitsPerSample;
+ android.hardware.bluetooth.audio.AptxMode[] aptxMode;
+ android.hardware.bluetooth.audio.AptxSinkBuffering sinkBufferingMs;
+ android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay ttp;
+ android.hardware.bluetooth.audio.AptxAdaptiveInputMode inputMode;
+ int inputFadeDurationMs;
+ byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
new file mode 100644
index 0000000..0499b70
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxAdaptiveChannelMode {
+ JOINT_STEREO = 0,
+ MONO = 1,
+ DUAL_MONO = 2,
+ TWS_STEREO = 4,
+ UNKNOWN = 255,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
new file mode 100644
index 0000000..aab0521
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveConfiguration {
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.AptxAdaptiveChannelMode channelMode;
+ byte bitsPerSample;
+ android.hardware.bluetooth.audio.AptxMode aptxMode;
+ android.hardware.bluetooth.audio.AptxSinkBuffering sinkBufferingMs;
+ android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay ttp;
+ android.hardware.bluetooth.audio.AptxAdaptiveInputMode inputMode;
+ int inputFadeDurationMs;
+ byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
new file mode 100644
index 0000000..f702939
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxAdaptiveInputMode {
+ STEREO = 0,
+ DUAL_MONO = 1,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
new file mode 100644
index 0000000..3560666
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveTimeToPlay {
+ byte lowLowLatency;
+ byte highLowLatency;
+ byte lowHighQuality;
+ byte highHighQuality;
+ byte lowTws;
+ byte highTws;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..08a38e2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxCapabilities {
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..91e88b3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxConfiguration {
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode channelMode;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl
new file mode 100644
index 0000000..d5dd9d9
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxMode {
+ UNKNOWN = 0,
+ HIGH_QUALITY = 4096,
+ LOW_LATENCY = 8192,
+ ULTRA_LOW_LATENCY = 16384,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
new file mode 100644
index 0000000..527418e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxSinkBuffering {
+ byte minLowLatency;
+ byte maxLowLatency;
+ byte minHighQuality;
+ byte maxHighQuality;
+ byte minTws;
+ byte maxTws;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..8ae716f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union AudioCapabilities {
+ android.hardware.bluetooth.audio.PcmCapabilities pcmCapabilities;
+ android.hardware.bluetooth.audio.CodecCapabilities a2dpCapabilities;
+ android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..3abfb31
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union AudioConfiguration {
+ android.hardware.bluetooth.audio.PcmConfiguration pcmConfig;
+ android.hardware.bluetooth.audio.CodecConfiguration a2dpConfig;
+ android.hardware.bluetooth.audio.LeAudioConfiguration leAudioConfig;
+ android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration leAudioBroadcastConfig;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..319a5e2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AudioLocation {
+ UNKNOWN = 1,
+ FRONT_LEFT = 2,
+ FRONT_RIGHT = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..c20c057
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum BluetoothAudioStatus {
+ UNKNOWN = 0,
+ SUCCESS = 1,
+ UNSUPPORTED_CODEC_CONFIGURATION = 2,
+ FAILURE = 3,
+ RECONFIGURATION = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
new file mode 100644
index 0000000..58710ef
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable BroadcastCapability {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ android.hardware.bluetooth.audio.AudioLocation supportedChannel;
+ int channelCountPerStream;
+ android.hardware.bluetooth.audio.BroadcastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union LeAudioCodecCapabilities {
+ @nullable android.hardware.bluetooth.audio.Lc3Capabilities[] lc3Capabilities;
+ @nullable android.hardware.bluetooth.audio.BroadcastCapability.VendorCapabilities[] vendorCapabillities;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..c3bc741
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum ChannelMode {
+ UNKNOWN = 0,
+ MONO = 1,
+ STEREO = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..6efdcb7
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable CodecCapabilities {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ android.hardware.bluetooth.audio.CodecCapabilities.Capabilities capabilities;
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union Capabilities {
+ android.hardware.bluetooth.audio.SbcCapabilities sbcCapabilities;
+ android.hardware.bluetooth.audio.AacCapabilities aacCapabilities;
+ android.hardware.bluetooth.audio.LdacCapabilities ldacCapabilities;
+ android.hardware.bluetooth.audio.AptxCapabilities aptxCapabilities;
+ android.hardware.bluetooth.audio.AptxAdaptiveCapabilities aptxAdaptiveCapabilities;
+ android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+ android.hardware.bluetooth.audio.CodecCapabilities.VendorCapabilities vendorCapabilities;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..77a6b1b
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable CodecConfiguration {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ int encodedAudioBitrate;
+ int peerMtu;
+ boolean isScmstEnabled;
+ android.hardware.bluetooth.audio.CodecConfiguration.CodecSpecific config;
+ @VintfStability
+ parcelable VendorConfiguration {
+ int vendorId;
+ char codecId;
+ ParcelableHolder codecConfig;
+ }
+ @VintfStability
+ union CodecSpecific {
+ android.hardware.bluetooth.audio.SbcConfiguration sbcConfig;
+ android.hardware.bluetooth.audio.AacConfiguration aacConfig;
+ android.hardware.bluetooth.audio.LdacConfiguration ldacConfig;
+ android.hardware.bluetooth.audio.AptxConfiguration aptxConfig;
+ android.hardware.bluetooth.audio.AptxAdaptiveConfiguration aptxAdaptiveConfig;
+ android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+ android.hardware.bluetooth.audio.CodecConfiguration.VendorConfiguration vendorConfig;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..1522cb4
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum CodecType {
+ UNKNOWN = 0,
+ SBC = 1,
+ AAC = 2,
+ APTX = 3,
+ APTX_HD = 4,
+ LDAC = 5,
+ LC3 = 6,
+ VENDOR = 7,
+ APTX_ADAPTIVE = 8,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..d364371
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioPort {
+ android.hardware.bluetooth.audio.PresentationPosition getPresentationPosition();
+ void startStream(boolean isLowLatency);
+ void stopStream();
+ void suspendStream();
+ void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+ void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+ void setLatencyMode(in android.hardware.bluetooth.audio.LatencyMode latencyMode);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..267af0f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProvider {
+ void endSession();
+ android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig, in android.hardware.bluetooth.audio.LatencyMode[] supportedLatencyModes);
+ void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+ void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+ void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
+ void setLowLatencyModeAllowed(in boolean allowed);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..5e33deb
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+ android.hardware.bluetooth.audio.AudioCapabilities[] getProviderCapabilities(in android.hardware.bluetooth.audio.SessionType sessionType);
+ android.hardware.bluetooth.audio.IBluetoothAudioProvider openProvider(in android.hardware.bluetooth.audio.SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl
new file mode 100644
index 0000000..5583679
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum LatencyMode {
+ UNKNOWN = 0,
+ LOW_LATENCY = 1,
+ FREE = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..cc4449a
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable Lc3Capabilities {
+ byte[] pcmBitDepth;
+ int[] samplingFrequencyHz;
+ int[] frameDurationUs;
+ int[] octetsPerFrame;
+ byte[] blocksPerSdu;
+ android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..7e8dccf
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable Lc3Configuration {
+ byte pcmBitDepth;
+ int samplingFrequencyHz;
+ int frameDurationUs;
+ int octetsPerFrame;
+ byte blocksPerSdu;
+ android.hardware.bluetooth.audio.ChannelMode channelMode;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..aa4e4c8
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LdacCapabilities {
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.LdacChannelMode[] channelMode;
+ android.hardware.bluetooth.audio.LdacQualityIndex[] qualityIndex;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..88d6faf
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacChannelMode {
+ UNKNOWN = 0,
+ STEREO = 1,
+ DUAL = 2,
+ MONO = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..8a37638
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LdacConfiguration {
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.LdacChannelMode channelMode;
+ android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..35e4358
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacQualityIndex {
+ HIGH = 0,
+ MID = 1,
+ LOW = 2,
+ ABR = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
new file mode 100644
index 0000000..7d53b0c
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioBroadcastConfiguration {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration.BroadcastStreamMap[] streamMap;
+ @VintfStability
+ parcelable BroadcastStreamMap {
+ char streamHandle;
+ int audioChannelAllocation;
+ android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
new file mode 100644
index 0000000..9818d54
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioCodecCapabilitiesSetting {
+ android.hardware.bluetooth.audio.UnicastCapability unicastEncodeCapability;
+ android.hardware.bluetooth.audio.UnicastCapability unicastDecodeCapability;
+ android.hardware.bluetooth.audio.BroadcastCapability broadcastCapability;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..bb3d7e4
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union LeAudioCodecConfiguration {
+ android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+ android.hardware.bluetooth.audio.LeAudioCodecConfiguration.VendorConfiguration vendorConfig;
+ @VintfStability
+ parcelable VendorConfiguration {
+ ParcelableHolder extension;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..edb6795
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioConfiguration {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap[] streamMap;
+ int peerDelayUs;
+ android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
+ @VintfStability
+ parcelable StreamMap {
+ char streamHandle;
+ int audioChannelAllocation;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..0c2f87d
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PcmCapabilities {
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+ byte[] bitsPerSample;
+ int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..93d7805
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PcmConfiguration {
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.ChannelMode channelMode;
+ byte bitsPerSample;
+ int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..7e997e8
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PresentationPosition {
+ long remoteDeviceAudioDelayNanos;
+ long transmittedOctets;
+ android.hardware.bluetooth.audio.PresentationPosition.TimeSpec transmittedOctetsTimestamp;
+ @VintfStability
+ parcelable TimeSpec {
+ long tvSec;
+ long tvNSec;
+ }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..091f6d7
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcAllocMethod {
+ ALLOC_MD_S = 0,
+ ALLOC_MD_L = 1,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..c8d7e7e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable SbcCapabilities {
+ int[] sampleRateHz;
+ android.hardware.bluetooth.audio.SbcChannelMode[] channelMode;
+ byte[] blockLength;
+ byte[] numSubbands;
+ android.hardware.bluetooth.audio.SbcAllocMethod[] allocMethod;
+ byte[] bitsPerSample;
+ int minBitpool;
+ int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..6441a99
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcChannelMode {
+ UNKNOWN = 0,
+ JOINT_STEREO = 1,
+ STEREO = 2,
+ DUAL = 3,
+ MONO = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..8eab9c3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable SbcConfiguration {
+ int sampleRateHz;
+ android.hardware.bluetooth.audio.SbcChannelMode channelMode;
+ byte blockLength;
+ byte numSubbands;
+ android.hardware.bluetooth.audio.SbcAllocMethod allocMethod;
+ byte bitsPerSample;
+ int minBitpool;
+ int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..baec9c2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SessionType {
+ UNKNOWN = 0,
+ A2DP_SOFTWARE_ENCODING_DATAPATH = 1,
+ A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 2,
+ HEARING_AID_SOFTWARE_ENCODING_DATAPATH = 3,
+ LE_AUDIO_SOFTWARE_ENCODING_DATAPATH = 4,
+ LE_AUDIO_SOFTWARE_DECODING_DATAPATH = 5,
+ LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 6,
+ LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7,
+ LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH = 8,
+ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 9,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
new file mode 100644
index 0000000..130fef9
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable UnicastCapability {
+ android.hardware.bluetooth.audio.CodecType codecType;
+ android.hardware.bluetooth.audio.AudioLocation supportedChannel;
+ int deviceCount;
+ int channelCountPerDevice;
+ android.hardware.bluetooth.audio.UnicastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union LeAudioCodecCapabilities {
+ android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+ android.hardware.bluetooth.audio.UnicastCapability.VendorCapabilities vendorCapabillities;
+ }
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..c4153e9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec capabilities
+ */
+@VintfStability
+parcelable AacCapabilities {
+ AacObjectType[] objectType;
+ int[] sampleRateHz;
+ ChannelMode[] channelMode;
+ boolean variableBitRateSupported;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..30338e7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec configuration
+ */
+@VintfStability
+parcelable AacConfiguration {
+ AacObjectType objectType;
+ int sampleRateHz;
+ ChannelMode channelMode;
+ boolean variableBitRateEnabled;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..4e9958c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum AacObjectType {
+ /**
+ * MPEG-2 Low Complexity. Support is Mandatory.
+ */
+ MPEG2_LC,
+ /**
+ * MPEG-4 Low Complexity. Support is Optional.
+ */
+ MPEG4_LC,
+ /**
+ * MPEG-4 Long Term Prediction. Support is Optional.
+ */
+ MPEG4_LTP,
+ /**
+ * MPEG-4 Scalable. Support is Optional.
+ */
+ MPEG4_SCALABLE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
new file mode 100644
index 0000000..6a56704
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AptxAdaptiveChannelMode;
+import android.hardware.bluetooth.audio.AptxMode;
+import android.hardware.bluetooth.audio.AptxSinkBuffering;
+import android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay;
+import android.hardware.bluetooth.audio.AptxAdaptiveInputMode;
+
+
+@VintfStability
+parcelable AptxAdaptiveCapabilities {
+ int[] sampleRateHz;
+ AptxAdaptiveChannelMode[] channelMode;
+ byte[] bitsPerSample;
+ AptxMode[] aptxMode;
+ AptxSinkBuffering sinkBufferingMs;
+ AptxAdaptiveTimeToPlay ttp;
+ AptxAdaptiveInputMode inputMode;
+ int inputFadeDurationMs;
+ byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
new file mode 100644
index 0000000..c5e89b1
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AptxAdaptiveChannelMode {
+ /* Joint Stereo - default mode */
+ JOINT_STEREO = 0,
+ /* Legacy Mono */
+ MONO = 1,
+ /* Two streams L & R in a single channel (TWS) */
+ DUAL_MONO = 2,
+ /* Stereo - For TWS+ where L and R are different links */
+ TWS_STEREO = 4,
+ UNKNOWN = 0xFF,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
new file mode 100644
index 0000000..84c3119
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AptxAdaptiveChannelMode;
+import android.hardware.bluetooth.audio.AptxMode;
+import android.hardware.bluetooth.audio.AptxSinkBuffering;
+import android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay;
+import android.hardware.bluetooth.audio.AptxAdaptiveInputMode;
+
+@VintfStability
+parcelable AptxAdaptiveConfiguration {
+ int sampleRateHz;
+ AptxAdaptiveChannelMode channelMode;
+ byte bitsPerSample;
+ AptxMode aptxMode;
+ AptxSinkBuffering sinkBufferingMs;
+ AptxAdaptiveTimeToPlay ttp;
+ AptxAdaptiveInputMode inputMode;
+ int inputFadeDurationMs;
+ byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
new file mode 100644
index 0000000..c2f0fc9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AptxAdaptiveInputMode {
+ STEREO = 0x00,
+ DUAL_MONO = 0x01,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
new file mode 100644
index 0000000..9bcf1a4
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable AptxAdaptiveTimeToPlay {
+ byte lowLowLatency;
+ byte highLowLatency;
+ byte lowHighQuality;
+ byte highHighQuality;
+ byte lowTws;
+ byte highTws;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..f5605d3
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec capabilities
+ */
+@VintfStability
+parcelable AptxCapabilities {
+ int[] sampleRateHz;
+ ChannelMode[] channelMode;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..83b7b0c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec configuration
+ */
+@VintfStability
+parcelable AptxConfiguration {
+ int sampleRateHz;
+ ChannelMode channelMode;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl
new file mode 100644
index 0000000..2422d69
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.bluetooth.audio;
+@VintfStability
+@Backing(type="int")
+enum AptxMode {
+ UNKNOWN = 0x00,
+ HIGH_QUALITY = 0x1000,
+ LOW_LATENCY = 0x2000,
+ ULTRA_LOW_LATENCY = 0x4000,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
new file mode 100644
index 0000000..3593b5d
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable AptxSinkBuffering {
+ byte minLowLatency;
+ byte maxLowLatency;
+ byte minHighQuality;
+ byte maxHighQuality;
+ byte minTws;
+ byte maxTws;
+}
+
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..a75c445
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.CodecCapabilities;
+import android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting;
+import android.hardware.bluetooth.audio.PcmCapabilities;
+
+/**
+ * Used to specify the capabilities of the different session types
+ */
+@VintfStability
+union AudioCapabilities {
+ PcmCapabilities pcmCapabilities;
+ CodecCapabilities a2dpCapabilities;
+ LeAudioCodecCapabilitiesSetting leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..a06337e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.CodecConfiguration;
+import android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration;
+import android.hardware.bluetooth.audio.LeAudioConfiguration;
+import android.hardware.bluetooth.audio.PcmConfiguration;
+
+/**
+ * Used to configure either a Hardware or Software Encoding session based on session type
+ */
+@VintfStability
+union AudioConfiguration {
+ PcmConfiguration pcmConfig;
+ CodecConfiguration a2dpConfig;
+ LeAudioConfiguration leAudioConfig;
+ LeAudioBroadcastConfiguration leAudioBroadcastConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..dedfbf9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="int")
+enum AudioLocation {
+ UNKNOWN = 1,
+ FRONT_LEFT = 1 << 1,
+ FRONT_RIGHT = 1 << 2,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..9ddafe9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="int")
+enum BluetoothAudioStatus {
+ UNKNOWN = 0,
+ SUCCESS = 1,
+ UNSUPPORTED_CODEC_CONFIGURATION = 2,
+ // General failure
+ FAILURE = 3,
+ RECONFIGURATION = 4,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
new file mode 100644
index 0000000..f1301fb
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+
+/**
+ * Used to specify the le audio broadcast codec capabilities for hardware offload.
+ */
+@VintfStability
+parcelable BroadcastCapability {
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union LeAudioCodecCapabilities {
+ @nullable Lc3Capabilities[] lc3Capabilities;
+ @nullable VendorCapabilities[] vendorCapabillities;
+ }
+ CodecType codecType;
+ AudioLocation supportedChannel;
+ // Supported channel count for each stream
+ int channelCountPerStream;
+ LeAudioCodecCapabilities leAudioCodecCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..6613872
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum ChannelMode {
+ UNKNOWN,
+ MONO,
+ STEREO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..9fcdf1c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AacCapabilities;
+import android.hardware.bluetooth.audio.AptxCapabilities;
+import android.hardware.bluetooth.audio.AptxAdaptiveCapabilities;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+import android.hardware.bluetooth.audio.LdacCapabilities;
+import android.hardware.bluetooth.audio.SbcCapabilities;
+
+/**
+ * Used to specify the capabilities of the codecs supported by Hardware Encoding.
+ * AptX and AptX-HD both use the AptxCapabilities field.
+ */
+@VintfStability
+parcelable CodecCapabilities {
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union Capabilities {
+ SbcCapabilities sbcCapabilities;
+ AacCapabilities aacCapabilities;
+ LdacCapabilities ldacCapabilities;
+ AptxCapabilities aptxCapabilities;
+ AptxAdaptiveCapabilities aptxAdaptiveCapabilities;
+ Lc3Capabilities lc3Capabilities;
+ VendorCapabilities vendorCapabilities;
+ }
+ CodecType codecType;
+ Capabilities capabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..5ed12e3
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AacConfiguration;
+import android.hardware.bluetooth.audio.AptxConfiguration;
+import android.hardware.bluetooth.audio.AptxAdaptiveConfiguration;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Configuration;
+import android.hardware.bluetooth.audio.LdacConfiguration;
+import android.hardware.bluetooth.audio.SbcConfiguration;
+
+/**
+ * Used to configure a Hardware Encoding session.
+ * AptX and AptX-HD both use the AptxConfiguration field.
+ */
+@VintfStability
+parcelable CodecConfiguration {
+ @VintfStability
+ parcelable VendorConfiguration {
+ int vendorId;
+ char codecId;
+ ParcelableHolder codecConfig;
+ }
+ @VintfStability
+ union CodecSpecific {
+ SbcConfiguration sbcConfig;
+ AacConfiguration aacConfig;
+ LdacConfiguration ldacConfig;
+ AptxConfiguration aptxConfig;
+ AptxAdaptiveConfiguration aptxAdaptiveConfig;
+ Lc3Configuration lc3Config;
+ VendorConfiguration vendorConfig;
+ }
+ CodecType codecType;
+ /**
+ * The encoded audio bitrate in bits / second.
+ * 0x00000000 - The audio bitrate is not specified / unused
+ * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
+ * 0x01000000 - 0xFFFFFFFF - Reserved
+ *
+ * The HAL needs to support all legal bitrates for the selected codec.
+ */
+ int encodedAudioBitrate;
+ /**
+ * Peer MTU (in two-octets)
+ */
+ int peerMtu;
+ /**
+ * Content protection by SCMS-T
+ */
+ boolean isScmstEnabled;
+ CodecSpecific config;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..386876e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="int")
+enum CodecType {
+ UNKNOWN,
+ SBC,
+ AAC,
+ APTX,
+ APTX_HD,
+ LDAC,
+ LC3,
+ VENDOR,
+ APTX_ADAPTIVE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..4ddf645
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.common.SourceMetadata;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LatencyMode;
+import android.hardware.bluetooth.audio.PresentationPosition;
+
+/**
+ * HAL interface from the Audio HAL to the Bluetooth stack
+ *
+ * The Audio HAL calls methods in this interface to start, suspend, and stop
+ * an audio stream. These calls return immediately and the results, if any,
+ * are sent over the IBluetoothAudioProvider interface.
+ *
+ * Moreover, the Audio HAL can also get the presentation position of the stream
+ * and provide stream metadata.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioPort {
+ /**
+ * Get the audio presentation position.
+ *
+ * @return the audio presentation position
+ *
+ */
+ PresentationPosition getPresentationPosition();
+
+ /**
+ * This indicates that the caller of this method has opened the data path
+ * and wants to start an audio stream. The caller must wait for a
+ * IBluetoothAudioProvider.streamStarted(Status) call.
+ *
+ * @param isLowLatency true if the stream being started with the latency
+ * control mechanism.
+ */
+ void startStream(boolean isLowLatency);
+
+ /**
+ * This indicates that the caller of this method wants to stop the audio
+ * stream. The data path will be closed after this call. There is no
+ * callback from the IBluetoothAudioProvider interface even though the
+ * teardown is asynchronous.
+ */
+ void stopStream();
+
+ /**
+ * This indicates that the caller of this method wants to suspend the audio
+ * stream. The caller must wait for the Bluetooth process to call
+ * IBluetoothAudioProvider.streamSuspended(Status). The caller still keeps
+ * the data path open.
+ */
+ void suspendStream();
+
+ /**
+ * Called when the metadata of the stream's source has been changed.
+ *
+ * @param sourceMetadata Description of the audio that is played by the
+ * clients.
+ */
+ void updateSourceMetadata(in SourceMetadata sourceMetadata);
+
+ /**
+ * Called when the metadata of the stream's sink has been changed.
+ *
+ * @param sinkMetadata as passed from Audio Framework
+ */
+ void updateSinkMetadata(in SinkMetadata sinkMetadata);
+
+ /**
+ * Called when latency mode is changed.
+ *
+ * @param latencyMode latency mode from audio
+ */
+ void setLatencyMode(in LatencyMode latencyMode);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..d5c051e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AudioConfiguration;
+import android.hardware.bluetooth.audio.BluetoothAudioStatus;
+import android.hardware.bluetooth.audio.IBluetoothAudioPort;
+import android.hardware.bluetooth.audio.LatencyMode;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+/**
+ * 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.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioProvider {
+ /**
+ * Ends the current session and unregisters the IBluetoothAudioPort
+ * interface.
+ */
+ void endSession();
+
+ /**
+ * 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.
+ * @param supportedLatencyModes latency modes supported by the active
+ * remote device
+ *
+ * @return 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
+ */
+ MQDescriptor<byte, SynchronizedReadWrite> startSession(
+ in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig,
+ in LatencyMode[] supportedLatencyModes);
+ /**
+ * Callback for IBluetoothAudioPort.startStream()
+ *
+ * @param status true for SUCCESS or false for FAILURE
+ */
+ void streamStarted(in BluetoothAudioStatus status);
+
+ /**
+ * Callback for IBluetoothAudioPort.suspendStream()
+ *
+ * @param status true for SUCCESS or false for FAILURE
+ */
+ void streamSuspended(in BluetoothAudioStatus status);
+
+ /**
+ * Called when the audio configuration of the stream has been changed.
+ *
+ * @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.
+ */
+ void updateAudioConfiguration(in AudioConfiguration audioConfig);
+
+ /**
+ * Called when the supported latency mode is updated.
+ *
+ * @param allowed If the peripheral devices can't keep up with low latency
+ * mode, the API will be called with supported is false.
+ */
+ void setLowLatencyModeAllowed(in boolean allowed);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..3cde22c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AudioCapabilities;
+import android.hardware.bluetooth.audio.IBluetoothAudioProvider;
+import android.hardware.bluetooth.audio.SessionType;
+/**
+ * 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().
+ *
+ */
+
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+ /**
+ * 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 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.
+ */
+ AudioCapabilities[] getProviderCapabilities(in SessionType sessionType);
+
+ /**
+ * 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 provider The provider of the specified session type
+ */
+ IBluetoothAudioProvider openProvider(in SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl
new file mode 100644
index 0000000..0c354f7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum LatencyMode {
+ UNKNOWN,
+ LOW_LATENCY,
+ FREE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..fc2f382
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec capabilities.
+ */
+@VintfStability
+parcelable Lc3Capabilities {
+ /*
+ * PCM is Input for encoder, Output for decoder
+ */
+ byte[] pcmBitDepth;
+ /*
+ * codec-specific parameters
+ */
+ int[] samplingFrequencyHz;
+ /*
+ * FrameDuration based on microseconds.
+ */
+ int[] frameDurationUs;
+ /*
+ * length in octets of a codec frame
+ */
+ int[] octetsPerFrame;
+ /*
+ * Number of blocks of codec frames per single SDU (Service Data Unit)
+ */
+ byte[] blocksPerSdu;
+ /*
+ * Channel mode used in A2DP special audio, ignored in standard LE Audio mode
+ */
+ ChannelMode[] channelMode;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..e8a93b2
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec configuration.
+ */
+@VintfStability
+parcelable Lc3Configuration {
+ /*
+ * PCM is Input for encoder, Output for decoder
+ */
+ byte pcmBitDepth;
+ /*
+ * codec-specific parameters
+ */
+ int samplingFrequencyHz;
+ /*
+ * FrameDuration based on microseconds.
+ */
+ int frameDurationUs;
+ /*
+ * length in octets of a codec frame
+ */
+ int octetsPerFrame;
+ /*
+ * Number of blocks of codec frames per single SDU (Service Data Unit)
+ */
+ byte blocksPerSdu;
+ /*
+ * Channel mode used in A2DP special audio, ignored in standard LE Audio mode
+ */
+ ChannelMode channelMode;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..1dbec08
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec capabilities
+ * all qualities must be supported.
+ */
+@VintfStability
+parcelable LdacCapabilities {
+ int[] sampleRateHz;
+ LdacChannelMode[] channelMode;
+ LdacQualityIndex[] qualityIndex;
+ byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..3cc910f
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+/**
+ * Channel Mode: 3 bits
+ */
+@VintfStability
+@Backing(type="byte")
+enum LdacChannelMode {
+ UNKNOWN,
+ STEREO,
+ DUAL,
+ MONO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..cc03dd0
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec configuration
+ * Only used when configuring the codec.
+ */
+@VintfStability
+parcelable LdacConfiguration {
+ int sampleRateHz;
+ LdacChannelMode channelMode;
+ LdacQualityIndex qualityIndex;
+ byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..9993b8b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum LdacQualityIndex {
+ /**
+ * 990kbps
+ */
+ HIGH,
+ /**
+ * 660kbps
+ */
+ MID,
+ /**
+ * 330kbps
+ */
+ LOW,
+ /**
+ * Adaptive Bit Rate mode
+ */
+ ABR,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
new file mode 100644
index 0000000..e9a1a0c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable LeAudioBroadcastConfiguration {
+ @VintfStability
+ parcelable BroadcastStreamMap {
+ /*
+ * The connection handle used for a broadcast group.
+ * Range: 0x0000 to 0xEFFF
+ */
+ char streamHandle;
+ /*
+ * Audio channel allocation is a bit field, each enabled bit means that given audio
+ * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+ * least significant bit to the most significant bit.
+ */
+ int audioChannelAllocation;
+ LeAudioCodecConfiguration leAudioCodecConfig;
+ }
+ CodecType codecType;
+ BroadcastStreamMap[] streamMap;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
new file mode 100644
index 0000000..58dac06
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.BroadcastCapability;
+import android.hardware.bluetooth.audio.UnicastCapability;
+
+/**
+ * Used to specify the le audio capabilities for unicast and broadcast hardware offload.
+ */
+@VintfStability
+parcelable LeAudioCodecCapabilitiesSetting {
+ UnicastCapability unicastEncodeCapability;
+ UnicastCapability unicastDecodeCapability;
+ BroadcastCapability broadcastCapability;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..421eeb2
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.Lc3Configuration;
+
+@VintfStability
+union LeAudioCodecConfiguration {
+ @VintfStability
+ parcelable VendorConfiguration {
+ ParcelableHolder extension;
+ }
+ Lc3Configuration lc3Config;
+ VendorConfiguration vendorConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..0d1e3de
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable LeAudioConfiguration {
+ @VintfStability
+ parcelable StreamMap {
+ /*
+ * The connection handle used for a unicast group.
+ * Range: 0x0000 to 0xEFFF
+ */
+ char streamHandle;
+ /*
+ * Audio channel allocation is a bit field, each enabled bit means that given audio
+ * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+ * least significant bit to the most significant bit. The valus follows the Bluetooth SIG
+ * Audio Location assigned number.
+ */
+ int audioChannelAllocation;
+ }
+ CodecType codecType;
+ StreamMap[] streamMap;
+ int peerDelayUs;
+ LeAudioCodecConfiguration leAudioCodecConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..776b777
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed capabilities
+ */
+@VintfStability
+parcelable PcmCapabilities {
+ int[] sampleRateHz;
+ ChannelMode[] channelMode;
+ byte[] bitsPerSample;
+ /**
+ * Data interval for data transfer
+ */
+ int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..03aa27b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed configuration
+ */
+@VintfStability
+parcelable PcmConfiguration {
+ int sampleRateHz;
+ ChannelMode channelMode;
+ byte bitsPerSample;
+ /**
+ * Data interval for data transfer
+ */
+ int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..f3b8aed
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+parcelable PresentationPosition {
+ @VintfStability
+ parcelable TimeSpec {
+ /**
+ * seconds
+ */
+ long tvSec;
+ /**
+ * nanoseconds
+ */
+ long tvNSec;
+ }
+ /*
+ * remoteDeviceAudioDelayNanos the audio delay from when the remote
+ * device (e.g. headset) receives audio data to when the device plays the
+ * sound. If the delay is unknown, the value is set to zero.
+ */
+ long remoteDeviceAudioDelayNanos;
+ /*
+ * transmittedOctets the number of audio data octets that were sent
+ * to a remote device. This excludes octets that have been written to the
+ * data path but have not been sent to the remote device. The count is
+ * not reset until stopStream() is called. If the software data path is
+ * unused (e.g. Hardware Offload), the value is set to 0.
+ */
+ long transmittedOctets;
+ /*
+ * transmittedOctetsTimestamp the value of CLOCK_MONOTONIC
+ * corresponding to transmittedOctets. If the software data path is
+ * unused (e.g., for Hardware Offload), the value is set to zero.
+ */
+ TimeSpec transmittedOctetsTimestamp;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..1159f30
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcAllocMethod {
+ /**
+ * SNR
+ */
+ ALLOC_MD_S,
+ /**
+ * Loudness
+ */
+ ALLOC_MD_L,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..743a1f7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec capabilities.
+ */
+@VintfStability
+parcelable SbcCapabilities {
+ int[] sampleRateHz;
+ SbcChannelMode[] channelMode;
+ byte[] blockLength;
+ byte[] numSubbands;
+ SbcAllocMethod[] allocMethod;
+ byte[] bitsPerSample;
+ /*
+ * range from 2 to 250.
+ */
+ int minBitpool;
+ /*
+ * range from 2 to 250.
+ */
+ int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..68e3267
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcChannelMode {
+ UNKNOWN,
+ JOINT_STEREO,
+ STEREO,
+ DUAL,
+ MONO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..054d03e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec configuration.
+ */
+@VintfStability
+parcelable SbcConfiguration {
+ int sampleRateHz;
+ SbcChannelMode channelMode;
+ byte blockLength;
+ byte numSubbands;
+ SbcAllocMethod allocMethod;
+ byte bitsPerSample;
+ /*
+ * range from 2 to 250.
+ */
+ int minBitpool;
+ /*
+ * range from 2 to 250.
+ */
+ int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..95beee7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+@VintfStability
+@Backing(type="byte")
+enum SessionType {
+ UNKNOWN,
+ /**
+ * A2DP legacy that AVDTP media is encoded by Bluetooth Stack
+ */
+ A2DP_SOFTWARE_ENCODING_DATAPATH,
+ /**
+ * The encoding of AVDTP media is done by HW and there is control only
+ */
+ A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ /**
+ * Used when encoded by Bluetooth Stack and streaming to Hearing Aid
+ */
+ HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+ /**
+ * Used when audio is encoded by the Bluetooth Stack and is streamed to LE
+ * Audio unicast device.
+ */
+ LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+ /**
+ * Used when audio is decoded by the Bluetooth Stack and is streamed to LE
+ * Audio unicast device.
+ */
+ LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+ /**
+ * Used when audio is encoded by hardware offload and is streamed to LE
+ * Audio unicast device. This is a control path only.
+ */
+ LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ /**
+ * Used when audio is decoded by hardware offload and is streamed to LE
+ * Audio unicast device. This is a control path only.
+ */
+ LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+ /**
+ * Used when audio is encoded by the Bluetooth stack and is streamed to LE
+ * Audio broadcast channels.
+ */
+ LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
+ /**
+ * Used when audio is encoded by hardware offload and is streamed to LE
+ * Audio broadcast channels. This is a control path only.
+ */
+ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
new file mode 100644
index 0000000..f8a924a
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+
+/**
+ * Used to specify the le audio unicast codec capabilities for hardware offload.
+ */
+@VintfStability
+parcelable UnicastCapability {
+ @VintfStability
+ parcelable VendorCapabilities {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ union LeAudioCodecCapabilities {
+ Lc3Capabilities lc3Capabilities;
+ VendorCapabilities vendorCapabillities;
+ }
+ CodecType codecType;
+ AudioLocation supportedChannel;
+ // The number of connected device
+ int deviceCount;
+ // Supported channel count for each device
+ int channelCountPerDevice;
+ LeAudioCodecCapabilities leAudioCodecCapabilities;
+}
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..4b4713d
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpHW"
+
+#include "A2dpOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {
+ session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
+ return (session_type == session_type_);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+ if (audio_config.getTag() != AudioConfiguration::a2dpConfig) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (!BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+ session_type_, audio_config.get<AudioConfiguration::a2dpConfig>())) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
+ DataMQDesc* _aidl_return) {
+ *_aidl_return = DataMQDesc();
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..4621e85
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+ A2dpOffloadAudioProvider();
+
+ bool isValid(const SessionType& session_type) override;
+
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+
+ private:
+ ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..59df3a9
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpSW"
+
+#include "A2dpSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+// Here the buffer size is based on SBC
+static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
+// SBC is 128, and here we choose the LCM of 16, 24, and 32
+static constexpr uint32_t kPcmFrameCount = 96;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
+// PCM counts, here we just choose a greater number
+static constexpr uint32_t kRtpFrameCount = 10;
+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(), data_mq_(nullptr) {
+ LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+ << " byte(s)";
+ std::unique_ptr<DataMQ> data_mq(
+ new DataMQ(kDataMqSize, /* EventFlag */ true));
+ if (data_mq && data_mq->isValid()) {
+ data_mq_ = std::move(data_mq);
+ session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+ } else {
+ ALOGE_IF(!data_mq, "failed to allocate data MQ");
+ ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+ }
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+ if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ const PcmConfiguration& pcm_config =
+ audio_config.get<AudioConfiguration::pcmConfig>();
+ if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << pcm_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady(
+ DataMQDesc* _aidl_return) {
+ if (data_mq_ == nullptr || !data_mq_->isValid()) {
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ *_aidl_return = data_mq_->dupeDesc();
+ auto desc = data_mq_->dupeDesc();
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..10f533a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+ A2dpSoftwareAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+
+ private:
+ // audio data queue for software encoding
+ std::unique_ptr<DataMQ> data_mq_;
+
+ ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp
new file mode 100644
index 0000000..13a5440
--- /dev/null
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -0,0 +1,35 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+ name: "android.hardware.bluetooth.audio-impl",
+ vendor: true,
+ vintf_fragments: ["bluetooth_audio.xml"],
+ srcs: [
+ "BluetoothAudioProvider.cpp",
+ "BluetoothAudioProviderFactory.cpp",
+ "A2dpOffloadAudioProvider.cpp",
+ "A2dpSoftwareAudioProvider.cpp",
+ "HearingAidAudioProvider.cpp",
+ "LeAudioOffloadAudioProvider.cpp",
+ "LeAudioSoftwareAudioProvider.cpp",
+ "service.cpp",
+ ],
+ export_include_dirs: ["."],
+ header_libs: ["libhardware_headers"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "android.hardware.bluetooth.audio-V1-ndk",
+ "libbluetooth_audio_session_aidl",
+ ],
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
new file mode 100644
index 0000000..0dd8148
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderStub"
+
+#include "BluetoothAudioProvider.h"
+
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProvider::BluetoothAudioProvider() {
+ death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latencyModes,
+ DataMQDesc* _aidl_return) {
+ if (host_if == nullptr) {
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ latency_modes_ = latencyModes;
+ audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+ stack_iface_ = host_if;
+
+ AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
+ this);
+
+ onSessionReady(_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::endSession() {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+ if (stack_iface_ != nullptr) {
+ BluetoothAudioSessionReport::OnSessionEnded(session_type_);
+
+ AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
+ death_recipient_.get(), this);
+ } else {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ }
+
+ stack_iface_ = nullptr;
+ audio_config_ = nullptr;
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
+ BluetoothAudioStatus status) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status);
+
+ if (stack_iface_ != nullptr) {
+ BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
+ status);
+ } else {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status) << " has NO session";
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended(
+ BluetoothAudioStatus status) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status);
+
+ if (stack_iface_ != nullptr) {
+ BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
+ status);
+ } else {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", status=" << toString(status) << " has NO session";
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
+ const AudioConfiguration& audio_config) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+ if (stack_iface_ == nullptr || audio_config_ == nullptr) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ if (audio_config.getTag() != audio_config_->getTag()) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " audio config type is not match";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+ BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
+ *audio_config_);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed(
+ bool allowed) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+ if (stack_iface_ == nullptr) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ LOG(INFO) << __func__ << " - allowed " << allowed;
+ BluetoothAudioSessionReport::ReportLowLatencyModeAllowedChanged(
+ session_type_, allowed);
+ return ndk::ScopedAStatus::ok();
+}
+
+void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) {
+ LOG(ERROR) << __func__ << " - BluetoothAudio Service died";
+ auto provider = static_cast<BluetoothAudioProvider*>(ptr);
+ if (provider == nullptr) {
+ LOG(ERROR) << __func__ << ": Null AudioProvider HAL died";
+ return;
+ }
+ provider->endSession();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
new file mode 100644
index 0000000..a9f830a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProvider : public BnBluetoothAudioProvider {
+ public:
+ BluetoothAudioProvider();
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+ ndk::ScopedAStatus endSession();
+ ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
+ ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
+ ndk::ScopedAStatus updateAudioConfiguration(
+ const AudioConfiguration& audio_config);
+ ndk::ScopedAStatus setLowLatencyModeAllowed(bool allowed);
+
+ virtual bool isValid(const SessionType& sessionType) = 0;
+
+ protected:
+ virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0;
+ static void binderDiedCallbackAidl(void* cookie_ptr);
+
+ ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
+
+ std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+ std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
+ SessionType session_type_;
+ std::vector<LatencyMode> latency_modes_;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
new file mode 100644
index 0000000..1e1680a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderFactoryAIDL"
+
+#include "BluetoothAudioProviderFactory.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <android-base/logging.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
+#include "LeAudioSoftwareAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
+ const SessionType session_type,
+ std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type);
+ std::shared_ptr<BluetoothAudioProvider> provider = nullptr;
+
+ switch (session_type) {
+ case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<A2dpSoftwareAudioProvider>();
+ break;
+ case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<A2dpOffloadAudioProvider>();
+ break;
+ case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<LeAudioSoftwareOutputAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<LeAudioOffloadOutputAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<LeAudioSoftwareInputAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ provider = ndk::SharedRefBase::make<LeAudioOffloadInputAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH:
+ provider =
+ ndk::SharedRefBase::make<LeAudioSoftwareBroadcastAudioProvider>();
+ break;
+ case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ provider =
+ ndk::SharedRefBase::make<LeAudioOffloadBroadcastAudioProvider>();
+ break;
+ default:
+ provider = nullptr;
+ break;
+ }
+
+ if (provider == nullptr || !provider->isValid(session_type)) {
+ provider = nullptr;
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ *_aidl_return = provider;
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities(
+ const SessionType session_type,
+ std::vector<AudioCapabilities>* _aidl_return) {
+ if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ auto codec_capabilities =
+ BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type);
+ _aidl_return->resize(codec_capabilities.size());
+ for (int i = 0; i < codec_capabilities.size(); i++) {
+ _aidl_return->at(i).set<AudioCapabilities::a2dpCapabilities>(
+ codec_capabilities[i]);
+ }
+ } else if (session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type ==
+ SessionType::
+ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
+ BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(session_type);
+ if (db_codec_capabilities.size()) {
+ _aidl_return->resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ _aidl_return->at(i).set<AudioCapabilities::leAudioCapabilities>(
+ db_codec_capabilities[i]);
+ }
+ }
+ } else if (session_type != SessionType::UNKNOWN) {
+ auto pcm_capabilities = BluetoothAudioCodecs::GetSoftwarePcmCapabilities();
+ _aidl_return->resize(pcm_capabilities.size());
+ for (int i = 0; i < pcm_capabilities.size(); i++) {
+ _aidl_return->at(i).set<AudioCapabilities::pcmCapabilities>(
+ pcm_capabilities[i]);
+ }
+ }
+
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type)
+ << " supports " << _aidl_return->size() << " codecs";
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
new file mode 100644
index 0000000..b38cfd2
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProviderFactory : public BnBluetoothAudioProviderFactory {
+ public:
+ BluetoothAudioProviderFactory();
+
+ ndk::ScopedAStatus openProvider(
+ const SessionType session_type,
+ std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) override;
+
+ ndk::ScopedAStatus getProviderCapabilities(
+ const SessionType session_type,
+ std::vector<AudioCapabilities>* _aidl_return) override;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
new file mode 100644
index 0000000..e8b01ac
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderHearingAid"
+
+#include "HearingAidAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+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(), data_mq_(nullptr) {
+ LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+ << " byte(s)";
+ std::unique_ptr<DataMQ> data_mq(
+ new DataMQ(kDataMqSize, /* EventFlag */ true));
+ if (data_mq && data_mq->isValid()) {
+ data_mq_ = std::move(data_mq);
+ session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+ } else {
+ ALOGE_IF(!data_mq, "failed to allocate data MQ");
+ ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+ }
+}
+bool HearingAidAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+ if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+ if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << pcm_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady(
+ DataMQDesc* _aidl_return) {
+ if (data_mq_ == nullptr || !data_mq_->isValid()) {
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ *_aidl_return = data_mq_->dupeDesc();
+ auto desc = data_mq_->dupeDesc();
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..a158c86
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class HearingAidAudioProvider : public BluetoothAudioProvider {
+ public:
+ HearingAidAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+
+ private:
+ // audio data queue for software encoding
+ std::unique_ptr<DataMQ> data_mq_;
+
+ ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
new file mode 100644
index 0000000..0e22e44
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioHW"
+
+#include "LeAudioOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
+ : LeAudioOffloadAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
+ : LeAudioOffloadAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+LeAudioOffloadBroadcastAudioProvider::LeAudioOffloadBroadcastAudioProvider()
+ : LeAudioOffloadAudioProvider() {
+ session_type_ =
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
+ : BluetoothAudioProvider() {}
+
+bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+ if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ const auto& le_audio_config =
+ audio_config.get<AudioConfiguration::leAudioConfig>();
+ if (!BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+ session_type_, le_audio_config)) {
+ LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
+ << le_audio_config.toString();
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
+ DataMQDesc* _aidl_return) {
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..614c794
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+ LeAudioOffloadAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+
+ private:
+ ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+ LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+ LeAudioOffloadInputAudioProvider();
+};
+
+class LeAudioOffloadBroadcastAudioProvider
+ : public LeAudioOffloadAudioProvider {
+ public:
+ LeAudioOffloadBroadcastAudioProvider();
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..911c928
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioSW"
+
+#include "LeAudioSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+#include <cstdint>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr uint32_t kBufferOutCount = 2; // two frame buffer
+static constexpr uint32_t kBufferInCount = 2; // two frame buffer
+
+inline uint32_t channel_mode_to_channel_count(ChannelMode channel_mode) {
+ switch (channel_mode) {
+ case ChannelMode::MONO:
+ return 1;
+ case ChannelMode::STEREO:
+ return 2;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+LeAudioSoftwareOutputAudioProvider::LeAudioSoftwareOutputAudioProvider()
+ : LeAudioSoftwareAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioSoftwareInputAudioProvider::LeAudioSoftwareInputAudioProvider()
+ : LeAudioSoftwareAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
+}
+
+LeAudioSoftwareBroadcastAudioProvider::LeAudioSoftwareBroadcastAudioProvider()
+ : LeAudioSoftwareAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioSoftwareAudioProvider::LeAudioSoftwareAudioProvider()
+ : BluetoothAudioProvider(), data_mq_(nullptr) {}
+
+bool LeAudioSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+ if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+ << audio_config.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+ if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+ LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+ << pcm_config.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ uint32_t buffer_modifier = 0;
+ if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH)
+ buffer_modifier = kBufferOutCount;
+ else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH)
+ buffer_modifier = kBufferInCount;
+
+ uint32_t data_mq_size =
+ (ceil(pcm_config.sampleRateHz) / 1000) *
+ channel_mode_to_channel_count(pcm_config.channelMode) *
+ (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
+ buffer_modifier;
+ if (data_mq_size <= 0) {
+ LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
+ << ", SampleRateHz: " << pcm_config.sampleRateHz
+ << ", ChannelMode: " << toString(pcm_config.channelMode)
+ << ", BitsPerSample: "
+ << static_cast<int>(pcm_config.bitsPerSample)
+ << ", DataIntervalUs: " << pcm_config.dataIntervalUs
+ << ", SessionType: " << toString(session_type_);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size
+ << " byte(s)";
+
+ std::unique_ptr<DataMQ> temp_data_mq(
+ new DataMQ(data_mq_size, /* EventFlag */ true));
+ if (temp_data_mq == nullptr || !temp_data_mq->isValid()) {
+ ALOGE_IF(!temp_data_mq, "failed to allocate data MQ");
+ ALOGE_IF(temp_data_mq && !temp_data_mq->isValid(), "data MQ is invalid");
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ data_mq_ = std::move(temp_data_mq);
+
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady(
+ DataMQDesc* _aidl_return) {
+ if (data_mq_ == nullptr || !data_mq_->isValid()) {
+ *_aidl_return = DataMQDesc();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ *_aidl_return = data_mq_->dupeDesc();
+ auto desc = data_mq_->dupeDesc();
+ BluetoothAudioSessionReport::OnSessionStarted(
+ session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
new file mode 100644
index 0000000..21243ff
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+ LeAudioSoftwareAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+
+ ndk::ScopedAStatus startSession(
+ const std::shared_ptr<IBluetoothAudioPort>& host_if,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
+
+ private:
+ // audio data queue for software encoding
+ std::unique_ptr<DataMQ> data_mq_;
+
+ ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioSoftwareOutputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+ LeAudioSoftwareOutputAudioProvider();
+};
+
+class LeAudioSoftwareInputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+ LeAudioSoftwareInputAudioProvider();
+};
+
+class LeAudioSoftwareBroadcastAudioProvider
+ : public LeAudioSoftwareAudioProvider {
+ public:
+ LeAudioSoftwareBroadcastAudioProvider();
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml
new file mode 100644
index 0000000..1859a1a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.bluetooth.audio</name>
+ <fqname>IBluetoothAudioProviderFactory/default</fqname>
+ </hal>
+</manifest>
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/service.cpp b/bluetooth/audio/aidl/default/service.cpp
new file mode 100644
index 0000000..f8f9cde
--- /dev/null
+++ b/bluetooth/audio/aidl/default/service.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BtAudioAIDLService"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+#include "BluetoothAudioProviderFactory.h"
+
+using ::aidl::android::hardware::bluetooth::audio::
+ BluetoothAudioProviderFactory;
+
+extern "C" __attribute__((visibility("default"))) binder_status_t
+createIBluetoothAudioProviderFactory() {
+ auto factory = ::ndk::SharedRefBase::make<BluetoothAudioProviderFactory>();
+ const std::string instance_name =
+ std::string() + BluetoothAudioProviderFactory::descriptor + "/default";
+ binder_status_t aidl_status = AServiceManager_addService(
+ factory->asBinder().get(), instance_name.c_str());
+ ALOGW_IF(aidl_status != STATUS_OK, "Could not register %s, status=%d",
+ instance_name.c_str(), aidl_status);
+ return aidl_status;
+}
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
new file mode 100644
index 0000000..feb952e
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -0,0 +1,32 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalBluetoothAudioTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
+ srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
+ shared_libs: [
+ "android.hardware.audio.common-V1-ndk",
+ "android.hardware.bluetooth.audio-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
new file mode 100644
index 0000000..18352a0
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -0,0 +1,1673 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include <cstdint>
+#include <future>
+#include <unordered_set>
+#include <vector>
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::bluetooth::audio::AacCapabilities;
+using aidl::android::hardware::bluetooth::audio::AacConfiguration;
+using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
+using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
+using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
+using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
+using aidl::android::hardware::bluetooth::audio::ChannelMode;
+using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
+using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::CodecType;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
+using aidl::android::hardware::bluetooth::audio::LatencyMode;
+using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
+using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
+using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
+using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
+using aidl::android::hardware::bluetooth::audio::
+ LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
+using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
+using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
+using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
+using aidl::android::hardware::bluetooth::audio::SessionType;
+using aidl::android::hardware::bluetooth::audio::UnicastCapability;
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using android::AidlMessageQueue;
+using android::ProcessState;
+using android::String16;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+// Constants
+
+static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
+static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
+static constexpr ChannelMode a2dp_channel_modes[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+static constexpr CodecType a2dp_codec_types[] = {
+ CodecType::UNKNOWN, CodecType::SBC, CodecType::AAC,
+ CodecType::APTX, CodecType::APTX_HD, CodecType::LDAC,
+ CodecType::LC3, CodecType::APTX_ADAPTIVE};
+static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
+// Helpers
+
+template <typename T>
+struct identity {
+ typedef T type;
+};
+
+template <class T>
+bool contained_in_vector(const std::vector<T>& vector,
+ const typename identity<T>::type& target) {
+ return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
+ const CodecConfiguration::CodecSpecific& src) {
+ switch (src.getTag()) {
+ case CodecConfiguration::CodecSpecific::sbcConfig:
+ dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
+ src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::aacConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aacConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::ldacConfig:
+ dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
+ src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::aptxConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::lc3Config:
+ dst.set<CodecConfiguration::CodecSpecific::lc3Config>(
+ src.get<CodecConfiguration::CodecSpecific::lc3Config>());
+ break;
+ case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
+ break;
+ default:
+ break;
+ }
+}
+
+class BluetoothAudioPort : public BnBluetoothAudioPort {
+ public:
+ BluetoothAudioPort() {}
+
+ ndk::ScopedAStatus startStream(bool) { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus setCodecType(const CodecType) {
+ return ScopedAStatus::ok();
+ }
+
+ protected:
+ virtual ~BluetoothAudioPort() = default;
+};
+
+class BluetoothAudioProviderFactoryAidl
+ : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
+ SpAIBinder(AServiceManager_getService(GetParam().c_str())));
+ audio_provider_ = nullptr;
+ ASSERT_NE(provider_factory_, nullptr);
+ }
+
+ virtual void TearDown() override { provider_factory_ = nullptr; }
+
+ void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+ temp_provider_capabilities_.clear();
+ auto aidl_retval = provider_factory_->getProviderCapabilities(
+ session_type, &temp_provider_capabilities_);
+ // AIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(aidl_retval.isOk());
+ switch (session_type) {
+ case SessionType::UNKNOWN: {
+ ASSERT_TRUE(temp_provider_capabilities_.empty());
+ } break;
+ case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+ case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_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].getTag(),
+ AudioCapabilities::pcmCapabilities);
+ } break;
+ case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
+ std::unordered_set<CodecType> codec_types;
+ // empty capability means offload is unsupported
+ for (auto& audio_capability : temp_provider_capabilities_) {
+ ASSERT_EQ(audio_capability.getTag(),
+ AudioCapabilities::a2dpCapabilities);
+ const auto& codec_capabilities =
+ audio_capability.get<AudioCapabilities::a2dpCapabilities>();
+ // Every codec can present once at most
+ ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
+ switch (codec_capabilities.codecType) {
+ case CodecType::SBC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::sbcCapabilities);
+ break;
+ case CodecType::AAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::aacCapabilities);
+ break;
+ case CodecType::APTX:
+ case CodecType::APTX_HD:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::aptxCapabilities);
+ break;
+ case CodecType::LDAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::ldacCapabilities);
+ break;
+ case CodecType::LC3:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::lc3Capabilities);
+ break;
+ case CodecType::APTX_ADAPTIVE:
+ case CodecType::VENDOR:
+ case CodecType::UNKNOWN:
+ break;
+ }
+ codec_types.insert(codec_capabilities.codecType);
+ }
+ } break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
+ ASSERT_FALSE(temp_provider_capabilities_.empty());
+ for (auto audio_capability : temp_provider_capabilities_) {
+ ASSERT_EQ(audio_capability.getTag(),
+ AudioCapabilities::leAudioCapabilities);
+ }
+ } break;
+ }
+ }
+
+ /***
+ * 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) {
+ auto aidl_retval =
+ provider_factory_->openProvider(session_type, &audio_provider_);
+ if (aidl_retval.isOk()) {
+ ASSERT_NE(session_type, SessionType::UNKNOWN);
+ ASSERT_NE(audio_provider_, nullptr);
+ audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
+ } else {
+ // Hardware offloading is optional
+ ASSERT_TRUE(
+ session_type == SessionType::UNKNOWN ||
+ session_type ==
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::
+ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_EQ(audio_provider_, nullptr);
+ }
+ }
+
+ bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
+ if (temp_provider_capabilities_.size() != 1 ||
+ temp_provider_capabilities_[0].getTag() !=
+ AudioCapabilities::pcmCapabilities) {
+ return false;
+ }
+ auto pcm_capability = temp_provider_capabilities_[0]
+ .get<AudioCapabilities::pcmCapabilities>();
+ return (contained_in_vector(pcm_capability.channelMode,
+ pcm_config.channelMode) &&
+ contained_in_vector(pcm_capability.sampleRateHz,
+ pcm_config.sampleRateHz) &&
+ contained_in_vector(pcm_capability.bitsPerSample,
+ pcm_config.bitsPerSample));
+ }
+
+ std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
+ std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
+ std::shared_ptr<IBluetoothAudioPort> audio_port_;
+ std::vector<AudioCapabilities> temp_provider_capabilities_;
+
+ static constexpr SessionType kSessionTypes[] = {
+ SessionType::UNKNOWN,
+ SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ };
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl,
+ OpenProviderAndCheckCapabilitiesBySession) {
+ for (auto session_type : kSessionTypes) {
+ 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 BluetoothAudioProviderA2dpSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::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;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, OpenA2dpSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareAidl,
+ StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : a2dp_sample_rates) {
+ for (auto bits_per_sample : a2dp_bits_per_samples) {
+ for (auto channel_mode : a2dp_channel_modes) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ };
+ bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
+ */
+class BluetoothAudioProviderA2dpHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+
+ void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
+ temp_codec_capabilities_ = nullptr;
+ for (auto& codec_capability : temp_provider_capabilities_) {
+ auto& a2dp_capabilities =
+ codec_capability.get<AudioCapabilities::a2dpCapabilities>();
+ if (a2dp_capabilities.codecType != codec_type) {
+ continue;
+ }
+ temp_codec_capabilities_ = &a2dp_capabilities;
+ }
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetSbcCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
+ if (!supported) {
+ SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ sbc_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(sbc_config));
+ return sbc_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::SBC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::SBC) {
+ return sbc_codec_specifics;
+ }
+ // parse the capability
+ auto& sbc_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::sbcCapabilities>();
+ if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+ return sbc_codec_specifics;
+ }
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t sample_rate : sbc_capability.sampleRateHz) {
+ for (int8_t block_length : sbc_capability.blockLength) {
+ for (int8_t num_subbands : sbc_capability.numSubbands) {
+ for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
+ for (auto channel_mode : sbc_capability.channelMode) {
+ for (auto alloc_method : sbc_capability.allocMethod) {
+ SbcConfiguration sbc_data = {
+ .sampleRateHz = 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};
+ sbc_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(sbc_data));
+ }
+ }
+ }
+ }
+ }
+ }
+ return sbc_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetAacCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
+ if (!supported) {
+ AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ aac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aac_config));
+ return aac_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::AAC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::AAC) {
+ return aac_codec_specifics;
+ }
+ // parse the capability
+ auto& aac_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::aacCapabilities>();
+
+ std::vector<bool> variable_bit_rate_enableds = {false};
+ if (aac_capability.variableBitRateSupported) {
+ variable_bit_rate_enableds.push_back(true);
+ }
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (auto object_type : aac_capability.objectType) {
+ for (int32_t sample_rate : aac_capability.sampleRateHz) {
+ for (auto channel_mode : aac_capability.channelMode) {
+ for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
+ for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+ AacConfiguration aac_data{
+ .objectType = object_type,
+ .sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .variableBitRateEnabled = variable_bit_rate_enabled,
+ .bitsPerSample = bits_per_sample};
+ aac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aac_data));
+ }
+ }
+ }
+ }
+ }
+ return aac_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetLdacCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
+ if (!supported) {
+ LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ ldac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(ldac_config));
+ return ldac_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::LDAC) {
+ return ldac_codec_specifics;
+ }
+ // parse the capability
+ auto& ldac_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::ldacCapabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t sample_rate : ldac_capability.sampleRateHz) {
+ for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
+ for (auto channel_mode : ldac_capability.channelMode) {
+ for (auto quality_index : ldac_capability.qualityIndex) {
+ LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .qualityIndex = quality_index,
+ .bitsPerSample = bits_per_sample};
+ ldac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(ldac_data));
+ }
+ }
+ }
+ }
+ return ldac_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
+ if (!supported) {
+ AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ aptx_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aptx_config));
+ return aptx_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(
+ (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+ if (temp_codec_capabilities_ == nullptr) {
+ return aptx_codec_specifics;
+ }
+ 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
+ auto& aptx_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::aptxCapabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
+ for (int32_t sample_rate : aptx_capability.sampleRateHz) {
+ for (auto channel_mode : aptx_capability.channelMode) {
+ AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .bitsPerSample = bits_per_sample};
+ aptx_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aptx_data));
+ }
+ }
+ }
+ return aptx_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetLc3CodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> lc3_codec_specifics;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0,
+ .frameDurationUs = 0};
+ lc3_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(lc3_config));
+ return lc3_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::LC3);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::LC3) {
+ return lc3_codec_specifics;
+ }
+ // parse the capability
+ auto& lc3_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::lc3Capabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (auto channel_mode : lc3_capability.channelMode) {
+ Lc3Configuration lc3_data{.samplingFrequencyHz = samplingFrequencyHz,
+ .channelMode = channel_mode,
+ .frameDurationUs = frameDurationUs};
+ lc3_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(lc3_data));
+ }
+ }
+ }
+ return lc3_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(BluetoothAudioProviderA2dpHardwareAidl, OpenA2dpHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpSbcHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::SBC,
+ .encodedAudioBitrate = 328000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : sbc_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_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(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpAacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::AAC,
+ .encodedAudioBitrate = 320000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : aac_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_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(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpLdacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::LDAC,
+ .encodedAudioBitrate = 990000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : ldac_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_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(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpLc3HardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::LC3,
+ .encodedAudioBitrate = 990000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : lc3_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_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(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpAptxHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+ CodecConfiguration codec_config = {
+ .codecType = codec_type,
+ .encodedAudioBitrate =
+ (codec_type == CodecType::APTX ? 352000 : 576000),
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+
+ auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
+ (codec_type == CodecType::APTX_HD ? true : false), true);
+
+ for (auto& codec_specific : aptx_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_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(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+ ASSERT_NE(audio_provider_, nullptr);
+
+ std::vector<CodecConfiguration::CodecSpecific> 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::LC3:
+ codec_specifics = GetLc3CodecSpecificSupportedList(false);
+ continue;
+ case CodecType::APTX_ADAPTIVE:
+ case CodecType::VENDOR:
+ case CodecType::UNKNOWN:
+ codec_specifics.clear();
+ break;
+ }
+ if (codec_specifics.empty()) {
+ continue;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = codec_type,
+ .encodedAudioBitrate = 328000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ for (auto codec_specific : codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::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;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
+ static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode hearing_aid_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+ OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+ StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+ for (int32_t sample_rate : hearing_aid_sample_rates_) {
+ for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
+ for (auto channel_mode : hearing_aid_channel_modes_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ };
+ bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_output_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000,
+ };
+ static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_output_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+ OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_input_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000};
+ static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_input_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_input_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ OpenLeAudioInputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_input_sample_rates_) {
+ for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
+ for (auto channel_mode : le_audio_input_channel_modes_) {
+ for (auto data_interval_us : le_audio_input_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsOffloadOutputSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.unicastEncodeCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
+ bool supported) {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+ le_audio_codec_configs.push_back(lc3_config);
+ return le_audio_codec_configs;
+ }
+
+ // There might be more than one LeAudioCodecCapabilitiesSetting
+ std::vector<Lc3Capabilities> lc3_capabilities;
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ auto& unicast_capability =
+ decoding ? le_audio_capability.unicastDecodeCapability
+ : le_audio_capability.unicastEncodeCapability;
+ if (unicast_capability.codecType != CodecType::LC3) {
+ continue;
+ }
+ auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
+ UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+ lc3_capabilities.push_back(lc3_capability);
+ }
+
+ // Combine those parameters into one list of LeAudioCodecConfiguration
+ // This seems horrible, but usually each Lc3Capability only contains a
+ // single Lc3Configuration, which means every array has a length of 1.
+ for (auto& lc3_capability : lc3_capabilities) {
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
+ LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
+ if (!IsOffloadOutputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
+ if (!IsOffloadOutputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputHardwareAidl
+ : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ bool IsOffloadInputSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.unicastDecodeCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ OpenLeAudioInputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
+ if (!IsOffloadInputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
+ if (!IsOffloadInputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_output_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000,
+ };
+ static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_output_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsBroadcastOffloadSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.broadcastCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+ le_audio_codec_configs.push_back(lc3_config);
+ return le_audio_codec_configs;
+ }
+
+ // There might be more than one LeAudioCodecCapabilitiesSetting
+ std::vector<Lc3Capabilities> lc3_capabilities;
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ auto& broadcast_capability = le_audio_capability.broadcastCapability;
+ if (broadcast_capability.codecType != CodecType::LC3) {
+ continue;
+ }
+ auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
+ BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+ for (int idx = 0; idx < lc3_capability->size(); idx++)
+ lc3_capabilities.push_back(*lc3_capability->at(idx));
+ }
+
+ // Combine those parameters into one list of LeAudioCodecConfiguration
+ // This seems horrible, but usually each Lc3Capability only contains a
+ // single Lc3Configuration, which means every array has a length of 1.
+ for (auto& lc3_capability : lc3_capabilities) {
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
+ LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with broadcast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
+ if (!IsBroadcastOffloadSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
+ LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+ .codecType = CodecType::LC3,
+ .streamMap = {},
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_broadcast_config.streamMap[0]
+ .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+ lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_broadcast_config),
+ latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with Broadcast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
+ if (!IsBroadcastOffloadSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
+ LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+ .codecType = CodecType::LC3,
+ .streamMap = {},
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_broadcast_config.streamMap[0]
+ .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+ lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_broadcast_config),
+ latency_modes, &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderFactoryAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderHearingAidSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderHearingAidSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioOutputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioInputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioOutputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioInputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioInputHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 19d2d92..42f9455 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -14,22 +14,44 @@
srcs: [
"session/BluetoothAudioSession.cpp",
"session/BluetoothAudioSession_2_1.cpp",
- "session/BluetoothAudioSession_2_2.cpp",
"session/BluetoothAudioSupportedCodecsDB.cpp",
"session/BluetoothAudioSupportedCodecsDB_2_1.cpp",
- "session/BluetoothAudioSupportedCodecsDB_2_2.cpp",
],
export_include_dirs: ["session/"],
header_libs: ["libhardware_headers"],
shared_libs: [
+ "android.hardware.audio.common@5.0",
"android.hardware.bluetooth.audio@2.0",
"android.hardware.bluetooth.audio@2.1",
- "android.hardware.bluetooth.audio@2.2",
"libbase",
"libcutils",
"libfmq",
"libhidlbase",
"liblog",
"libutils",
+ "libbluetooth_audio_session_aidl",
+ ],
+}
+
+cc_library_shared {
+ name: "libbluetooth_audio_session_aidl",
+ vendor: true,
+ srcs: [
+ "aidl_session/BluetoothAudioCodecs.cpp",
+ "aidl_session/BluetoothAudioSession.cpp",
+ "aidl_session/HidlToAidlMiddleware.cpp",
+ ],
+ export_include_dirs: ["aidl_session/"],
+ header_libs: ["libhardware_headers"],
+ shared_libs: [
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "libbase",
+ "libcutils",
+ "libbinder_ndk",
+ "libfmq",
+ "liblog",
+ "android.hardware.bluetooth.audio-V1-ndk",
+ "libhidlbase",
],
}
diff --git a/bluetooth/audio/utils/OWNERS b/bluetooth/audio/utils/OWNERS
deleted file mode 100644
index ed92847..0000000
--- a/bluetooth/audio/utils/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/packages/modules/Bluetooth:/OWNERS
-
-cheneyni@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
new file mode 100644
index 0000000..8fd1ab5
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioCodecsAidl"
+
+#include "BluetoothAudioCodecs.h"
+
+#include <aidl/android/hardware/bluetooth/audio/AacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/AacObjectType.h>
+#include <aidl/android/hardware/bluetooth/audio/AptxCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/ChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
+ .sampleRateHz = {16000, 24000, 44100, 48000, 88200, 96000},
+ .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+ .bitsPerSample = {16, 24, 32},
+ .dataIntervalUs = {},
+};
+
+static const SbcCapabilities kDefaultOffloadSbcCapability = {
+ .sampleRateHz = {44100},
+ .channelMode = {SbcChannelMode::MONO, SbcChannelMode::JOINT_STEREO},
+ .blockLength = {4, 8, 12, 16},
+ .numSubbands = {8},
+ .allocMethod = {SbcAllocMethod::ALLOC_MD_L},
+ .bitsPerSample = {16},
+ .minBitpool = 2,
+ .maxBitpool = 53};
+
+static const AacCapabilities kDefaultOffloadAacCapability = {
+ .objectType = {AacObjectType::MPEG2_LC},
+ .sampleRateHz = {44100},
+ .channelMode = {ChannelMode::STEREO},
+ .variableBitRateSupported = true,
+ .bitsPerSample = {16}};
+
+static const LdacCapabilities kDefaultOffloadLdacCapability = {
+ .sampleRateHz = {44100, 48000, 88200, 96000},
+ .channelMode = {LdacChannelMode::DUAL, LdacChannelMode::STEREO},
+ .qualityIndex = {LdacQualityIndex::HIGH},
+ .bitsPerSample = {16, 24, 32}};
+
+static const AptxCapabilities kDefaultOffloadAptxCapability = {
+ .sampleRateHz = {44100, 48000},
+ .channelMode = {ChannelMode::STEREO},
+ .bitsPerSample = {16},
+};
+
+static const AptxCapabilities kDefaultOffloadAptxHdCapability = {
+ .sampleRateHz = {44100, 48000},
+ .channelMode = {ChannelMode::STEREO},
+ .bitsPerSample = {24},
+};
+
+static const Lc3Capabilities kDefaultA2dpOffloadLc3Capability = {
+ .samplingFrequencyHz = {44100, 48000},
+ .frameDurationUs = {7500, 10000},
+ .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+};
+
+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 = {}},
+ {.codecType = CodecType::LC3, .capabilities = {}}};
+
+std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
+
+static const UnicastCapability kInvalidUnicastCapability = {
+ .codecType = CodecType::UNKNOWN};
+
+static const BroadcastCapability kInvalidBroadcastCapability = {
+ .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Capabilities kLc3Capability_16_1 = {
+ .samplingFrequencyHz = {16000},
+ .frameDurationUs = {7500},
+ .octetsPerFrame = {30}};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Capabilities kLc3Capability_16_2 = {
+ .samplingFrequencyHz = {16000},
+ .frameDurationUs = {10000},
+ .octetsPerFrame = {40}};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Capabilities kLc3Capability_48_4 = {
+ .samplingFrequencyHz = {48000},
+ .frameDurationUs = {10000},
+ .octetsPerFrame = {120}};
+
+static const std::vector<Lc3Capabilities> supportedLc3CapabilityList = {
+ kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+ static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
+ static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+ supportedDeviceSetting = {
+ // Stereo, two connected device, one for L one for R
+ std::make_tuple(stereoAudio, 2, 1),
+ // Stereo, one connected device for both L and R
+ std::make_tuple(stereoAudio, 1, 2),
+ // Mono
+ std::make_tuple(monoAudio, 1, 1)};
+
+template <class T>
+bool BluetoothAudioCodecs::ContainedInVector(
+ const std::vector<T>& vector, const typename identity<T>::type& target) {
+ return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+bool BluetoothAudioCodecs::IsOffloadSbcConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::sbcConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const SbcConfiguration sbc_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::sbcConfig>();
+
+ if (ContainedInVector(kDefaultOffloadSbcCapability.sampleRateHz,
+ sbc_data.sampleRateHz) &&
+ ContainedInVector(kDefaultOffloadSbcCapability.blockLength,
+ sbc_data.blockLength) &&
+ ContainedInVector(kDefaultOffloadSbcCapability.numSubbands,
+ sbc_data.numSubbands) &&
+ ContainedInVector(kDefaultOffloadSbcCapability.bitsPerSample,
+ sbc_data.bitsPerSample) &&
+ ContainedInVector(kDefaultOffloadSbcCapability.channelMode,
+ sbc_data.channelMode) &&
+ ContainedInVector(kDefaultOffloadSbcCapability.allocMethod,
+ sbc_data.allocMethod) &&
+ sbc_data.minBitpool <= sbc_data.maxBitpool &&
+ kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
+ kDefaultOffloadSbcCapability.maxBitpool >= sbc_data.maxBitpool) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::aacConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const AacConfiguration aac_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::aacConfig>();
+
+ if (ContainedInVector(kDefaultOffloadAacCapability.sampleRateHz,
+ aac_data.sampleRateHz) &&
+ ContainedInVector(kDefaultOffloadAacCapability.bitsPerSample,
+ aac_data.bitsPerSample) &&
+ ContainedInVector(kDefaultOffloadAacCapability.channelMode,
+ aac_data.channelMode) &&
+ ContainedInVector(kDefaultOffloadAacCapability.objectType,
+ aac_data.objectType) &&
+ (!aac_data.variableBitRateEnabled ||
+ kDefaultOffloadAacCapability.variableBitRateSupported)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLdacConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() !=
+ CodecConfiguration::CodecSpecific::ldacConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const LdacConfiguration ldac_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::ldacConfig>();
+
+ if (ContainedInVector(kDefaultOffloadLdacCapability.sampleRateHz,
+ ldac_data.sampleRateHz) &&
+ ContainedInVector(kDefaultOffloadLdacCapability.bitsPerSample,
+ ldac_data.bitsPerSample) &&
+ ContainedInVector(kDefaultOffloadLdacCapability.channelMode,
+ ldac_data.channelMode) &&
+ ContainedInVector(kDefaultOffloadLdacCapability.qualityIndex,
+ ldac_data.qualityIndex)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() !=
+ CodecConfiguration::CodecSpecific::aptxConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const AptxConfiguration aptx_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+ if (ContainedInVector(kDefaultOffloadAptxCapability.sampleRateHz,
+ aptx_data.sampleRateHz) &&
+ ContainedInVector(kDefaultOffloadAptxCapability.bitsPerSample,
+ aptx_data.bitsPerSample) &&
+ ContainedInVector(kDefaultOffloadAptxCapability.channelMode,
+ aptx_data.channelMode)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxHdConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() !=
+ CodecConfiguration::CodecSpecific::aptxConfig) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const AptxConfiguration aptx_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+ if (ContainedInVector(kDefaultOffloadAptxHdCapability.sampleRateHz,
+ aptx_data.sampleRateHz) &&
+ ContainedInVector(kDefaultOffloadAptxHdCapability.bitsPerSample,
+ aptx_data.bitsPerSample) &&
+ ContainedInVector(kDefaultOffloadAptxHdCapability.channelMode,
+ aptx_data.channelMode)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLc3ConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific) {
+ if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::lc3Config) {
+ LOG(WARNING) << __func__
+ << ": Invalid CodecSpecific=" << codec_specific.toString();
+ return false;
+ }
+ const Lc3Configuration lc3_data =
+ codec_specific.get<CodecConfiguration::CodecSpecific::lc3Config>();
+
+ if (ContainedInVector(kDefaultA2dpOffloadLc3Capability.samplingFrequencyHz,
+ lc3_data.samplingFrequencyHz) &&
+ ContainedInVector(kDefaultA2dpOffloadLc3Capability.frameDurationUs,
+ lc3_data.frameDurationUs) &&
+ ContainedInVector(kDefaultA2dpOffloadLc3Capability.channelMode,
+ lc3_data.channelMode)) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << codec_specific.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+ const SessionType& session_type, const LeAudioConfiguration&) {
+ if (session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return false;
+ }
+ return true;
+}
+
+std::vector<PcmCapabilities>
+BluetoothAudioCodecs::GetSoftwarePcmCapabilities() {
+ return {kDefaultSoftwarePcmCapabilities};
+}
+
+std::vector<CodecCapabilities>
+BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
+ const SessionType& session_type) {
+ if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return {};
+ }
+ 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
+ .set<CodecCapabilities::Capabilities::sbcCapabilities>(
+ kDefaultOffloadSbcCapability);
+ break;
+ case CodecType::AAC:
+ codec_capability.capabilities
+ .set<CodecCapabilities::Capabilities::aacCapabilities>(
+ kDefaultOffloadAacCapability);
+ break;
+ case CodecType::LDAC:
+ codec_capability.capabilities
+ .set<CodecCapabilities::Capabilities::ldacCapabilities>(
+ kDefaultOffloadLdacCapability);
+ break;
+ case CodecType::APTX:
+ codec_capability.capabilities
+ .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+ kDefaultOffloadAptxCapability);
+ break;
+ case CodecType::APTX_HD:
+ codec_capability.capabilities
+ .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+ kDefaultOffloadAptxHdCapability);
+ break;
+ case CodecType::LC3:
+ codec_capability.capabilities
+ .set<CodecCapabilities::Capabilities::lc3Capabilities>(
+ kDefaultA2dpOffloadLc3Capability);
+ break;
+ case CodecType::UNKNOWN:
+ case CodecType::VENDOR:
+ case CodecType::APTX_ADAPTIVE:
+ break;
+ }
+ }
+ return offload_a2dp_codec_capabilities;
+}
+
+bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(
+ const PcmConfiguration& pcm_config) {
+ if (ContainedInVector(kDefaultSoftwarePcmCapabilities.sampleRateHz,
+ pcm_config.sampleRateHz) &&
+ ContainedInVector(kDefaultSoftwarePcmCapabilities.bitsPerSample,
+ pcm_config.bitsPerSample) &&
+ ContainedInVector(kDefaultSoftwarePcmCapabilities.channelMode,
+ pcm_config.channelMode)
+ // data interval is not checked for now
+ // && pcm_config.dataIntervalUs != 0
+ ) {
+ return true;
+ }
+ LOG(WARNING) << __func__
+ << ": Unsupported CodecSpecific=" << pcm_config.toString();
+ return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+ const SessionType& session_type, const CodecConfiguration& codec_config) {
+ if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ LOG(ERROR) << __func__
+ << ": Invalid SessionType=" << toString(session_type);
+ return false;
+ }
+ const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
+ switch (codec_config.codecType) {
+ case CodecType::SBC:
+ if (IsOffloadSbcConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::AAC:
+ if (IsOffloadAacConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::LDAC:
+ if (IsOffloadLdacConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::APTX:
+ if (IsOffloadAptxConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::APTX_HD:
+ if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::LC3:
+ if (IsOffloadLc3ConfigurationValid(codec_specific)) {
+ return true;
+ }
+ break;
+ case CodecType::APTX_ADAPTIVE:
+ case CodecType::UNKNOWN:
+ case CodecType::VENDOR:
+ break;
+ }
+ return false;
+}
+
+UnicastCapability composeUnicastLc3Capability(
+ AudioLocation audioLocation, uint8_t deviceCnt, uint8_t channelCount,
+ const Lc3Capabilities& capability) {
+ return {
+ .codecType = CodecType::LC3,
+ .supportedChannel = audioLocation,
+ .deviceCount = deviceCnt,
+ .channelCountPerDevice = channelCount,
+ .leAudioCodecCapabilities =
+ UnicastCapability::LeAudioCodecCapabilities(capability),
+ };
+}
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
+ const SessionType& session_type) {
+ if (session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return std::vector<LeAudioCodecCapabilitiesSetting>(0);
+ }
+
+ if (kDefaultOffloadLeAudioCapabilities.empty()) {
+ for (auto [audioLocation, deviceCnt, channelCount] :
+ supportedDeviceSetting) {
+ for (auto capability : supportedLc3CapabilityList) {
+ UnicastCapability lc3Capability = composeUnicastLc3Capability(
+ audioLocation, deviceCnt, channelCount, capability);
+ UnicastCapability lc3MonoDecodeCapability =
+ composeUnicastLc3Capability(monoAudio, 1, 1, capability);
+
+ // Adds the capability for encode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.unicastEncodeCapability = lc3Capability,
+ .unicastDecodeCapability = kInvalidUnicastCapability,
+ .broadcastCapability = kInvalidBroadcastCapability});
+
+ // Adds the capability for decode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.unicastEncodeCapability = kInvalidUnicastCapability,
+ .unicastDecodeCapability = lc3Capability,
+ .broadcastCapability = kInvalidBroadcastCapability});
+
+ // Adds the capability for the case that encode and decode exist at the
+ // same time
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.unicastEncodeCapability = lc3Capability,
+ .unicastDecodeCapability = lc3MonoDecodeCapability,
+ .broadcastCapability = kInvalidBroadcastCapability});
+ }
+ }
+ }
+
+ return kDefaultOffloadLeAudioCapabilities;
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
new file mode 100644
index 0000000..0259a7e
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/Lc3Configuration.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioCodecs {
+ public:
+ static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities();
+ static std::vector<CodecCapabilities> GetA2dpOffloadCodecCapabilities(
+ const SessionType& session_type);
+
+ static bool IsSoftwarePcmConfigurationValid(
+ const PcmConfiguration& pcm_config);
+ static bool IsOffloadCodecConfigurationValid(
+ const SessionType& session_type, const CodecConfiguration& codec_config);
+
+ static bool IsOffloadLeAudioConfigurationValid(
+ const SessionType& session_type, const LeAudioConfiguration&);
+
+ static std::vector<LeAudioCodecCapabilitiesSetting>
+ GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
+
+ private:
+ template <typename T>
+ struct identity {
+ typedef T type;
+ };
+ template <class T>
+ static bool ContainedInVector(const std::vector<T>& vector,
+ const typename identity<T>::type& target);
+ template <class T>
+ static bool ContainedInBitmask(const T& bitmask, const T& target);
+ static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield);
+ 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 IsOffloadLc3ConfigurationValid(
+ const CodecConfiguration::CodecSpecific& codec_specific);
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
new file mode 100644
index 0000000..37ac967
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#define LOG_TAG "BTAudioSessionAidl"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_manager.h>
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+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
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+ : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
+
+/***
+ *
+ * Callback methods
+ *
+ ***/
+
+void BluetoothAudioSession::OnSessionStarted(
+ const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+ const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes) {
+ 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=" << audio_config.toString()
+ << " Invalid";
+ } else if (!UpdateDataPath(mq_desc)) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+ << " MqDescriptor Invalid";
+ audio_config_ = nullptr;
+ } else {
+ stack_iface_ = stack_iface;
+ latency_modes_ = latency_modes;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", AudioConfiguration=" << audio_config.toString();
+ ReportSessionStatus();
+ }
+}
+
+void BluetoothAudioSession::OnSessionEnded() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ bool toggled = IsSessionReady();
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+ audio_config_ = nullptr;
+ stack_iface_ = nullptr;
+ UpdateDataPath(nullptr);
+ if (toggled) {
+ ReportSessionStatus();
+ }
+}
+
+/***
+ *
+ * Util methods
+ *
+ ***/
+
+const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ switch (session_type_) {
+ case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ return AudioConfiguration(CodecConfiguration{});
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ return AudioConfiguration(LeAudioConfiguration{});
+ case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ return AudioConfiguration(LeAudioBroadcastConfiguration{});
+ default:
+ return AudioConfiguration(PcmConfiguration{});
+ }
+ }
+ return *audio_config_;
+}
+
+void BluetoothAudioSession::ReportAudioConfigChanged(
+ const AudioConfiguration& audio_config) {
+ if (session_type_ !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_ !=
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return;
+ }
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+ 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__ << " for SessionType=" << toString(session_type_)
+ << ", bluetooth_audio=0x"
+ << ::android::base::StringPrintf("%04x", cookie);
+ if (cb->audio_configuration_changed_cb_ != nullptr) {
+ cb->audio_configuration_changed_cb_(cookie);
+ }
+ }
+}
+
+bool BluetoothAudioSession::IsSessionReady() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+
+ bool is_mq_valid =
+ (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ (data_mq_ != nullptr && data_mq_->isValid()));
+ return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
+}
+
+/***
+ *
+ * Status callback methods
+ *
+ ***/
+
+uint16_t BluetoothAudioSession::RegisterStatusCback(
+ const PortStatusCallbacks& callbacks) {
+ 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<PortStatusCallbacks> cb =
+ std::make_shared<PortStatusCallbacks>();
+ *cb = callbacks;
+ observers_[cookie] = cb;
+ return cookie;
+}
+
+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);
+ }
+}
+
+/***
+ *
+ * Stream methods
+ *
+ ***/
+
+bool BluetoothAudioSession::StartStream(bool is_low_latency) {
+ 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(is_low_latency);
+ 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";
+ }
+}
+
+/***
+ *
+ * Private methods
+ *
+ ***/
+
+bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
+ if (mq_desc == nullptr) {
+ // usecase of reset by nullptr
+ data_mq_ = nullptr;
+ return true;
+ }
+ std::unique_ptr<DataMQ> temp_mq;
+ temp_mq.reset(new DataMQ(*mq_desc));
+ if (!temp_mq || !temp_mq->isValid()) {
+ data_mq_ = nullptr;
+ return false;
+ }
+ data_mq_ = std::move(temp_mq);
+ 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_DECODING_DATAPATH ||
+ session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+ bool is_offload_a2dp_session =
+ (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ bool is_offload_le_audio_session =
+ (session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ auto audio_config_tag = audio_config.getTag();
+ bool is_software_audio_config =
+ (is_software_session &&
+ audio_config_tag == AudioConfiguration::pcmConfig);
+ bool is_a2dp_offload_audio_config =
+ (is_offload_a2dp_session &&
+ audio_config_tag == AudioConfiguration::a2dpConfig);
+ bool is_le_audio_offload_audio_config =
+ (is_offload_le_audio_session &&
+ audio_config_tag == AudioConfiguration::leAudioConfig);
+ if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
+ !is_le_audio_offload_audio_config) {
+ return false;
+ }
+ audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+ return true;
+}
+
+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<PortStatusCallbacks> callback = observer.second;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " notify to bluetooth_audio=0x"
+ << ::android::base::StringPrintf("%04x", cookie);
+ callback->session_changed_cb_(cookie);
+ }
+}
+
+/***
+ *
+ * PCM methods
+ *
+ ***/
+
+size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
+ size_t bytes) {
+ if (buffer == nullptr || bytes <= 0) {
+ return 0;
+ }
+ size_t total_written = 0;
+ int timeout_ms = kFmqSendTimeoutMs;
+ do {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ if (!IsSessionReady()) {
+ break;
+ }
+ size_t num_bytes_to_write = data_mq_->availableToWrite();
+ if (num_bytes_to_write) {
+ if (num_bytes_to_write > (bytes - total_written)) {
+ num_bytes_to_write = bytes - total_written;
+ }
+
+ if (!data_mq_->write(
+ static_cast<const MQDataType*>(buffer) + total_written,
+ num_bytes_to_write)) {
+ LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
+ << " failed";
+ return total_written;
+ }
+ total_written += num_bytes_to_write;
+ } else if (timeout_ms >= kWritePollMs) {
+ lock.unlock();
+ usleep(kWritePollMs * 1000);
+ timeout_ms -= kWritePollMs;
+ } else {
+ LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
+ << (kFmqSendTimeoutMs - timeout_ms) << " ms";
+ return total_written;
+ }
+ } while (total_written < bytes);
+ return total_written;
+}
+
+size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+ if (buffer == nullptr || bytes <= 0) {
+ return 0;
+ }
+ size_t total_read = 0;
+ int timeout_ms = kFmqReceiveTimeoutMs;
+ do {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ if (!IsSessionReady()) {
+ break;
+ }
+ size_t num_bytes_to_read = data_mq_->availableToRead();
+ if (num_bytes_to_read) {
+ if (num_bytes_to_read > (bytes - total_read)) {
+ num_bytes_to_read = bytes - total_read;
+ }
+ if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
+ num_bytes_to_read)) {
+ LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
+ << " failed";
+ return total_read;
+ }
+ total_read += num_bytes_to_read;
+ } else if (timeout_ms >= kReadPollMs) {
+ lock.unlock();
+ usleep(kReadPollMs * 1000);
+ timeout_ms -= kReadPollMs;
+ continue;
+ } else {
+ LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
+ << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
+ return total_read;
+ }
+ } while (total_read < bytes);
+ return total_read;
+}
+
+/***
+ *
+ * Other methods
+ *
+ ***/
+
+void BluetoothAudioSession::ReportControlStatus(bool start_resp,
+ 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<PortStatusCallbacks> callback = 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");
+ callback->control_result_cb_(cookie, start_resp, status);
+ }
+}
+
+void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ low_latency_allowed_ = allowed;
+ 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<PortStatusCallbacks> callback = observer.second;
+ LOG(INFO) << __func__
+ << " - allowed=" << (allowed ? " allowed" : " disallowed");
+ callback->low_latency_mode_allowed_cb_(cookie, allowed);
+ }
+}
+
+bool BluetoothAudioSession::GetPresentationPosition(
+ PresentationPosition& presentation_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;
+
+ if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ return false;
+ }
+ return retval;
+}
+
+void BluetoothAudioSession::UpdateSourceMetadata(
+ 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_ENCODING_DATAPATH) {
+ return;
+ }
+
+ SourceMetadata hal_source_metadata;
+ hal_source_metadata.tracks.resize(track_count);
+ for (int i = 0; i < track_count; i++) {
+ hal_source_metadata.tracks[i].usage =
+ static_cast<media::audio::common::AudioUsage>(
+ source_metadata.tracks[i].usage);
+ hal_source_metadata.tracks[i].contentType =
+ static_cast<media::audio::common::AudioContentType>(
+ source_metadata.tracks[i].content_type);
+ hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
+ LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
+ << ", content="
+ << toString(hal_source_metadata.tracks[i].contentType)
+ << ", gain=" << hal_source_metadata.tracks[i].gain;
+ }
+
+ auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ }
+}
+
+void BluetoothAudioSession::UpdateSinkMetadata(
+ const struct sink_metadata& sink_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 = sink_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_ENCODING_DATAPATH) {
+ return;
+ }
+
+ SinkMetadata hal_sink_metadata;
+ hal_sink_metadata.tracks.resize(track_count);
+ for (int i = 0; i < track_count; i++) {
+ hal_sink_metadata.tracks[i].source =
+ static_cast<media::audio::common::AudioSource>(
+ sink_metadata.tracks[i].source);
+ hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << ", source=" << sink_metadata.tracks[i].source
+ << ", dest_device=" << sink_metadata.tracks[i].dest_device
+ << ", gain=" << sink_metadata.tracks[i].gain
+ << ", dest_device_address="
+ << sink_metadata.tracks[i].dest_device_address;
+ }
+
+ auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ }
+}
+
+std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return std::vector<LatencyMode>();
+ }
+ if (low_latency_allowed_) return latency_modes_;
+ std::vector<LatencyMode> modes;
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY)
+ // ignore those low latency mode if Bluetooth stack doesn't allow
+ continue;
+ modes.push_back(mode);
+ }
+ return modes;
+}
+
+void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return;
+ }
+
+ auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ }
+}
+
+bool BluetoothAudioSession::IsAidlAvailable() {
+ if (is_aidl_checked) return is_aidl_available;
+ is_aidl_available =
+ (AServiceManager_checkService(
+ kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
+ is_aidl_checked = true;
+ return is_aidl_available;
+}
+
+/***
+ *
+ * BluetoothAudioSessionInstance
+ *
+ ***/
+std::mutex BluetoothAudioSessionInstance::mutex_;
+std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+ BluetoothAudioSessionInstance::sessions_map_;
+
+std::shared_ptr<BluetoothAudioSession>
+BluetoothAudioSessionInstance::GetSessionInstance(
+ const SessionType& session_type) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ if (!sessions_map_.empty()) {
+ auto entry = sessions_map_.find(session_type);
+ if (entry != sessions_map_.end()) {
+ return entry->second;
+ }
+ }
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ std::make_shared<BluetoothAudioSession>(session_type);
+ sessions_map_[session_type] = session_ptr;
+ return session_ptr;
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
new file mode 100644
index 0000000..5bf17bd
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/audio.h>
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+
+using MQDataType = int8_t;
+using MQDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MQDataType, MQDataMode>;
+using DataMQDesc =
+ ::aidl::android::hardware::common::fmq::MQDescriptor<MQDataType,
+ MQDataMode>;
+
+static constexpr uint16_t kObserversCookieSize = 0x0010; // 0x0000 ~ 0x000f
+static 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,
+ 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_;
+ /***
+ * audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
+ * configuration, 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)> audio_configuration_changed_cb_;
+ /***
+ * low_latency_mode_allowed_cb_ - when the Bluetooth stack low latency mode
+ * allowed or disallowed, the BluetoothAudioProvider will invoke
+ * this callback to report to the bluetooth_audio module.
+ * @param: cookie - indicates which bluetooth_audio output should handle
+ * @param: allowed - indicates if low latency mode is allowed
+ ***/
+ std::function<void(uint16_t cookie, bool allowed)>
+ low_latency_mode_allowed_cb_;
+};
+
+class BluetoothAudioSession {
+ 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 std::shared_ptr<IBluetoothAudioPort> stack_iface,
+ const DataMQDesc* mq_desc,
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes);
+
+ /***
+ * 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, 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();
+
+ /***
+ * The report function is used to report that the Bluetooth stack has notified
+ * the audio configuration changed, and will invoke
+ * audio_configuration_changed_cb_ to notify registered bluetooth_audio
+ * outputs
+ ***/
+ void ReportAudioConfigChanged(const AudioConfiguration& audio_config);
+
+ /***
+ * The report function is used to report that the Bluetooth stack has notified
+ * the low latency mode allowed changed, and will invoke
+ * low_latency_mode_allowed_changed_cb to notify registered bluetooth_audio
+ * outputs
+ ***/
+ void ReportLowLatencyModeAllowedChanged(bool allowed);
+ /***
+ * Those control functions are for the bluetooth_audio module to start,
+ * suspend, stop stream, to check position, and to update metadata.
+ ***/
+ bool StartStream(bool low_latency);
+ bool SuspendStream();
+ void StopStream();
+ bool GetPresentationPosition(PresentationPosition& presentation_position);
+ void UpdateSourceMetadata(const struct source_metadata& source_metadata);
+ void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
+
+ std::vector<LatencyMode> GetSupportedLatencyModes();
+ void SetLatencyMode(const LatencyMode& latency_mode);
+
+ // 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);
+
+ // Return if IBluetoothAudioProviderFactory implementation existed
+ static bool IsAidlAvailable();
+
+ 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
+ std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+ // audio data path (FMQ) for software encoding
+ std::unique_ptr<DataMQ> data_mq_;
+ // audio data configuration for both software and offloading
+ std::unique_ptr<AudioConfiguration> audio_config_;
+ std::vector<LatencyMode> latency_modes_;
+ bool low_latency_allowed_ = true;
+
+ // saving those registered bluetooth_audio's callbacks
+ std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
+ observers_;
+
+ bool UpdateDataPath(const DataMQDesc* mq_desc);
+ bool UpdateAudioConfig(const AudioConfiguration& audio_config);
+ // invoking the registered session_changed_cb_
+ void ReportSessionStatus();
+
+ static inline std::atomic<bool> is_aidl_checked = false;
+ static inline std::atomic<bool> is_aidl_available = false;
+ static inline const std::string kDefaultAudioProviderFactoryInterface =
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
+};
+
+class BluetoothAudioSessionInstance {
+ public:
+ // The API is to fetch the specified session of A2DP / Hearing Aid
+ static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
+ const SessionType& session_type);
+
+ private:
+ static std::mutex mutex_;
+ static std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+ sessions_map_;
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..5b838b0
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+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();
+ }
+ switch (session_type) {
+ case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ return AudioConfiguration(CodecConfiguration{});
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ return AudioConfiguration(LeAudioConfiguration{});
+ case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ return AudioConfiguration(LeAudioBroadcastConfiguration{});
+ default:
+ return AudioConfiguration(PcmConfiguration{});
+ }
+ }
+
+ /***
+ * 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,
+ bool low_latency = false) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->StartStream(low_latency);
+ }
+ 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,
+ PresentationPosition& presentation_position) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->GetPresentationPosition(presentation_position);
+ }
+ return false;
+ }
+
+ static void UpdateSourceMetadata(
+ 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->UpdateSourceMetadata(source_metadata);
+ }
+ }
+
+ static void UpdateSinkMetadata(const SessionType& session_type,
+ const struct sink_metadata& sink_metadata) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->UpdateSinkMetadata(sink_metadata);
+ }
+ }
+
+ static std::vector<LatencyMode> GetSupportedLatencyModes(
+ const SessionType& session_type) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->GetSupportedLatencyModes();
+ }
+ return std::vector<LatencyMode>();
+ }
+
+ static void SetLatencyMode(const SessionType& session_type,
+ const LatencyMode& latency_mode) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->SetLatencyMode(latency_mode);
+ }
+ }
+
+ /***
+ * 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 hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..0350259
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionReport {
+ public:
+ /***
+ * The API reports the Bluetooth stack has started the session, and will
+ * inform registered bluetooth_audio outputs
+ ***/
+ static void OnSessionStarted(
+ const SessionType& session_type,
+ const std::shared_ptr<IBluetoothAudioPort> host_iface,
+ const DataMQDesc* data_mq, const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->OnSessionStarted(host_iface, data_mq, audio_config,
+ latency_modes);
+ }
+ }
+
+ /***
+ * 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,
+ BluetoothAudioStatus status) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->ReportControlStatus(start_resp, status);
+ }
+ }
+ /***
+ * The API reports the Bluetooth stack has replied the changed of the audio
+ * configuration, and will inform registered bluetooth_audio outputs
+ ***/
+ static void ReportAudioConfigChanged(const SessionType& session_type,
+ const AudioConfiguration& audio_config) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->ReportAudioConfigChanged(audio_config);
+ }
+ }
+ /***
+ * The API reports the Bluetooth stack has replied the changed of the low
+ * latency audio allowed, and will inform registered bluetooth_audio outputs
+ ***/
+ static void ReportLowLatencyModeAllowedChanged(
+ const SessionType& session_type, bool allowed) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->ReportLowLatencyModeAllowedChanged(allowed);
+ }
+ }
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
new file mode 100644
index 0000000..a4664f1
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BtAudioNakahara"
+
+#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <android-base/logging.h>
+
+#include <functional>
+#include <unordered_map>
+
+#include "../aidl_session/BluetoothAudioSession.h"
+#include "../aidl_session/BluetoothAudioSessionControl.h"
+#include "HidlToAidlMiddleware_2_0.h"
+#include "HidlToAidlMiddleware_2_1.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using HidlStatus = ::android::hardware::bluetooth::audio::V2_0::Status;
+using PcmConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using SampleRate_2_0 = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using ChannelMode_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using BitsPerSample_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using CodecConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using CodecType_2_0 = ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using SbcConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using AacConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using LdacConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using AptxConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using SbcAllocMethod_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using SbcBlockLength_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using SbcChannelMode_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using SbcNumSubbands_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using AacObjectType_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using AacVarBitRate_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using LdacChannelMode_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using LdacQualityIndex_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+
+using PcmConfig_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using Lc3CodecConfig_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration;
+using Lc3Config_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
+using Lc3FrameDuration_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+
+std::mutex legacy_callback_lock;
+std::unordered_map<
+ SessionType,
+ std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_0>>>
+ legacy_callback_table;
+
+const static std::unordered_map<SessionType_2_1, SessionType>
+ session_type_2_1_to_aidl_map{
+ {SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
+ {SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+ {SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
+ {SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH},
+ {SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH},
+ {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+ {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH},
+ };
+
+const static std::unordered_map<int32_t, SampleRate_2_1>
+ sample_rate_to_hidl_2_1_map{
+ {44100, SampleRate_2_1::RATE_44100},
+ {48000, SampleRate_2_1::RATE_48000},
+ {88200, SampleRate_2_1::RATE_88200},
+ {96000, SampleRate_2_1::RATE_96000},
+ {176400, SampleRate_2_1::RATE_176400},
+ {192000, SampleRate_2_1::RATE_192000},
+ {16000, SampleRate_2_1::RATE_16000},
+ {24000, SampleRate_2_1::RATE_24000},
+ {8000, SampleRate_2_1::RATE_8000},
+ {32000, SampleRate_2_1::RATE_32000},
+ };
+
+const static std::unordered_map<CodecType, CodecType_2_0>
+ codec_type_to_hidl_2_0_map{
+ {CodecType::UNKNOWN, CodecType_2_0::UNKNOWN},
+ {CodecType::SBC, CodecType_2_0::SBC},
+ {CodecType::AAC, CodecType_2_0::AAC},
+ {CodecType::APTX, CodecType_2_0::APTX},
+ {CodecType::APTX_HD, CodecType_2_0::APTX_HD},
+ {CodecType::LDAC, CodecType_2_0::LDAC},
+ {CodecType::LC3, CodecType_2_0::UNKNOWN},
+ };
+
+const static std::unordered_map<SbcChannelMode, SbcChannelMode_2_0>
+ sbc_channel_mode_to_hidl_2_0_map{
+ {SbcChannelMode::UNKNOWN, SbcChannelMode_2_0::UNKNOWN},
+ {SbcChannelMode::JOINT_STEREO, SbcChannelMode_2_0::JOINT_STEREO},
+ {SbcChannelMode::STEREO, SbcChannelMode_2_0::STEREO},
+ {SbcChannelMode::DUAL, SbcChannelMode_2_0::DUAL},
+ {SbcChannelMode::MONO, SbcChannelMode_2_0::MONO},
+ };
+
+const static std::unordered_map<int8_t, SbcBlockLength_2_0>
+ sbc_block_length_to_hidl_map{
+ {4, SbcBlockLength_2_0::BLOCKS_4},
+ {8, SbcBlockLength_2_0::BLOCKS_8},
+ {12, SbcBlockLength_2_0::BLOCKS_12},
+ {16, SbcBlockLength_2_0::BLOCKS_16},
+ };
+
+const static std::unordered_map<int8_t, SbcNumSubbands_2_0>
+ sbc_subbands_to_hidl_map{
+ {4, SbcNumSubbands_2_0::SUBBAND_4},
+ {8, SbcNumSubbands_2_0::SUBBAND_8},
+ };
+
+const static std::unordered_map<SbcAllocMethod, SbcAllocMethod_2_0>
+ sbc_alloc_method_to_hidl_map{
+ {SbcAllocMethod::ALLOC_MD_S, SbcAllocMethod_2_0::ALLOC_MD_S},
+ {SbcAllocMethod::ALLOC_MD_L, SbcAllocMethod_2_0::ALLOC_MD_L},
+ };
+
+const static std::unordered_map<AacObjectType, AacObjectType_2_0>
+ aac_object_type_to_hidl_map{
+ {AacObjectType::MPEG2_LC, AacObjectType_2_0::MPEG2_LC},
+ {AacObjectType::MPEG4_LC, AacObjectType_2_0::MPEG4_LC},
+ {AacObjectType::MPEG4_LTP, AacObjectType_2_0::MPEG4_LTP},
+ {AacObjectType::MPEG4_SCALABLE, AacObjectType_2_0::MPEG4_SCALABLE},
+ };
+
+const static std::unordered_map<LdacChannelMode, LdacChannelMode_2_0>
+ ldac_channel_mode_to_hidl_map{
+ {LdacChannelMode::UNKNOWN, LdacChannelMode_2_0::UNKNOWN},
+ {LdacChannelMode::STEREO, LdacChannelMode_2_0::STEREO},
+ {LdacChannelMode::DUAL, LdacChannelMode_2_0::DUAL},
+ {LdacChannelMode::MONO, LdacChannelMode_2_0::MONO},
+ };
+
+const static std::unordered_map<LdacQualityIndex, LdacQualityIndex_2_0>
+ ldac_qindex_to_hidl_map{
+ {LdacQualityIndex::HIGH, LdacQualityIndex_2_0::QUALITY_HIGH},
+ {LdacQualityIndex::MID, LdacQualityIndex_2_0::QUALITY_MID},
+ {LdacQualityIndex::LOW, LdacQualityIndex_2_0::QUALITY_LOW},
+ {LdacQualityIndex::ABR, LdacQualityIndex_2_0::QUALITY_ABR},
+ };
+
+inline SessionType from_session_type_2_1(
+ const SessionType_2_1& session_type_hidl) {
+ auto it = session_type_2_1_to_aidl_map.find(session_type_hidl);
+ if (it != session_type_2_1_to_aidl_map.end()) return it->second;
+ return SessionType::UNKNOWN;
+}
+
+inline SessionType from_session_type_2_0(
+ const SessionType_2_0& session_type_hidl) {
+ return from_session_type_2_1(static_cast<SessionType_2_1>(session_type_hidl));
+}
+
+inline HidlStatus to_hidl_status(const BluetoothAudioStatus& status) {
+ switch (status) {
+ case BluetoothAudioStatus::SUCCESS:
+ return HidlStatus::SUCCESS;
+ case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION:
+ return HidlStatus::UNSUPPORTED_CODEC_CONFIGURATION;
+ default:
+ return HidlStatus::FAILURE;
+ }
+}
+
+inline SampleRate_2_1 to_hidl_sample_rate_2_1(const int32_t sample_rate_hz) {
+ auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz);
+ if (it != sample_rate_to_hidl_2_1_map.end()) return it->second;
+ return SampleRate_2_1::RATE_UNKNOWN;
+}
+
+inline SampleRate_2_0 to_hidl_sample_rate_2_0(const int32_t sample_rate_hz) {
+ auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz);
+ if (it != sample_rate_to_hidl_2_1_map.end())
+ return static_cast<SampleRate_2_0>(it->second);
+ return SampleRate_2_0::RATE_UNKNOWN;
+}
+
+inline BitsPerSample_2_0 to_hidl_bits_per_sample(const int8_t bit_per_sample) {
+ switch (bit_per_sample) {
+ case 16:
+ return BitsPerSample_2_0::BITS_16;
+ case 24:
+ return BitsPerSample_2_0::BITS_24;
+ case 32:
+ return BitsPerSample_2_0::BITS_32;
+ default:
+ return BitsPerSample_2_0::BITS_UNKNOWN;
+ }
+}
+
+inline ChannelMode_2_0 to_hidl_channel_mode(const ChannelMode channel_mode) {
+ switch (channel_mode) {
+ case ChannelMode::MONO:
+ return ChannelMode_2_0::MONO;
+ case ChannelMode::STEREO:
+ return ChannelMode_2_0::STEREO;
+ default:
+ return ChannelMode_2_0::UNKNOWN;
+ }
+}
+
+inline PcmConfig_2_0 to_hidl_pcm_config_2_0(
+ const PcmConfiguration& pcm_config) {
+ PcmConfig_2_0 hidl_pcm_config;
+ hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_0(pcm_config.sampleRateHz);
+ hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+ hidl_pcm_config.bitsPerSample =
+ to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+ return hidl_pcm_config;
+}
+
+inline CodecType_2_0 to_hidl_codec_type_2_0(const CodecType codec_type) {
+ auto it = codec_type_to_hidl_2_0_map.find(codec_type);
+ if (it != codec_type_to_hidl_2_0_map.end()) return it->second;
+ return CodecType_2_0::UNKNOWN;
+}
+
+inline SbcConfig_2_0 to_hidl_sbc_config(const SbcConfiguration sbc_config) {
+ SbcConfig_2_0 hidl_sbc_config;
+ hidl_sbc_config.minBitpool = sbc_config.minBitpool;
+ hidl_sbc_config.maxBitpool = sbc_config.maxBitpool;
+ hidl_sbc_config.sampleRate = to_hidl_sample_rate_2_0(sbc_config.sampleRateHz);
+ hidl_sbc_config.bitsPerSample =
+ to_hidl_bits_per_sample(sbc_config.bitsPerSample);
+ if (sbc_channel_mode_to_hidl_2_0_map.find(sbc_config.channelMode) !=
+ sbc_channel_mode_to_hidl_2_0_map.end()) {
+ hidl_sbc_config.channelMode =
+ sbc_channel_mode_to_hidl_2_0_map.at(sbc_config.channelMode);
+ }
+ if (sbc_block_length_to_hidl_map.find(sbc_config.blockLength) !=
+ sbc_block_length_to_hidl_map.end()) {
+ hidl_sbc_config.blockLength =
+ sbc_block_length_to_hidl_map.at(sbc_config.blockLength);
+ }
+ if (sbc_subbands_to_hidl_map.find(sbc_config.numSubbands) !=
+ sbc_subbands_to_hidl_map.end()) {
+ hidl_sbc_config.numSubbands =
+ sbc_subbands_to_hidl_map.at(sbc_config.numSubbands);
+ }
+ if (sbc_alloc_method_to_hidl_map.find(sbc_config.allocMethod) !=
+ sbc_alloc_method_to_hidl_map.end()) {
+ hidl_sbc_config.allocMethod =
+ sbc_alloc_method_to_hidl_map.at(sbc_config.allocMethod);
+ }
+ return hidl_sbc_config;
+}
+
+inline AacConfig_2_0 to_hidl_aac_config(const AacConfiguration aac_config) {
+ AacConfig_2_0 hidl_aac_config;
+ hidl_aac_config.sampleRate = to_hidl_sample_rate_2_0(aac_config.sampleRateHz);
+ hidl_aac_config.bitsPerSample =
+ to_hidl_bits_per_sample(aac_config.bitsPerSample);
+ hidl_aac_config.channelMode = to_hidl_channel_mode(aac_config.channelMode);
+ if (aac_object_type_to_hidl_map.find(aac_config.objectType) !=
+ aac_object_type_to_hidl_map.end()) {
+ hidl_aac_config.objectType =
+ aac_object_type_to_hidl_map.at(aac_config.objectType);
+ }
+ hidl_aac_config.variableBitRateEnabled = aac_config.variableBitRateEnabled
+ ? AacVarBitRate_2_0::ENABLED
+ : AacVarBitRate_2_0::DISABLED;
+ return hidl_aac_config;
+}
+
+inline LdacConfig_2_0 to_hidl_ldac_config(const LdacConfiguration ldac_config) {
+ LdacConfig_2_0 hidl_ldac_config;
+ hidl_ldac_config.sampleRate =
+ to_hidl_sample_rate_2_0(ldac_config.sampleRateHz);
+ hidl_ldac_config.bitsPerSample =
+ to_hidl_bits_per_sample(ldac_config.bitsPerSample);
+ if (ldac_channel_mode_to_hidl_map.find(ldac_config.channelMode) !=
+ ldac_channel_mode_to_hidl_map.end()) {
+ hidl_ldac_config.channelMode =
+ ldac_channel_mode_to_hidl_map.at(ldac_config.channelMode);
+ }
+ if (ldac_qindex_to_hidl_map.find(ldac_config.qualityIndex) !=
+ ldac_qindex_to_hidl_map.end()) {
+ hidl_ldac_config.qualityIndex =
+ ldac_qindex_to_hidl_map.at(ldac_config.qualityIndex);
+ }
+ return hidl_ldac_config;
+}
+
+inline AptxConfig_2_0 to_hidl_aptx_config(const AptxConfiguration aptx_config) {
+ AptxConfig_2_0 hidl_aptx_config;
+ hidl_aptx_config.sampleRate =
+ to_hidl_sample_rate_2_0(aptx_config.sampleRateHz);
+ hidl_aptx_config.bitsPerSample =
+ to_hidl_bits_per_sample(aptx_config.bitsPerSample);
+ hidl_aptx_config.channelMode = to_hidl_channel_mode(aptx_config.channelMode);
+ return hidl_aptx_config;
+}
+
+inline CodecConfig_2_0 to_hidl_codec_config_2_0(
+ const CodecConfiguration& codec_config) {
+ CodecConfig_2_0 hidl_codec_config;
+ hidl_codec_config.codecType = to_hidl_codec_type_2_0(codec_config.codecType);
+ hidl_codec_config.encodedAudioBitrate =
+ static_cast<uint32_t>(codec_config.encodedAudioBitrate);
+ hidl_codec_config.peerMtu = static_cast<uint32_t>(codec_config.peerMtu);
+ hidl_codec_config.isScmstEnabled = codec_config.isScmstEnabled;
+ switch (codec_config.config.getTag()) {
+ case CodecConfiguration::CodecSpecific::sbcConfig:
+ hidl_codec_config.config.sbcConfig(to_hidl_sbc_config(
+ codec_config.config
+ .get<CodecConfiguration::CodecSpecific::sbcConfig>()));
+ break;
+ case CodecConfiguration::CodecSpecific::aacConfig:
+ hidl_codec_config.config.aacConfig(to_hidl_aac_config(
+ codec_config.config
+ .get<CodecConfiguration::CodecSpecific::aacConfig>()));
+ break;
+ case CodecConfiguration::CodecSpecific::ldacConfig:
+ hidl_codec_config.config.ldacConfig(to_hidl_ldac_config(
+ codec_config.config
+ .get<CodecConfiguration::CodecSpecific::ldacConfig>()));
+ break;
+ case CodecConfiguration::CodecSpecific::aptxConfig:
+ hidl_codec_config.config.aptxConfig(to_hidl_aptx_config(
+ codec_config.config
+ .get<CodecConfiguration::CodecSpecific::aptxConfig>()));
+ break;
+ default:
+ break;
+ }
+ return hidl_codec_config;
+}
+
+inline AudioConfig_2_0 to_hidl_audio_config_2_0(
+ const AudioConfiguration& audio_config) {
+ AudioConfig_2_0 hidl_audio_config;
+ if (audio_config.getTag() == AudioConfiguration::pcmConfig) {
+ hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_0(
+ audio_config.get<AudioConfiguration::pcmConfig>()));
+ } else if (audio_config.getTag() == AudioConfiguration::a2dpConfig) {
+ hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+ audio_config.get<AudioConfiguration::a2dpConfig>()));
+ }
+ return hidl_audio_config;
+}
+
+inline PcmConfig_2_1 to_hidl_pcm_config_2_1(
+ const PcmConfiguration& pcm_config) {
+ PcmConfig_2_1 hidl_pcm_config;
+ hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_1(pcm_config.sampleRateHz);
+ hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+ hidl_pcm_config.bitsPerSample =
+ to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+ hidl_pcm_config.dataIntervalUs =
+ static_cast<uint32_t>(pcm_config.dataIntervalUs);
+ return hidl_pcm_config;
+}
+
+inline Lc3Config_2_1 to_hidl_lc3_config_2_1(
+ const Lc3Configuration& lc3_config) {
+ Lc3Config_2_1 hidl_lc3_config;
+ hidl_lc3_config.pcmBitDepth = to_hidl_bits_per_sample(lc3_config.pcmBitDepth);
+ hidl_lc3_config.samplingFrequency =
+ to_hidl_sample_rate_2_1(lc3_config.samplingFrequencyHz);
+ if (lc3_config.samplingFrequencyHz == 10000)
+ hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_10000US;
+ else if (lc3_config.samplingFrequencyHz == 7500)
+ hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_7500US;
+ hidl_lc3_config.octetsPerFrame =
+ static_cast<uint32_t>(lc3_config.octetsPerFrame);
+ hidl_lc3_config.blocksPerSdu = static_cast<uint32_t>(lc3_config.blocksPerSdu);
+ return hidl_lc3_config;
+}
+
+inline Lc3CodecConfig_2_1 to_hidl_leaudio_config_2_1(
+ const LeAudioConfiguration& unicast_config) {
+ Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
+ .audioChannelAllocation = 0,
+ };
+ if (unicast_config.leAudioCodecConfig.getTag() ==
+ LeAudioCodecConfiguration::lc3Config) {
+ LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
+ }
+ auto& le_codec_config = unicast_config.leAudioCodecConfig
+ .get<LeAudioCodecConfiguration::lc3Config>();
+
+ hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+ for (const auto& map : unicast_config.streamMap) {
+ hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
+ }
+ return hidl_lc3_codec_config;
+}
+
+inline Lc3CodecConfig_2_1 to_hidl_leaudio_broadcast_config_2_1(
+ const LeAudioBroadcastConfiguration& broadcast_config) {
+ Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
+ .audioChannelAllocation = 0,
+ };
+ // NOTE: Broadcast is not officially supported in HIDL
+ if (broadcast_config.streamMap.empty()) {
+ return hidl_lc3_codec_config;
+ }
+ if (broadcast_config.streamMap[0].leAudioCodecConfig.getTag() !=
+ LeAudioCodecConfiguration::lc3Config) {
+ LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
+ }
+ auto& le_codec_config =
+ broadcast_config.streamMap[0]
+ .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>();
+ hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+ for (const auto& map : broadcast_config.streamMap) {
+ hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
+ }
+ return hidl_lc3_codec_config;
+}
+
+inline AudioConfig_2_1 to_hidl_audio_config_2_1(
+ const AudioConfiguration& audio_config) {
+ AudioConfig_2_1 hidl_audio_config;
+ switch (audio_config.getTag()) {
+ case AudioConfiguration::pcmConfig:
+ hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
+ audio_config.get<AudioConfiguration::pcmConfig>()));
+ break;
+ case AudioConfiguration::a2dpConfig:
+ hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+ audio_config.get<AudioConfiguration::a2dpConfig>()));
+ break;
+ case AudioConfiguration::leAudioConfig:
+ hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_config_2_1(
+ audio_config.get<AudioConfiguration::leAudioConfig>()));
+ break;
+ case AudioConfiguration::leAudioBroadcastConfig:
+ hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_broadcast_config_2_1(
+ audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
+ break;
+ }
+ return hidl_audio_config;
+}
+
+/***
+ *
+ * 2.0
+ *
+ ***/
+
+bool HidlToAidlMiddleware_2_0::IsSessionReady(
+ const SessionType_2_0& session_type) {
+ return BluetoothAudioSessionControl::IsSessionReady(
+ from_session_type_2_0(session_type));
+}
+
+uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback(
+ const SessionType_2_0& session_type,
+ const PortStatusCallbacks_2_0& cbacks) {
+ LOG(INFO) << __func__ << ": " << toString(session_type);
+ auto aidl_session_type = from_session_type_2_0(session_type);
+ // Pass the exact reference to the lambda
+ auto& session_legacy_callback_table =
+ legacy_callback_table[aidl_session_type];
+ PortStatusCallbacks aidl_callbacks{};
+ if (cbacks.control_result_cb_) {
+ aidl_callbacks.control_result_cb_ =
+ [&session_legacy_callback_table](uint16_t cookie, bool start_resp,
+ const BluetoothAudioStatus& status) {
+ if (session_legacy_callback_table.find(cookie) ==
+ session_legacy_callback_table.end()) {
+ LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+ return;
+ }
+ auto& cback = session_legacy_callback_table[cookie];
+ cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
+ };
+ }
+ if (cbacks.session_changed_cb_) {
+ aidl_callbacks.session_changed_cb_ =
+ [&session_legacy_callback_table](uint16_t cookie) {
+ if (session_legacy_callback_table.find(cookie) ==
+ session_legacy_callback_table.end()) {
+ LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+ return;
+ }
+ auto& cback = session_legacy_callback_table[cookie];
+ cback->session_changed_cb_(cookie);
+ };
+ };
+ auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
+ aidl_session_type, aidl_callbacks);
+ {
+ std::lock_guard<std::mutex> guard(legacy_callback_lock);
+ session_legacy_callback_table[cookie] =
+ std::make_shared<PortStatusCallbacks_2_0>(cbacks);
+ }
+ return cookie;
+}
+
+void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
+ const SessionType_2_0& session_type, uint16_t cookie) {
+ LOG(INFO) << __func__ << ": " << toString(session_type);
+ auto aidl_session_type = from_session_type_2_0(session_type);
+ BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
+ cookie);
+ auto& session_callback_table = legacy_callback_table[aidl_session_type];
+ if (session_callback_table.find(cookie) != session_callback_table.end()) {
+ std::lock_guard<std::mutex> guard(legacy_callback_lock);
+ session_callback_table.erase(cookie);
+ }
+}
+
+const AudioConfig_2_0 HidlToAidlMiddleware_2_0::GetAudioConfig(
+ const SessionType_2_0& session_type) {
+ return to_hidl_audio_config_2_0(BluetoothAudioSessionControl::GetAudioConfig(
+ from_session_type_2_0(session_type)));
+}
+
+bool HidlToAidlMiddleware_2_0::StartStream(
+ const SessionType_2_0& session_type) {
+ return BluetoothAudioSessionControl::StartStream(
+ from_session_type_2_0(session_type));
+}
+
+void HidlToAidlMiddleware_2_0::StopStream(const SessionType_2_0& session_type) {
+ return BluetoothAudioSessionControl::StopStream(
+ from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::SuspendStream(
+ const SessionType_2_0& session_type) {
+ return BluetoothAudioSessionControl::SuspendStream(
+ from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::GetPresentationPosition(
+ const SessionType_2_0& session_type, uint64_t* remote_delay_report_ns,
+ uint64_t* total_bytes_readed, timespec* data_position) {
+ PresentationPosition presentation_position;
+ auto ret_val = BluetoothAudioSessionControl::GetPresentationPosition(
+ from_session_type_2_0(session_type), presentation_position);
+ if (remote_delay_report_ns)
+ *remote_delay_report_ns = presentation_position.remoteDeviceAudioDelayNanos;
+ if (total_bytes_readed)
+ *total_bytes_readed = presentation_position.transmittedOctets;
+ if (data_position)
+ *data_position = {
+ .tv_sec = static_cast<__kernel_old_time_t>(
+ presentation_position.transmittedOctetsTimestamp.tvSec),
+ .tv_nsec = static_cast<long>(
+ presentation_position.transmittedOctetsTimestamp.tvNSec)};
+ return ret_val;
+}
+
+void HidlToAidlMiddleware_2_0::UpdateTracksMetadata(
+ const SessionType_2_0& session_type,
+ const struct source_metadata* source_metadata) {
+ return BluetoothAudioSessionControl::UpdateSourceMetadata(
+ from_session_type_2_0(session_type), *source_metadata);
+}
+
+size_t HidlToAidlMiddleware_2_0::OutWritePcmData(
+ const SessionType_2_0& session_type, const void* buffer, size_t bytes) {
+ return BluetoothAudioSessionControl::OutWritePcmData(
+ from_session_type_2_0(session_type), buffer, bytes);
+}
+
+size_t HidlToAidlMiddleware_2_0::InReadPcmData(
+ const SessionType_2_0& session_type, void* buffer, size_t bytes) {
+ return BluetoothAudioSessionControl::InReadPcmData(
+ from_session_type_2_0(session_type), buffer, bytes);
+}
+
+bool HidlToAidlMiddleware_2_0::IsAidlAvailable() {
+ return BluetoothAudioSession::IsAidlAvailable();
+}
+
+/***
+ *
+ * 2.1
+ *
+ ***/
+
+const AudioConfig_2_1 HidlToAidlMiddleware_2_1::GetAudioConfig(
+ const SessionType_2_1& session_type) {
+ return to_hidl_audio_config_2_1(BluetoothAudioSessionControl::GetAudioConfig(
+ from_session_type_2_1(session_type)));
+}
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
new file mode 100644
index 0000000..b124d8f
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/bluetooth/audio/2.0/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using PortStatusCallbacks_2_0 =
+ ::android::bluetooth::audio::PortStatusCallbacks;
+using AudioConfig_2_0 =
+ ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_0 {
+ public:
+ static bool IsAidlAvailable();
+
+ static bool IsSessionReady(const SessionType_2_0& session_type);
+
+ static uint16_t RegisterControlResultCback(
+ const SessionType_2_0& session_type,
+ const PortStatusCallbacks_2_0& cbacks);
+
+ static void UnregisterControlResultCback(const SessionType_2_0& session_type,
+ uint16_t cookie);
+
+ static const AudioConfig_2_0 GetAudioConfig(
+ const SessionType_2_0& session_type);
+
+ static bool StartStream(const SessionType_2_0& session_type);
+
+ static void StopStream(const SessionType_2_0& session_type);
+
+ static bool SuspendStream(const SessionType_2_0& session_type);
+
+ static bool GetPresentationPosition(const SessionType_2_0& session_type,
+ uint64_t* remote_delay_report_ns,
+ uint64_t* total_bytes_readed,
+ timespec* data_position);
+
+ static void UpdateTracksMetadata(
+ const SessionType_2_0& session_type,
+ const struct source_metadata* source_metadata);
+
+ static size_t OutWritePcmData(const SessionType_2_0& session_type,
+ const void* buffer, size_t bytes);
+
+ static size_t InReadPcmData(const SessionType_2_0& session_type, void* buffer,
+ size_t bytes);
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
new file mode 100644
index 0000000..82dce96
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::SessionType;
+using AudioConfig_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_1 {
+ public:
+ static const AudioConfig_2_1 GetAudioConfig(
+ const SessionType_2_1& session_type);
+};
+
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
index 2f3ddaf..283952e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
@@ -21,10 +21,13 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+
namespace android {
namespace bluetooth {
namespace audio {
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
using ::android::hardware::audio::common::V5_0::AudioContentType;
using ::android::hardware::audio::common::V5_0::AudioUsage;
using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
@@ -149,6 +152,8 @@
// 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() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::IsSessionReady(session_type_);
std::lock_guard<std::recursive_mutex> guard(mutex_);
bool dataMQ_valid =
(session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
@@ -200,6 +205,9 @@
// @return: cookie - the assigned number to this bluetooth_audio output
uint16_t BluetoothAudioSession::RegisterStatusCback(
const PortStatusCallbacks& cbacks) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::RegisterControlResultCback(session_type_,
+ cbacks);
std::lock_guard<std::recursive_mutex> guard(mutex_);
uint16_t cookie = ObserversCookieGetInitValue(session_type_);
uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
@@ -227,6 +235,9 @@
// PortStatusCallbacks
// @param: cookie - indicates which bluetooth_audio output is
void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::UnregisterControlResultCback(session_type_,
+ cookie);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (observers_.erase(cookie) != 1) {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
@@ -238,6 +249,9 @@
// The control function is for the bluetooth_audio module to get the current
// AudioConfiguration
const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return (audio_config_ =
+ HidlToAidlMiddleware_2_0::GetAudioConfig(session_type_));
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (IsSessionReady()) {
return audio_config_;
@@ -251,6 +265,8 @@
// Those control functions are for the bluetooth_audio module to start, suspend,
// stop stream, to check position, and to update metadata.
bool BluetoothAudioSession::StartStream() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::StartStream(session_type_);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (!IsSessionReady()) {
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -267,6 +283,8 @@
}
bool BluetoothAudioSession::SuspendStream() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::SuspendStream(session_type_);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (!IsSessionReady()) {
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -283,6 +301,8 @@
}
void BluetoothAudioSession::StopStream() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::StopStream(session_type_);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (!IsSessionReady()) {
return;
@@ -297,6 +317,10 @@
bool BluetoothAudioSession::GetPresentationPosition(
uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
timespec* data_position) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::GetPresentationPosition(
+ session_type_, remote_delay_report_ns, total_bytes_readed,
+ data_position);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (!IsSessionReady()) {
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -330,6 +354,9 @@
void BluetoothAudioSession::UpdateTracksMetadata(
const struct source_metadata* source_metadata) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::UpdateTracksMetadata(session_type_,
+ source_metadata);
std::lock_guard<std::recursive_mutex> guard(mutex_);
if (!IsSessionReady()) {
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -374,6 +401,9 @@
// The control function writes stream to FMQ
size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
size_t bytes) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::OutWritePcmData(session_type_, buffer,
+ bytes);
if (buffer == nullptr || !bytes) return 0;
size_t totalWritten = 0;
int ms_timeout = kFmqSendTimeoutMs;
@@ -407,6 +437,9 @@
// The control function reads stream from FMQ
size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_0::InReadPcmData(session_type_, buffer,
+ bytes);
if (buffer == nullptr || !bytes) return 0;
size_t totalRead = 0;
int ms_timeout = kFmqReceiveTimeoutMs;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
index 95f7408..4d7be21 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
@@ -35,7 +35,7 @@
std::shared_ptr<BluetoothAudioSession_2_1> session_ptr =
BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- return session_ptr->IsSessionReady();
+ return session_ptr->GetAudioSession()->IsSessionReady();
}
return false;
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
deleted file mode 100644
index e20914e..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include "BluetoothAudioSession_2_2.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-class BluetoothAudioSessionControl_2_2 {
- using SessionType_2_1 =
- ::android::hardware::bluetooth::audio::V2_1::SessionType;
- using AudioConfiguration_2_2 =
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
-
- 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_2_1& session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::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_2_1& session_type, const PortStatusCallbacks& cbacks) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->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_2_1& session_type,
- uint16_t cookie) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->UnregisterStatusCback(cookie);
- }
- }
-
- // The control API for the bluetooth_audio module to get current
- // AudioConfiguration
- static const AudioConfiguration_2_2 GetAudioConfig(
- const SessionType_2_1& session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioConfig();
- } else if (session_type ==
- SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
- return BluetoothAudioSession_2_2::kInvalidOffloadAudioConfiguration;
- } else {
- return BluetoothAudioSession_2_2::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_2_1& session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->StartStream();
- }
- return false;
- }
-
- static bool SuspendStream(const SessionType_2_1& session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->SuspendStream();
- }
- return false;
- }
-
- static void StopStream(const SessionType_2_1& session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->StopStream();
- }
- }
-
- static bool GetPresentationPosition(const SessionType_2_1& session_type,
- uint64_t* remote_delay_report_ns,
- uint64_t* total_bytes_readed,
- timespec* data_position) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->GetPresentationPosition(
- remote_delay_report_ns, total_bytes_readed, data_position);
- }
- return false;
- }
-
- static void UpdateTracksMetadata(
- const SessionType_2_1& session_type,
- const struct source_metadata* source_metadata) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->UpdateTracksMetadata(source_metadata);
- }
- }
-
- // The control API writes stream to FMQ
- static size_t OutWritePcmData(const SessionType_2_1& session_type,
- const void* buffer, size_t bytes) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->OutWritePcmData(buffer, bytes);
- }
- return 0;
- }
-
- // The control API reads stream from FMQ
- static size_t InReadPcmData(const SessionType_2_1& session_type, void* buffer,
- size_t bytes) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes);
- }
- return 0;
- }
-};
-
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
deleted file mode 100644
index 194259a..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-class BluetoothAudioSessionReport_2_2 {
- public:
- // The API reports the Bluetooth stack has started the session, and will
- // inform registered bluetooth_audio outputs
- static void OnSessionStarted(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type,
- const sp<IBluetoothAudioPort> host_iface,
- const DataMQ::Descriptor* dataMQ,
- const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
- audio_config) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::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 ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->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 ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type,
- const bool& start_resp, const BluetoothAudioStatus& status) {
- std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
- BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
- if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->ReportControlStatus(start_resp, status);
- }
- }
-};
-
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index c250ef1..276a291 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -21,9 +21,14 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+#include "../aidl_session/HidlToAidlMiddleware_2_1.h"
+
namespace android {
namespace bluetooth {
namespace audio {
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_1;
using SessionType_2_1 =
::android::hardware::bluetooth::audio::V2_1::SessionType;
using SessionType_2_0 =
@@ -46,6 +51,19 @@
return false;
}
}
+
+bool is_unsupported_2_1_session_type(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type) {
+ if (session_type ==
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return true;
+ } else {
+ return false;
+ }
+}
} // namespace
BluetoothAudioSession_2_1::BluetoothAudioSession_2_1(
@@ -53,21 +71,13 @@
session_type)
: audio_session(BluetoothAudioSessionInstance::GetSessionInstance(
static_cast<SessionType_2_0>(session_type))) {
- if (is_2_0_session_type(session_type)) {
+ if (is_2_0_session_type(session_type) ||
+ is_unsupported_2_1_session_type(session_type)) {
session_type_2_1_ = (SessionType_2_1::UNKNOWN);
} else {
session_type_2_1_ = (session_type);
}
-}
-
-bool BluetoothAudioSession_2_1::IsSessionReady() {
- if (session_type_2_1_ !=
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
- return audio_session->IsSessionReady();
- }
-
- std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- return audio_session->stack_iface_ != nullptr;
+ raw_session_type_ = session_type;
}
std::shared_ptr<BluetoothAudioSession>
@@ -79,8 +89,10 @@
// AudioConfiguration
const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
BluetoothAudioSession_2_1::GetAudioConfig() {
+ if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+ return HidlToAidlMiddleware_2_1::GetAudioConfig(raw_session_type_);
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- if (IsSessionReady()) {
+ if (audio_session->IsSessionReady()) {
// If session is unknown it means it should be 2.0 type
if (session_type_2_1_ != SessionType_2_1::UNKNOWN)
return audio_config_2_1_;
@@ -90,7 +102,7 @@
// pcmConfig only differs between 2.0 and 2.1 in AudioConfiguration
if (fromConf.getDiscriminator() ==
AudioConfiguration::hidl_discriminator::codecConfig) {
- toConf.codecConfig() = fromConf.codecConfig();
+ toConf.codecConfig(fromConf.codecConfig());
} else {
toConf.pcmConfig() = {
.sampleRate = static_cast<
@@ -122,9 +134,6 @@
SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
bool is_offload_a2dp_session =
(session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
- bool is_offload_le_audio_session =
- (session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
- session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
auto audio_config_discriminator = audio_config.getDiscriminator();
bool is_software_audio_config =
(is_software_session &&
@@ -136,13 +145,7 @@
audio_config_discriminator ==
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
hidl_discriminator::codecConfig);
- bool is_le_audio_offload_audio_config =
- (is_offload_le_audio_session &&
- audio_config_discriminator ==
- ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
- hidl_discriminator::leAudioCodecConfig);
- if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
- !is_le_audio_offload_audio_config) {
+ if (!is_software_audio_config && !is_a2dp_offload_audio_config) {
return false;
}
audio_config_2_1_ = audio_config;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index db82c73..e634064 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -31,6 +31,7 @@
std::shared_ptr<BluetoothAudioSession> audio_session;
::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
+ ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
// audio data configuration for both software and offloading
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
@@ -50,10 +51,6 @@
const ::android::hardware::bluetooth::audio::V2_1::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();
-
std::shared_ptr<BluetoothAudioSession> GetAudioSession();
// The report function is used to report that the Bluetooth stack has started
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
deleted file mode 100644
index 5a6b2e7..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "BTAudioProviderSession_2_2"
-
-#include "BluetoothAudioSession_2_2.h"
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-using SessionType_2_1 =
- ::android::hardware::bluetooth::audio::V2_1::SessionType;
-using SessionType_2_0 =
- ::android::hardware::bluetooth::audio::V2_0::SessionType;
-
-using AudioConfiguration_2_1 =
- ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
-
-::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- BluetoothAudioSession_2_2::invalidSoftwareAudioConfiguration = {};
-::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
-
-namespace {
-bool is_2_0_session_type(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type) {
- if (session_type == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
- session_type == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
- session_type == SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH) {
- return true;
- } else {
- return false;
- }
-}
-} // namespace
-
-BluetoothAudioSession_2_2::BluetoothAudioSession_2_2(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type)
- : audio_session(BluetoothAudioSessionInstance::GetSessionInstance(
- static_cast<SessionType_2_0>(session_type))),
- audio_session_2_1(
- BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type)) {
- if (is_2_0_session_type(session_type)) {
- session_type_2_1_ = (SessionType_2_1::UNKNOWN);
- } else {
- session_type_2_1_ = (session_type);
- }
-}
-
-bool BluetoothAudioSession_2_2::IsSessionReady() {
- if (session_type_2_1_ !=
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
- return audio_session->IsSessionReady();
- }
-
- std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- return audio_session->stack_iface_ != nullptr;
-}
-
-std::shared_ptr<BluetoothAudioSession>
-BluetoothAudioSession_2_2::GetAudioSession() {
- return audio_session;
-}
-std::shared_ptr<BluetoothAudioSession_2_1>
-BluetoothAudioSession_2_2::GetAudioSession_2_1() {
- return audio_session_2_1;
-}
-
-// The control function is for the bluetooth_audio module to get the current
-// AudioConfiguration
-const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-BluetoothAudioSession_2_2::GetAudioConfig() {
- std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- if (IsSessionReady()) {
- // If session is unknown it means it should be 2.0 type
- if (session_type_2_1_ != SessionType_2_1::UNKNOWN) {
- if (audio_config_2_2_ != invalidSoftwareAudioConfiguration)
- return audio_config_2_2_;
-
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
- const AudioConfiguration_2_1 fromConf =
- GetAudioSession_2_1()->GetAudioConfig();
- if (fromConf.getDiscriminator() ==
- AudioConfiguration_2_1::hidl_discriminator::pcmConfig) {
- toConf.pcmConfig() = fromConf.pcmConfig();
- return toConf;
- }
- }
-
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
- const AudioConfiguration fromConf = GetAudioSession()->GetAudioConfig();
- // pcmConfig only differs between 2.0 and 2.1 in AudioConfiguration
- if (fromConf.getDiscriminator() ==
- AudioConfiguration::hidl_discriminator::codecConfig) {
- toConf.codecConfig() = fromConf.codecConfig();
- } else {
- toConf.pcmConfig() = {
- .sampleRate = static_cast<
- ::android::hardware::bluetooth::audio::V2_1::SampleRate>(
- fromConf.pcmConfig().sampleRate),
- .channelMode = fromConf.pcmConfig().channelMode,
- .bitsPerSample = fromConf.pcmConfig().bitsPerSample,
- .dataIntervalUs = 0};
- }
- return toConf;
- } else if (session_type_2_1_ ==
- SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
- return kInvalidOffloadAudioConfiguration;
- } else {
- return kInvalidSoftwareAudioConfiguration;
- }
-}
-
-bool BluetoothAudioSession_2_2::UpdateAudioConfig(
- const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
- audio_config) {
- bool is_software_session =
- (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
- session_type_2_1_ ==
- SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
- session_type_2_1_ ==
- SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
- session_type_2_1_ ==
- SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
- bool is_offload_a2dp_session =
- (session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
- bool is_offload_le_audio_session =
- (session_type_2_1_ ==
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
- session_type_2_1_ ==
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
- auto audio_config_discriminator = audio_config.getDiscriminator();
- bool is_software_audio_config =
- (is_software_session &&
- audio_config_discriminator ==
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
- hidl_discriminator::pcmConfig);
- bool is_a2dp_offload_audio_config =
- (is_offload_a2dp_session &&
- audio_config_discriminator ==
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
- hidl_discriminator::codecConfig);
- bool is_le_audio_offload_audio_config =
- (is_offload_le_audio_session &&
- audio_config_discriminator ==
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
- hidl_discriminator::leAudioConfig);
- if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
- !is_le_audio_offload_audio_config) {
- return false;
- }
- audio_config_2_2_ = audio_config;
- return true;
-}
-
-// 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_2_2::OnSessionStarted(
- const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
- const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
- audio_config) {
- if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
- ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration config;
- if (audio_config.getDiscriminator() ==
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
- hidl_discriminator::codecConfig) {
- config.codecConfig(audio_config.codecConfig());
- } else {
- auto& tmpPcm = audio_config.pcmConfig();
- config.pcmConfig(
- ::android::hardware::bluetooth::audio::V2_0::PcmParameters{
- .sampleRate = static_cast<SampleRate>(tmpPcm.sampleRate),
- .channelMode = tmpPcm.channelMode,
- .bitsPerSample = tmpPcm.bitsPerSample
- /*dataIntervalUs is not passed to 2.0 */
- });
- }
-
- audio_session->OnSessionStarted(stack_iface, dataMQ, config);
- } else {
- std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- if (stack_iface == nullptr) {
- LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
- << ", IBluetoothAudioPort Invalid";
- } else if (!UpdateAudioConfig(audio_config)) {
- LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
- << ", AudioConfiguration=" << toString(audio_config)
- << " Invalid";
- } else if (!audio_session->UpdateDataPath(dataMQ)) {
- LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
- << " DataMQ Invalid";
- audio_config_2_2_ =
- (session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH
- ? kInvalidOffloadAudioConfiguration
- : kInvalidSoftwareAudioConfiguration);
- } else {
- audio_session->stack_iface_ = stack_iface;
- LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
- << ", AudioConfiguration=" << toString(audio_config);
- audio_session->ReportSessionStatus();
- };
- }
-}
-
-std::unique_ptr<BluetoothAudioSessionInstance_2_2>
- BluetoothAudioSessionInstance_2_2::instance_ptr =
- std::unique_ptr<BluetoothAudioSessionInstance_2_2>(
- new BluetoothAudioSessionInstance_2_2());
-
-// API to fetch the session of A2DP / Hearing Aid
-std::shared_ptr<BluetoothAudioSession_2_2>
-BluetoothAudioSessionInstance_2_2::GetSessionInstance(
- const SessionType_2_1& 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_2_2> session_ptr =
- std::make_shared<BluetoothAudioSession_2_2>(session_type);
- instance_ptr->sessions_map_[session_type] = session_ptr;
- return session_ptr;
-}
-
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
deleted file mode 100644
index 7213ede..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-#include <mutex>
-#include <unordered_map>
-
-#include "BluetoothAudioSession.h"
-#include "BluetoothAudioSession_2_1.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-class BluetoothAudioSession_2_2 {
- private:
- std::shared_ptr<BluetoothAudioSession> audio_session;
- std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1;
-
- ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
-
- // audio data configuration for both software and offloading
- ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- audio_config_2_2_;
-
- bool UpdateAudioConfig(
- const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
- audio_config);
-
- static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- invalidSoftwareAudioConfiguration;
- static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- invalidOffloadAudioConfiguration;
-
- public:
- BluetoothAudioSession_2_2(
- const ::android::hardware::bluetooth::audio::V2_1::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();
-
- std::shared_ptr<BluetoothAudioSession> GetAudioSession();
- std::shared_ptr<BluetoothAudioSession_2_1> GetAudioSession_2_1();
-
- // 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 ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
- audio_config);
-
- // The control function is for the bluetooth_audio module to get the current
- // AudioConfiguration
- const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
- GetAudioConfig();
-
- static constexpr ::android::hardware::bluetooth::audio::V2_2::
- AudioConfiguration& kInvalidSoftwareAudioConfiguration =
- invalidSoftwareAudioConfiguration;
- static constexpr ::android::hardware::bluetooth::audio::V2_2::
- AudioConfiguration& kInvalidOffloadAudioConfiguration =
- invalidOffloadAudioConfiguration;
-};
-
-class BluetoothAudioSessionInstance_2_2 {
- public:
- // The API is to fetch the specified session of A2DP / Hearing Aid
- static std::shared_ptr<BluetoothAudioSession_2_2> GetSessionInstance(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type);
-
- private:
- static std::unique_ptr<BluetoothAudioSessionInstance_2_2> instance_ptr;
- std::mutex mutex_;
- std::unordered_map<::android::hardware::bluetooth::audio::V2_1::SessionType,
- std::shared_ptr<BluetoothAudioSession_2_2>>
- sessions_map_;
-};
-
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
deleted file mode 100644
index 5becdaa..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_2_2"
-
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-using SessionType_2_1 =
- ::android::hardware::bluetooth::audio::V2_1::SessionType;
-
-bool IsOffloadLeAudioConfigurationValid(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type,
- const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&) {
- if (session_type !=
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
- session_type !=
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
- return false;
- }
-
- // TODO: perform checks on le_audio_codec_config once we know supported
- // parameters
-
- return true;
-}
-
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
deleted file mode 100644
index 59d22b7..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.2/types.h>
-
-#include "BluetoothAudioSupportedCodecsDB.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-bool IsOffloadLeAudioConfigurationValid(
- const ::android::hardware::bluetooth::audio::V2_1::SessionType&
- session_type,
- const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
- le_audio_codec_config);
-} // namespace audio
-} // namespace bluetooth
-} // namespace android
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index f0dfe96..0fb4eb0 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalBroadcastradioV1_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
static_libs: [
"android.hardware.broadcastradio@1.0",
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
index dd8c9c6..d58ba53 100644
--- a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -1,5 +1,6 @@
service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
- interface android.hardware.broadcastradio@2.0::IBroadcastRadio default
+ interface android.hardware.broadcastradio@2.0::IBroadcastRadio amfm
+ interface android.hardware.broadcastradio@2.0::IBroadcastRadio dab
class hal
user audioserver
group audio
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index e26486d..cb50c5e 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalBroadcastradioV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
static_libs: [
"android.hardware.broadcastradio@2.0",
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+ /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+ */
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+ ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 8886ee1..d2f61a5 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalCameraProviderV2_4TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
// TODO(b/64437680): Assume these are always available on the device.
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 5c886ee..052103d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -882,6 +882,7 @@
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+ static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/);
static bool isDepthOnly(const camera_metadata_t* staticMeta);
@@ -935,7 +936,9 @@
camera_metadata_ro_entry* streamConfigs,
camera_metadata_ro_entry* maxResolutionStreamConfigs,
const camera_metadata_t* staticMetadata);
- static bool isColorCamera(const camera_metadata_t *metadata);
+ void getPrivacyTestPatternModes(
+ const camera_metadata_t* staticMetadata,
+ std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
static V3_2::DataspaceFlags getDataspace(PixelFormat format);
@@ -3837,6 +3840,8 @@
getAvailableOutputStreams(staticMeta, outputStreams,
&outputThreshold));
for (auto& outputIter : outputStreams) {
+ V3_2::DataspaceFlags outputDataSpace =
+ getDataspace(static_cast<PixelFormat>(outputIter.format));
V3_2::Stream zslStream = {streamId++,
StreamType::OUTPUT,
static_cast<uint32_t>(input.width),
@@ -3859,7 +3864,7 @@
static_cast<uint32_t>(outputIter.height),
static_cast<PixelFormat>(outputIter.format),
GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
- 0,
+ outputDataSpace,
StreamRotation::ROTATION_0};
::android::hardware::hidl_vec<V3_2::Stream> streams = {inputStream, zslStream,
@@ -4658,6 +4663,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
hidl_handle buffer_handle;
StreamBuffer outputBuffer;
@@ -4834,6 +4840,7 @@
settings.setToExternal(
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
get_camera_metadata_size(settingsBuffer));
+ overrideRotateAndCrop(&settings);
free_camera_metadata(staticMeta);
ret = session->close();
@@ -4911,6 +4918,7 @@
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
filteredSettingsBuffer)),
get_camera_metadata_size(filteredSettingsBuffer));
+ overrideRotateAndCrop(&camSettings[0].settings);
camSettings[0].fmqSettingsSize = 0;
camSettings[0].physicalCameraId = physicalDeviceId;
@@ -5068,6 +5076,7 @@
settings.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
get_camera_metadata_size(settingsBuffer));
+ overrideRotateAndCrop(&settings);
free_camera_metadata(staticMeta);
ret = session->close();
@@ -5303,6 +5312,7 @@
camera_metadata_t *metaBuffer = requestMeta.release();
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
get_camera_metadata_size(metaBuffer), true);
+ overrideRotateAndCrop(&requestSettings[i]);
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
emptyInputBuffer, {outputBuffers[i]}};
@@ -5529,6 +5539,7 @@
camera_metadata_t *metaBuffer = requestMeta.release();
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
get_camera_metadata_size(metaBuffer), true);
+ overrideRotateAndCrop(&requestSettings[i]);
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
emptyInputBuffer, {outputBuffers[i]}};
@@ -5669,6 +5680,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
@@ -5753,6 +5765,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
hidl_handle buffer_handle;
if (useHalBufManager) {
@@ -6185,141 +6198,6 @@
}
}
-// Test the multi-camera API requirement for Google Requirement Freeze S
-// Note that this requirement can only be partially tested. If a vendor
-// device doesn't expose a physical camera in any shape or form, there is no way
-// the test can catch it.
-TEST_P(CameraHidlTest, grfSMultiCameraTest) {
- const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
- if (socGrfApi < 31 /*S*/) {
- // Non-GRF devices, or version < 31 Skip
- ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
- return;
- }
-
- // Test that if more than one rear-facing color camera is
- // supported, there must be at least one rear-facing logical camera.
- hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
- // Back facing non-logical color cameras
- std::set<std::string> rearColorCameras;
- // Back facing logical cameras' physical camera Id sets
- std::set<std::set<std::string>> rearPhysicalIds;
- for (const auto& name : cameraDeviceNames) {
- std::string cameraId;
- int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
- switch (deviceVersion) {
- case CAMERA_DEVICE_API_VERSION_3_7:
- case CAMERA_DEVICE_API_VERSION_3_6:
- case CAMERA_DEVICE_API_VERSION_3_5:
- case CAMERA_DEVICE_API_VERSION_3_4:
- case CAMERA_DEVICE_API_VERSION_3_3:
- case CAMERA_DEVICE_API_VERSION_3_2: {
- ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
- ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
- Return<void> ret;
- ret = mProvider->getCameraDeviceInterface_V3_x(
- name, [&](auto status, const auto& device) {
- ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
- ASSERT_EQ(Status::OK, status);
- ASSERT_NE(device, nullptr);
- device3_x = device;
- });
- ASSERT_TRUE(ret.isOk());
-
- ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-
- // Skip if this is not a color camera.
- if (!CameraHidlTest::isColorCamera(metadata)) {
- return;
- }
-
- // Check camera facing. Skip if facing is not BACK.
- // If this is not a logical camera, only note down
- // the camera ID, and skip.
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_LENS_FACING, &entry);
- ASSERT_EQ(retcode, 0);
- ASSERT_GT(entry.count, 0);
- uint8_t facing = entry.data.u8[0];
- bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
- if (facing != ANDROID_LENS_FACING_BACK) {
- // Not BACK facing. Skip.
- return;
- }
- if (!isLogicalCamera) {
- rearColorCameras.insert(cameraId);
- return;
- }
-
- // Check logical camera's physical camera IDs for color
- // cameras.
- std::unordered_set<std::string> physicalCameraIds;
- Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
- ASSERT_EQ(Status::OK, s);
- rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
- for (const auto& physicalId : physicalCameraIds) {
- // Skip if the physicalId is publicly available
- for (auto& deviceName : cameraDeviceNames) {
- std::string publicVersion, publicId;
- ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
- &publicVersion, &publicId));
- if (physicalId == publicId) {
- // Skip because public Ids will be iterated in outer loop.
- return;
- }
- }
-
- auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
- ASSERT_TRUE(castResult.isOk());
- ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
- device3_5 = castResult;
- ASSERT_NE(device3_5, nullptr);
-
- // Check camera characteristics for hidden camera id
- Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
- physicalId, [&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* physicalMetadata =
- (camera_metadata_t*)chars.data();
-
- if (CameraHidlTest::isColorCamera(physicalMetadata)) {
- rearColorCameras.insert(physicalId);
- }
- });
- ASSERT_TRUE(ret.isOk());
- }
- });
- ASSERT_TRUE(ret.isOk());
- } break;
- case CAMERA_DEVICE_API_VERSION_1_0: {
- // Not applicable
- } break;
- default: {
- ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
- ADD_FAILURE();
- } break;
- }
- }
-
- // If there are more than one rear-facing color camera, a logical
- // multi-camera must be defined consisting of all rear-facing color
- // cameras.
- if (rearColorCameras.size() > 1) {
- bool hasRearLogical = false;
- for (const auto& physicalIds : rearPhysicalIds) {
- if (std::includes(physicalIds.begin(), physicalIds.end(),
- rearColorCameras.begin(), rearColorCameras.end())) {
- hasRearLogical = true;
- break;
- }
- }
- ASSERT_TRUE(hasRearLogical);
- }
-}
-
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -6751,6 +6629,25 @@
ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
}
+void CameraHidlTest::getPrivacyTestPatternModes(
+ const camera_metadata_t* staticMetadata,
+ std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) {
+ ASSERT_NE(staticMetadata, nullptr);
+ ASSERT_NE(privacyTestPatternModes, nullptr);
+
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(
+ staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry);
+ ASSERT_TRUE(0 == retcode);
+
+ for (auto i = 0; i < entry.count; i++) {
+ if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR ||
+ entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+ privacyTestPatternModes->insert(entry.data.i32[i]);
+ }
+ }
+}
+
// Select an appropriate dataspace given a specific pixel format.
V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
switch (format) {
@@ -6792,23 +6689,6 @@
return ret;
}
-bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
- if ((0 == retcode) && (entry.count > 0)) {
- bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
- entry.data.u8 + entry.count);
- bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
- entry.data.u8 + entry.count);
- bool isColor = isBackwardCompatible && !isMonochrome;
- return isColor;
- }
- return false;
-}
-
// Retrieve the reprocess input-output format map from the static
// camera characteristics.
Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
@@ -7805,6 +7685,16 @@
ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
physicalIds.insert(cameraId);
}
+
+ std::unordered_set<int32_t> physicalRequestKeyIDs;
+ rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata),
+ ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+ ASSERT_TRUE(Status::OK == rc);
+ bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find(
+ ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end();
+ std::unordered_set<int32_t> privacyTestPatternModes;
+ getPrivacyTestPatternModes(metadata, &privacyTestPatternModes);
+
// Map from image format to number of multi-resolution sizes for that format
std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap;
std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
@@ -7826,6 +7716,7 @@
camera_metadata_ro_entry physicalStreamConfigs;
camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
bool isUltraHighRes = false;
+ std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
if (isPublicId) {
::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
Return<void> ret;
@@ -7856,6 +7747,8 @@
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
&physicalMaxResolutionStreamConfigs, staticMetadata);
isUltraHighRes = isUltraHighResolution(staticMetadata);
+
+ getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
});
ASSERT_TRUE(ret.isOk());
} else {
@@ -7882,6 +7775,7 @@
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
&physicalMaxResolutionStreamConfigs, staticMetadata);
isUltraHighRes = isUltraHighResolution(staticMetadata);
+ getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
});
ASSERT_TRUE(ret.isOk());
@@ -7898,6 +7792,10 @@
ASSERT_TRUE(ret.isOk());
}
+ if (hasTestPatternPhysicalRequestKey) {
+ ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
+ }
+
if (physicalMultiResStreamConfigs.count > 0) {
ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
@@ -8133,6 +8031,20 @@
poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
}
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+ if (0 == retcode && entry.count > 0) {
+ ASSERT_TRUE((entry.count % 2) == 0);
+ uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+ uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+ uint64_t stateMask = (1 << vendorStateStart) - 1;
+ stateMask &= ~((1 << maxPublicState) - 1);
+ for (int i = 0; i < entry.count; i += 2){
+ ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+ ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+ }
+ }
+
verifyExtendedSceneModeCharacteristics(metadata);
verifyZoomCharacteristics(metadata);
}
@@ -8893,6 +8805,25 @@
}
}
+void CameraHidlTest::overrideRotateAndCrop(
+ ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) {
+ if (settings == nullptr) {
+ return;
+ }
+
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+ requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data()));
+ auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP);
+ if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) {
+ uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+ requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1);
+ settings->releaseData();
+ camera_metadata_t *metaBuffer = requestMeta.release();
+ settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+ get_camera_metadata_size(metaBuffer), true);
+ }
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, CameraHidlTest,
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 028c923..549d970 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -30,6 +30,7 @@
ndk: {
apex_available: [
"//apex_available:platform",
+ "com.android.bluetooth",
"com.android.media.swcodec",
"com.android.neuralnetworks",
],
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 376ac97..6fd4200 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -25,11 +25,17 @@
backend: {
java: {
sdk_version: "module_current",
- srcs_available: true,
},
cpp: {
enabled: false,
},
+ ndk: {
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth",
+ ],
+ min_sdk_version: "29",
+ },
},
versions: ["1"],
}
diff --git a/common/support/Android.bp b/common/support/Android.bp
index b24893b..718901e 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -11,7 +11,11 @@
name: "libaidlcommonsupport",
vendor_available: true,
host_supported: true,
- defaults: ["libbinder_ndk_host_user"],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
srcs: ["NativeHandle.cpp"],
export_include_dirs: ["include"],
shared_libs: [
@@ -28,7 +32,11 @@
cc_test {
name: "libaidlcommonsupport_test",
host_supported: true,
- defaults: ["libbinder_ndk_host_user"],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
srcs: ["test.cpp"],
static_libs: [
"android.hardware.common-V2-ndk",
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index a75ed25..468735d 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -207,7 +207,10 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+ If the HIDL health HAL exists, it must be at least version 2.0.
+ See DeviceManifestTest.HealthHal -->
+ <hal format="hidl" optional="true">
<name>android.hardware.health</name>
<version>2.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index 3b8ee21..96f291f 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -213,7 +213,10 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+ If the HIDL health HAL exists, it must be at least version 2.0.
+ See DeviceManifestTest.HealthHal -->
+ <hal format="hidl" optional="true">
<name>android.hardware.health</name>
<version>2.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index 0fb21a7..3642814 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -238,7 +238,10 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+ If the HIDL health HAL exists, it must be at least version 2.1.
+ See DeviceManifestTest.HealthHal -->
+ <hal format="hidl" optional="true">
<name>android.hardware.health</name>
<version>2.1</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml
index aee2c51..9c42cb0 100644
--- a/compatibility_matrices/compatibility_matrix.6.xml
+++ b/compatibility_matrices/compatibility_matrix.6.xml
@@ -268,7 +268,10 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+ If the HIDL health HAL exists, it must be at least version 2.1.
+ See DeviceManifestTest.HealthHal -->
+ <hal format="hidl" optional="true">
<name>android.hardware.health</name>
<version>2.1</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c39db36..8c5a812 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -10,7 +10,7 @@
<hal format="hidl" optional="false">
<name>android.hardware.audio</name>
<version>6.0</version>
- <version>7.0</version>
+ <version>7.0-1</version>
<interface>
<name>IDevicesFactory</name>
<instance>default</instance>
@@ -131,11 +131,10 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
<name>android.hardware.bluetooth.audio</name>
- <version>2.0-2</version>
<interface>
- <name>IBluetoothAudioProvidersFactory</name>
+ <name>IBluetoothAudioProviderFactory</name>
<instance>default</instance>
</interface>
</hal>
@@ -267,16 +266,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.health</name>
- <version>2.1</version>
- <interface>
- <name>IHealth</name>
- <instance>default</instance>
- </interface>
- </hal>
- <!-- TODO(b/177269435): require health AIDL HAL and deprecate HIDL HAL -->
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="false">
<name>android.hardware.health</name>
<version>1</version>
<interface>
@@ -294,7 +284,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.identity</name>
- <version>1-3</version>
+ <version>1-4</version>
<interface>
<name>IIdentityCredentialStore</name>
<instance>default</instance>
@@ -308,9 +298,9 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
<name>android.hardware.ir</name>
- <version>1.0</version>
+ <version>1</version>
<interface>
<name>IConsumerIr</name>
<instance>default</instance>
@@ -342,9 +332,17 @@
</interface>
</hal>
<hal format="aidl" optional="true">
- <name>android.hardware.security.keymint</name>
+ <name>android.hardware.security.dice</name>
<version>1</version>
<interface>
+ <name>IDiceDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.security.keymint</name>
+ <version>1-2</version>
+ <interface>
<name>IKeyMintDevice</name>
<instance>default</instance>
<instance>strongbox</instance>
@@ -352,6 +350,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.security.keymint</name>
+ <version>1-2</version>
<interface>
<name>IRemotelyProvisionedComponent</name>
<instance>default</instance>
@@ -404,7 +403,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.neuralnetworks</name>
- <version>1-3</version>
+ <version>1-4</version>
<interface>
<name>IDevice</name>
<regex-instance>.*</regex-instance>
@@ -418,6 +417,13 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.nfc</name>
+ <interface>
+ <name>INfc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.oemlock</name>
<version>1.0</version>
@@ -621,7 +627,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="hidl" optional="false">
<name>android.hardware.thermal</name>
<version>2.0</version>
<interface>
@@ -733,4 +739,11 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.wifi.supplicant</name>
+ <interface>
+ <name>ISupplicant</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
</compatibility-matrix>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index d8c9170..f34009d 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -51,6 +51,7 @@
"android.hardware.media.bufferpool@2.0",
"android.hardware.radio.config@1.2",
// AIDL
+ "android.hardware.audio.common",
"android.hardware.biometrics.common",
"android.hardware.common",
"android.hardware.common.fmq",
diff --git a/current.txt b/current.txt
index 59fbfa9..6a77e19 100644
--- a/current.txt
+++ b/current.txt
@@ -898,9 +898,15 @@
c8a57364f6ad20842be14f4db284df5304f7521ca8eac6bcc1fa6c5b466fb8a6 android.hardware.wifi.supplicant@1.4::ISupplicantStaNetwork
2123482b69f3b531c88023aa2a007110e130efbf4ed68ac9ce0bc55d5e82bc8b android.hardware.wifi.supplicant@1.4::ISupplicantStaNetworkCallback
0821f516e4d428bc15251969f7e19411c94d8f2ccbd99e1fc8168d8e49e38b0f android.hardware.wifi.supplicant@1.4::types
+4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
+70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
+
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
# ABI preserving changes to HALs during Android T
62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
+d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
fa76bced6b1b71c40fc706c508a9011284c57f57831cd0cf5f45653ed4ea463e android.hardware.neuralnetworks@1.3::types
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 5ea6ad3..8ca6a65 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -44,6 +44,10 @@
local_include_dirs: [
"include",
],
+ tidy_timeout_srcs: [
+ "drm_hal_clearkey_test.cpp",
+ "drm_hal_vendor_test.cpp",
+ ],
srcs: [
"drm_hal_clearkey_test.cpp",
"drm_hal_vendor_test.cpp",
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index 656ec50..760b67e 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -32,6 +32,9 @@
local_include_dirs: [
"include",
],
+ tidy_timeout_srcs: [
+ "drm_hal_clearkey_test.cpp",
+ ],
srcs: [
"drm_hal_clearkey_test.cpp",
],
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index ca90ee9..dd22ebe 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -29,6 +29,9 @@
local_include_dirs: [
"include",
],
+ tidy_timeout_srcs: [
+ "drm_hal_test.cpp",
+ ],
srcs: [
"drm_hal_clearkey_module.cpp",
"drm_hal_common.cpp",
diff --git a/drm/1.4/vts/OWNERS b/drm/1.4/vts/OWNERS
index a652208..3a0672e 100644
--- a/drm/1.4/vts/OWNERS
+++ b/drm/1.4/vts/OWNERS
@@ -1,6 +1,8 @@
+conglin@google.com
edwinwong@google.com
fredgc@google.com
jtinker@google.com
+juce@google.com
kylealexander@google.com
rfrias@google.com
robertshih@google.com
diff --git a/drm/aidl/OWNERS b/drm/aidl/OWNERS
new file mode 100644
index 0000000..fa8fd20
--- /dev/null
+++ b/drm/aidl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+edwinwong@google.com
+kelzhan@google.com
+robertshih@google.com
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index e18eade..22d836b 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -34,7 +34,6 @@
enabled: false,
},
ndk: {
- separate_platform_variant: false,
vndk: {
enabled: true,
},
diff --git a/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
index 3b42546..b994d04 100644
--- a/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
+++ b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
@@ -103,8 +103,9 @@
* @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
* If execution runs longer than this, the IDumpstateDevice service may be killed and only
* partial information will be included in the report.
- * @return If error, return service specific error with code
- * ERROR_UNSUPPORTED_MODE or ERROR_DEVICE_LOGGING_NOT_ENABLED
+ * @throws ServiceSpecificException with one of the following values:
+ * |ERROR_UNSUPPORTED_MODE|,
+ * |ERROR_DEVICE_LOGGING_NOT_ENABLED|
*/
void dumpstateBoard(in ParcelFileDescriptor[] fd, in DumpstateMode mode, in long timeoutMillis);
diff --git a/dumpstate/aidl/default/main.cpp b/dumpstate/aidl/default/main.cpp
index 2451752..5bc85b4 100644
--- a/dumpstate/aidl/default/main.cpp
+++ b/dumpstate/aidl/default/main.cpp
@@ -29,7 +29,7 @@
const std::string instance = std::string() + Dumpstate::descriptor + "/default";
binder_status_t status =
AServiceManager_registerLazyService(dumpstate->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // Unreachable
diff --git a/gnss/aidl/default/service.cpp b/gnss/aidl/default/service.cpp
index 09f1ad2..bbe34f1 100644
--- a/gnss/aidl/default/service.cpp
+++ b/gnss/aidl/default/service.cpp
@@ -42,7 +42,7 @@
const std::string instance = std::string() + Gnss::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(gnssAidl->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
sp<IGnss> gnss = new GnssHidlHal(gnssAidl);
configureRpcThreadpool(1, true /* will join */);
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index b484f9c..0cd782e 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -53,17 +53,16 @@
/*
* TestPsdsExtension:
- * 1. Gets the PsdsExtension and verifies that it returns a non-null extension.
+ * 1. Gets the PsdsExtension
* 2. Injects empty PSDS data and verifies that it returns an error.
*/
TEST_P(GnssHalTest, TestPsdsExtension) {
sp<IGnssPsds> iGnssPsds;
auto status = aidl_gnss_hal_->getExtensionPsds(&iGnssPsds);
- ASSERT_TRUE(status.isOk());
- ASSERT_TRUE(iGnssPsds != nullptr);
-
- status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector<uint8_t>());
- ASSERT_FALSE(status.isOk());
+ if (status.isOk() && iGnssPsds != nullptr) {
+ status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector<uint8_t>());
+ ASSERT_FALSE(status.isOk());
+ }
}
void CheckSatellitePvt(const SatellitePvt& satellitePvt) {
diff --git a/graphics/OWNERS b/graphics/OWNERS
new file mode 100644
index 0000000..75ceb23
--- /dev/null
+++ b/graphics/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 1075130
+
+# Graphics team
+adyabr@google.com
+alecmouri@google.com
+chrisforbes@google.com
+jreck@google.com
+lpy@google.com
+sumir@google.com
\ No newline at end of file
diff --git a/graphics/common/OWNERS b/graphics/common/OWNERS
new file mode 100644
index 0000000..94999ea
--- /dev/null
+++ b/graphics/common/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1075130
+adyabr@google.com
+alecmouri@google.com
+jreck@google.com
+scroggo@google.com
diff --git a/graphics/composer/2.1/default/OWNERS b/graphics/composer/2.1/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.1/default/OWNERS
+++ b/graphics/composer/2.1/default/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.1/utils/OWNERS b/graphics/composer/2.1/utils/OWNERS
index 7af69b4..83c4f5f 100644
--- a/graphics/composer/2.1/utils/OWNERS
+++ b/graphics/composer/2.1/utils/OWNERS
@@ -1,2 +1,3 @@
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
index 1ead138..ccbc5b1 100644
--- a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -30,7 +30,7 @@
std::vector<Display> GraphicsComposerCallback::getDisplays() const {
std::lock_guard<std::mutex> lock(mMutex);
- return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+ return mDisplays;
}
int GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -51,12 +51,17 @@
Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
std::lock_guard<std::mutex> lock(mMutex);
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
if (connection == Connection::CONNECTED) {
- if (!mDisplays.insert(display).second) {
+ if (it == mDisplays.end()) {
+ mDisplays.push_back(display);
+ } else {
mInvalidHotplugCount++;
}
} else if (connection == Connection::DISCONNECTED) {
- if (!mDisplays.erase(display)) {
+ if (it != mDisplays.end()) {
+ mDisplays.erase(it);
+ } else {
mInvalidHotplugCount++;
}
}
@@ -67,7 +72,8 @@
Return<void> GraphicsComposerCallback::onRefresh(Display display) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidRefreshCount++;
}
@@ -77,7 +83,8 @@
Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
std::lock_guard<std::mutex> lock(mMutex);
- if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (!mVsyncAllowed || it == mDisplays.end()) {
mInvalidVsyncCount++;
}
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
index e3c348f..da64052 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -19,7 +19,7 @@
#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
#include <mutex>
-#include <unordered_set>
+#include <vector>
namespace android {
namespace hardware {
@@ -48,7 +48,7 @@
mutable std::mutex mMutex;
// the set of all currently connected displays
- std::unordered_set<Display> mDisplays;
+ std::vector<Display> mDisplays;
// true only when vsync is enabled
bool mVsyncAllowed = true;
diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
index ea06752..a643bbd 100644
--- a/graphics/composer/2.1/vts/OWNERS
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -1,5 +1,6 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
# VTS team
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index eb67d34..9ffd7d5 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalGraphicsComposerV2_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
// TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.1/vts/functional/OWNERS b/graphics/composer/2.1/vts/functional/OWNERS
index a2ed8c8..3d970d1 100644
--- a/graphics/composer/2.1/vts/functional/OWNERS
+++ b/graphics/composer/2.1/vts/functional/OWNERS
@@ -1,2 +1,4 @@
# Bug component: 25423
+adyabr@google.com
+alecmouri@google.com
sumir@google.com
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
index 709c4d1..e8f584d 100644
--- a/graphics/composer/2.2/default/OWNERS
+++ b/graphics/composer/2.2/default/OWNERS
@@ -1,3 +1,5 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
+
diff --git a/graphics/composer/2.2/utils/OWNERS b/graphics/composer/2.2/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.2/utils/OWNERS
+++ b/graphics/composer/2.2/utils/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 36f3c00..e45696d 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -30,6 +30,10 @@
// Needed for librenderengine
"skia_deps",
],
+ tidy_timeout_srcs: [
+ "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
+ "VtsHalGraphicsComposerV2_2TargetTest.cpp",
+ ],
srcs: [
"VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
"VtsHalGraphicsComposerV2_2TargetTest.cpp",
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 25423
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
sumir@google.com
diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.3/default/OWNERS
+++ b/graphics/composer/2.3/default/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.3/utils/OWNERS
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index d27a151..70384ac 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalGraphicsComposerV2_3TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
// TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 25423
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
sumir@google.com
diff --git a/graphics/composer/2.4/default/OWNERS b/graphics/composer/2.4/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.4/default/OWNERS
+++ b/graphics/composer/2.4/default/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.4/utils/OWNERS b/graphics/composer/2.4/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.4/utils/OWNERS
+++ b/graphics/composer/2.4/utils/OWNERS
@@ -1,3 +1,4 @@
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
diff --git a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
index c9366a8..51e1ab7 100644
--- a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
@@ -25,7 +25,7 @@
std::vector<Display> GraphicsComposerCallback::getDisplays() const {
std::lock_guard<std::mutex> lock(mMutex);
- return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+ return mDisplays;
}
int32_t GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -71,12 +71,17 @@
Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
std::lock_guard<std::mutex> lock(mMutex);
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
if (connection == Connection::CONNECTED) {
- if (!mDisplays.insert(display).second) {
+ if (it == mDisplays.end()) {
+ mDisplays.push_back(display);
+ } else {
mInvalidHotplugCount++;
}
} else if (connection == Connection::DISCONNECTED) {
- if (!mDisplays.erase(display)) {
+ if (it != mDisplays.end()) {
+ mDisplays.erase(it);
+ } else {
mInvalidHotplugCount++;
}
}
@@ -87,7 +92,8 @@
Return<void> GraphicsComposerCallback::onRefresh(Display display) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidRefreshCount++;
}
@@ -106,7 +112,8 @@
Return<void> GraphicsComposerCallback::onVsync_2_4(Display display, int64_t, VsyncPeriodNanos) {
std::lock_guard<std::mutex> lock(mMutex);
- if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (!mVsyncAllowed || it == mDisplays.end()) {
mInvalidVsync_2_4Count++;
}
@@ -117,7 +124,8 @@
Display display, const VsyncPeriodChangeTimeline& updatedTimeline) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidVsyncPeriodChangeCount++;
}
@@ -134,4 +142,4 @@
return Void();
}
-} // namespace android::hardware::graphics::composer::V2_4::vts
\ No newline at end of file
+} // namespace android::hardware::graphics::composer::V2_4::vts
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
index f4e23ae..c03070b 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
@@ -18,7 +18,7 @@
#include <android/hardware/graphics/composer/2.4/IComposerCallback.h>
#include <mutex>
-#include <unordered_set>
+#include <vector>
namespace android::hardware::graphics::composer::V2_4::vts {
@@ -56,7 +56,7 @@
mutable std::mutex mMutex;
// the set of all currently connected displays
- std::unordered_set<Display> mDisplays;
+ std::vector<Display> mDisplays;
// true only when vsync is enabled
bool mVsyncAllowed = true;
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 6089e2d..22ae7c4 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalGraphicsComposerV2_4TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
// TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.4/vts/functional/OWNERS b/graphics/composer/2.4/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.4/vts/functional/OWNERS
+++ b/graphics/composer/2.4/vts/functional/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 25423
# Graphics team
adyabr@google.com
+alecmouri@google.com
lpy@google.com
sumir@google.com
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index b071f71..fa294ff 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -161,7 +161,8 @@
return mGralloc->allocate(
width, height, /*layerCount*/ 1,
static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
- static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY));
}
struct TestParameters {
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp
index 0fcac19..597fb50 100644
--- a/health/2.0/vts/functional/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalHealthV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
static_libs: [
"libgflags",
diff --git a/health/2.1/vts/OWNERS b/health/2.1/vts/OWNERS
index 20450ba..a6803cd 100644
--- a/health/2.1/vts/OWNERS
+++ b/health/2.1/vts/OWNERS
@@ -1,3 +1,2 @@
elsk@google.com
-hridya@google.com
sspatil@google.com
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index 6e2f1d4..86bca69 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -37,7 +37,6 @@
sdk_version: "module_current",
},
ndk: {
- separate_platform_variant: false,
vndk: {
enabled: true,
},
@@ -63,9 +62,11 @@
"android.hardware.health@2.0",
"android.hardware.health@2.1",
],
- defaults: [
- "libbinder_ndk_host_user",
- ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
java_library {
diff --git a/health/aidl/README.md b/health/aidl/README.md
index a64fe93..54d6758 100644
--- a/health/aidl/README.md
+++ b/health/aidl/README.md
@@ -60,7 +60,11 @@
[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc).
Specifically:
-* You may ignore the `service` line. The name of the service does not matter.
+* For the `service` line, if the name of the service is **NOT**
+ `vendor.charger`, and there are actions
+ in the rc file triggered by `on property:init.svc.<name>=running` where
+ `<name>` is the name of your charger service, then you need a custom health
+ AIDL service.
* If your service belongs to additional classes beside `charger`, you need a
custom health AIDL service.
* Modify the `seclabel` line. Replace `charger` with `charger_vendor`.
@@ -232,13 +236,19 @@
It is recommended that you move the existing `service` entry with
`class charger` to the `init.rc` file in your custom health service.
+If there are existing actions in the rc file triggered by
+`on property:init.svc.<name>=running`, where `<name>` is the name of your
+existing charger service (usually `vendor.charger`), then the name of the
+service must be kept as-is. If you modify the name of the service, the actions
+are not triggered properly.
+
Modify the entry to invoke the health service binary with `--charger` argument.
See
[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc)
for an example:
```text
-service vendor.charger-tuna /vendor/bin/hw/android.hardware.health-service-tuna --charger
+service vendor.charger /vendor/bin/hw/android.hardware.health-service-tuna --charger
class charger
seclabel u:r:charger_vendor:s0
# ...
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
index 34a87a6..97d9e84 100644
--- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
@@ -37,6 +37,7 @@
boolean chargerAcOnline;
boolean chargerUsbOnline;
boolean chargerWirelessOnline;
+ boolean chargerDockOnline;
int maxChargingCurrentMicroamps;
int maxChargingVoltageMicrovolts;
android.hardware.health.BatteryStatus batteryStatus;
diff --git a/health/aidl/android/hardware/health/HealthInfo.aidl b/health/aidl/android/hardware/health/HealthInfo.aidl
index 504e218..5b98baf 100644
--- a/health/aidl/android/hardware/health/HealthInfo.aidl
+++ b/health/aidl/android/hardware/health/HealthInfo.aidl
@@ -40,6 +40,10 @@
*/
boolean chargerWirelessOnline;
/**
+ * Dock charger state - 'true' if online
+ */
+ boolean chargerDockOnline;
+ /**
* Maximum charging current supported by charger in µA
*/
int maxChargingCurrentMicroamps;
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index 8aa7638..8eab997 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -120,6 +120,15 @@
},
}
+// Users of libhealth_aidl_impl should use this defaults.
+cc_defaults {
+ name: "libhealth_aidl_impl_user",
+ defaults: [
+ "libhealth_aidl_common_defaults",
+ "libhealth_aidl_charger_defaults",
+ ],
+}
+
// AIDL version of android.hardware.health@2.1-service.
// Default binder service of the health HAL.
cc_defaults {
@@ -127,8 +136,7 @@
relative_install_path: "hw",
vintf_fragments: ["android.hardware.health-service.example.xml"],
defaults: [
- "libhealth_aidl_common_defaults",
- "libhealth_aidl_charger_defaults",
+ "libhealth_aidl_impl_user",
],
static_libs: [
"libhealth_aidl_impl",
diff --git a/health/aidl/default/HalHealthLoop.cpp b/health/aidl/default/HalHealthLoop.cpp
index c9a081e..ec23c10 100644
--- a/health/aidl/default/HalHealthLoop.cpp
+++ b/health/aidl/default/HalHealthLoop.cpp
@@ -61,7 +61,7 @@
void HalHealthLoop::set_charger_online(const HealthInfo& health_info) {
charger_online_ = health_info.chargerAcOnline || health_info.chargerUsbOnline ||
- health_info.chargerWirelessOnline;
+ health_info.chargerWirelessOnline || health_info.chargerDockOnline;
}
} // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index e1d1982..d41d01a 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -130,12 +130,7 @@
ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) {
battery_monitor_.updateValues();
- // TODO(b/177269435): BatteryMonitor should store AIDL HealthInfo instead.
- auto health_info_2_1 = battery_monitor_.getHealthInfo_2_1();
- if (!::android::h2a::translate(health_info_2_1, out)) {
- return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
- IHealth::STATUS_UNKNOWN, "Cannot translate HIDL HealthInfo to AIDL");
- }
+ *out = battery_monitor_.getHealthInfo();
// Fill in storage infos; these aren't retrieved by BatteryMonitor.
if (auto res = getStorageInfo(&out->storageInfos); !res.isOk()) {
diff --git a/health/aidl/default/android.hardware.health-service.example.rc b/health/aidl/default/android.hardware.health-service.example.rc
index 4258890..e052024 100644
--- a/health/aidl/default/android.hardware.health-service.example.rc
+++ b/health/aidl/default/android.hardware.health-service.example.rc
@@ -5,7 +5,7 @@
capabilities WAKE_ALARM BLOCK_SUSPEND
file /dev/kmsg w
-service vendor.charger-default /vendor/bin/hw/android.hardware.health-service.example --charger
+service vendor.charger /vendor/bin/hw/android.hardware.health-service.example --charger
class charger
seclabel u:r:charger_vendor:s0
user system
diff --git a/health/aidl/default/health-convert.cpp b/health/aidl/default/health-convert.cpp
index b5251f4..6118865 100644
--- a/health/aidl/default/health-convert.cpp
+++ b/health/aidl/default/health-convert.cpp
@@ -22,6 +22,7 @@
p->chargerAcOnline = info.chargerAcOnline;
p->chargerUsbOnline = info.chargerUsbOnline;
p->chargerWirelessOnline = info.chargerWirelessOnline;
+ p->chargerDockOnline = info.chargerDockOnline;
p->maxChargingCurrent = info.maxChargingCurrentMicroamps;
p->maxChargingVoltage = info.maxChargingVoltageMicrovolts;
p->batteryStatus = static_cast<int>(info.batteryStatus);
diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp
index 434f565..f9da79f 100644
--- a/health/aidl/vts/functional/Android.bp
+++ b/health/aidl/vts/functional/Android.bp
@@ -29,6 +29,9 @@
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
+ tidy_timeout_srcs: [
+ "VtsHalHealthTargetTest.cpp",
+ ],
srcs: [
"VtsHalHealthTargetTest.cpp",
],
@@ -43,6 +46,7 @@
"libhealthtest_headers",
],
test_suites: [
+ "general-tests",
"vts",
],
}
diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp
index 3f4b5bc..4190769 100644
--- a/health/utils/libhealthloop/HealthLoop.cpp
+++ b/health/utils/libhealthloop/HealthLoop.cpp
@@ -40,8 +40,6 @@
using namespace android;
using namespace std::chrono_literals;
-#define POWER_SUPPLY_SUBSYSTEM "power_supply"
-
namespace android {
namespace hardware {
namespace health {
@@ -143,7 +141,7 @@
cp = msg;
while (*cp) {
- if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
+ if (!strcmp(cp, "SUBSYSTEM=power_supply")) {
ScheduleBatteryUpdate();
break;
}
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
index 311e951..3a1415f 100644
--- a/health/utils/libhealthshim/Android.bp
+++ b/health/utils/libhealthshim/Android.bp
@@ -24,9 +24,11 @@
cc_defaults {
name: "libhealthshim_defaults",
host_supported: true, // for testing
- defaults: [
- "libbinder_ndk_host_user",
- ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
cflags: [
"-Wall",
"-Werror",
@@ -68,6 +70,9 @@
"libhealthshim",
"libgmock",
],
+ tidy_timeout_srcs: [
+ "test.cpp",
+ ],
srcs: [
"test.cpp",
],
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index dad3b8d..e3b8191 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -15,6 +15,7 @@
],
imports: [
"android.hardware.keymaster",
+ "android.hardware.security.keymint",
],
stability: "vintf",
backend: {
@@ -25,6 +26,7 @@
vndk: {
enabled: true,
},
+ apps_enabled: false,
},
},
versions: [
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
index d8a8128..83e1797 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
index 2685525..e6ec04e 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
index f8d5a9e..9b96ea8 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -38,4 +39,5 @@
int dataChunkSize;
boolean isDirectAccess;
@utf8InCpp String[] supportedDocTypes;
+ boolean isRemoteKeyProvisioningSupported = false;
}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
index 3224e4b..5065641 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
index c6fb3c8..31ca8b1 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -36,6 +37,8 @@
android.hardware.identity.HardwareInformation getHardwareInformation();
android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
+ android.hardware.identity.IPresentationSession createPresentationSession(in android.hardware.identity.CipherSuite cipherSuite);
+ android.hardware.security.keymint.IRemotelyProvisionedComponent getRemotelyProvisionedComponent();
const int STATUS_OK = 0;
const int STATUS_FAILED = 1;
const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
new file mode 100644
index 0000000..705dc29
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IPresentationSession {
+ byte[] getEphemeralKeyPair();
+ long getAuthChallenge();
+ void setReaderEphemeralPublicKey(in byte[] publicKey);
+ void setSessionTranscript(in byte[] sessionTranscript);
+ android.hardware.identity.IIdentityCredential getCredential(in byte[] credentialData);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
index 19a29ec..5377349 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -40,4 +41,5 @@
byte[] addEntryValue(in byte[] content);
@SuppressWarnings(value={"out-array"}) void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
+ void setRemotelyProvisionedAttestationKey(in byte[] attestationKeyBlob, in byte[] attestationCertificate);
}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
index c9c2b9f..cec8e0c 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
index aaf1e20..05b9ec2 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
index 695fb3f..2003594 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -12,7 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/identity/aidl/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
index d67739d..acd13b6 100644
--- a/identity/aidl/android/hardware/identity/HardwareInformation.aidl
+++ b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
@@ -51,4 +51,19 @@
*
*/
@utf8InCpp String[] supportedDocTypes;
+
+ /**
+ * isRemoteKeyProvisioningSupported indicates whether or not the underlying implementation
+ * supports a remotely provisioned key for attestation or not. If this field is false, then
+ * the implementation only uses a factory-installed, fixed attestation key. If this field is
+ * true, then an IRemotelyProvisionedComponent is associated with the IIdentityCredentialStore,
+ * and a remotely provisioned key blob may be provided for credential key attestation.
+ *
+ * Note that remote provisioning is not required, even when it is supported. Implementations
+ * MUST use a factory-installed attestation key as a fallback for when there are no
+ * remotely provisioned keys available. This behavior mirrors keystore key attestation.
+ *
+ * This field was added in API version 4.
+ */
+ boolean isRemoteKeyProvisioningSupported = false;
}
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 8ae293b..82b0a83 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -17,9 +17,9 @@
package android.hardware.identity;
import android.hardware.identity.Certificate;
+import android.hardware.identity.IWritableIdentityCredential;
import android.hardware.identity.RequestNamespace;
import android.hardware.identity.SecureAccessControlProfile;
-import android.hardware.identity.IWritableIdentityCredential;
import android.hardware.keymaster.HardwareAuthToken;
import android.hardware.keymaster.VerificationToken;
@@ -44,6 +44,9 @@
* This method was deprecated in API version 3 because there's no challenge so freshness
* can't be checked. Use deleteCredentalWithChallenge() instead.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @return a COSE_Sign1 signature described above
* @deprecated use deleteCredentalWithChallenge() instead.
*/
@@ -60,6 +63,9 @@
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @return the private key, in DER format as specified in RFC 5915.
*/
byte[] createEphemeralKeyPair();
@@ -70,6 +76,9 @@
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @param publicKey contains the reader's ephemeral public key, in uncompressed
* form (e.g. 0x04 || X || Y).
*/
@@ -83,6 +92,9 @@
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned. If user authentication is not needed, this method may not be called.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @return challenge, a non-zero number.
*/
long createAuthChallenge();
@@ -371,6 +383,9 @@
* This CBOR enables an issuer to determine the exact state of the credential it
* returns issuer-signed data for.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @param out signingKeyBlob contains an AES-GCM-ENC(storageKey, R, signingKey, docType)
* where signingKey is an EC private key in uncompressed form. That is, the returned
* blob is an encrypted copy of the newly-generated private signing key.
@@ -420,8 +435,12 @@
*
* This method was introduced in API version 3.
*
- * @param challenge a challenge set by the issuer to ensure freshness. Maximum size is 32 bytes
- * and it may be empty. Fails with STATUS_INVALID_DATA if bigger than 32 bytes.
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
+ * @param challenge a challenge set by the issuer to ensure freshness. Implementations must
+ * support challenges that are at least 32 bytes. Fails with STATUS_INVALID_DATA if bigger
+ * than 32 bytes.
* @return a COSE_Sign1 signature described above.
*/
byte[] deleteCredentialWithChallenge(in byte[] challenge);
@@ -442,8 +461,12 @@
*
* This method was introduced in API version 3.
*
- * @param challenge a challenge set by the issuer to ensure freshness. Maximum size is 32 bytes
- * and it may be empty. Fails with STATUS_INVALID_DATA if bigger than 32 bytes.
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
+ * @param challenge a challenge set by the issuer to ensure freshness. Implementations must
+ * support challenges that are at least 32 bytes. Fails with STATUS_INVALID_DATA if bigger
+ * than 32 bytes.
* @return a COSE_Sign1 signature described above.
*/
byte[] proveOwnership(in byte[] challenge);
@@ -456,6 +479,9 @@
*
* This method was introduced in API version 3.
*
+ * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+ * STATUS_FAILED must be returned.
+ *
* @return an IWritableIdentityCredential
*/
IWritableIdentityCredential updateCredential();
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index 638be79..d3e4da0 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -16,10 +16,12 @@
package android.hardware.identity;
-import android.hardware.identity.IIdentityCredential;
-import android.hardware.identity.IWritableIdentityCredential;
-import android.hardware.identity.HardwareInformation;
import android.hardware.identity.CipherSuite;
+import android.hardware.identity.HardwareInformation;
+import android.hardware.identity.IIdentityCredential;
+import android.hardware.identity.IPresentationSession;
+import android.hardware.identity.IWritableIdentityCredential;
+import android.hardware.security.keymint.IRemotelyProvisionedComponent;
/**
* IIdentityCredentialStore provides an interface to a secure store for user identity documents.
@@ -105,7 +107,7 @@
* STATUS_* integers defined in this interface. Each method states which status can be returned
* and under which circumstances.
*
- * The API described here is API version 3 which corresponds to feature version 202101
+ * The API described here is API version 4 which corresponds to feature version 202201
* of the android.security.identity Framework API. An XML file declaring the feature
* android.hardware.identity_credential (or android.hardware.identity_credential.direct_access
* if implementing the Direct Access HAL) should be included declaring this feature version.
@@ -214,16 +216,16 @@
* @return an IWritableIdentityCredential interface that provides operations to
* provision a credential.
*/
- IWritableIdentityCredential createCredential(in @utf8InCpp String docType,
- in boolean testCredential);
+ IWritableIdentityCredential createCredential(
+ in @utf8InCpp String docType, in boolean testCredential);
/**
* getCredential retrieves an IIdentityCredential interface which allows use of a stored
* Credential.
*
- * The cipher suite used to communicate with the remote verifier must also be specified. Currently
- * only a single cipher-suite is supported. Support for other cipher suites may be added in a
- * future version of this HAL.
+ * The cipher suite used to communicate with the remote verifier must also be specified.
+ * Currently only a single cipher-suite is supported. Support for other cipher suites may be
+ * added in a future version of this HAL.
*
* This method fails with STATUS_INVALID_DATA if the passed in credentialData cannot be
* decoded or decrypted.
@@ -241,4 +243,44 @@
* @return an IIdentityCredential interface that provides operations on the Credential.
*/
IIdentityCredential getCredential(in CipherSuite cipherSuite, in byte[] credentialData);
+
+ /**
+ * createPresentationSession creates IPresentationSession interface which can be used to
+ * present one or more credentials to a remote verifier device.
+ *
+ * The cipher suite used to communicate with the remote verifier must be specified. Currently
+ * only a single cipher-suite is supported. Support for other cipher suites may be added in a
+ * future version of this HAL. If the requested cipher suite is not support the call fails
+ * with STATUS_CIPHER_SUITE_NOT_SUPPORTED.
+ *
+ * In this version of the HAL, implementations are only required to support a single session
+ * being active. In a future version, implementations may be required to support multiple
+ * presentation sessions being active at the same time.
+ *
+ * This method was introduced in API version 4.
+ *
+ * @param cipherSuite The cipher suite to use.
+ *
+ * @return an IPresentationSession interface.
+ */
+ IPresentationSession createPresentationSession(in CipherSuite cipherSuite);
+
+ /**
+ * Fetch the IRemotelyProvisionedComponent that is used to generate attestation keys for
+ * remote provisionining. Keys generated by this component are to be certified by a remote
+ * provisionined authority, then used to attest to credential keys via
+ * IWritableIdentityCredential.setRemotelyProvisionedAttestationKey.
+ *
+ * Support for this method is indicated by HardwareInformation. If the
+ * |isRemoteKeyProvisioningSupported| field is false, this method will fail with
+ * EX_UNSUPPORTED_OPERATION.
+ *
+ * This method was added in API version 4.
+ *
+ * @see
+ * android.hardware.identity.IWritableIdentityCredential#setRemotelyProvisionedAttestationKey
+ *
+ * @return an IRemotelyProvisionedComponent that is used to generate attestation keys.
+ */
+ IRemotelyProvisionedComponent getRemotelyProvisionedComponent();
}
diff --git a/identity/aidl/android/hardware/identity/IPresentationSession.aidl b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
new file mode 100644
index 0000000..b0449f0
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.identity;
+
+import android.hardware.identity.CipherSuite;
+import android.hardware.identity.IIdentityCredential;
+
+/**
+ * An interface to present multiple credentials in the same session.
+ *
+ * This interface was introduced in API version 4.
+ *
+ */
+@VintfStability
+interface IPresentationSession {
+ /**
+ * Gets the ephemeral EC key pair to be used in establishing a secure session with a reader.
+ * This method returns the private key so the caller can perform an ECDH key agreement operation
+ * with the reader. The reason for generating the key pair in the secure environment is so that
+ * the secure environment knows what public key to expect to find in the session transcript
+ * when presenting credentials.
+ *
+ * The generated key matches the selected cipher suite of the presentation session (e.g. EC
+ * key using the P-256 curve).
+ *
+ * @return the private key, in DER format as specified in RFC 5915.
+ */
+ byte[] getEphemeralKeyPair();
+
+ /**
+ * Gets the challenge value to be used for proving successful user authentication. This
+ * is to be included in the authToken passed to the IIdentityCredential.startRetrieval()
+ * method and the verificationToken passed to the IIdentityCredential.setVerificationToken()
+ * method.
+ *
+ * @return challenge, a non-zero number.
+ */
+ long getAuthChallenge();
+
+ /**
+ * Sets the public part of the reader's ephemeral key pair to be used to complete
+ * an ECDH key agreement for the session.
+ *
+ * The curve of the key must match the curve for the key returned by getEphemeralKeyPair().
+ *
+ * This method may only be called once per instance. If called more than once, STATUS_FAILED
+ * must be returned.
+ *
+ * @param publicKey contains the reader's ephemeral public key, in uncompressed
+ * form (e.g. 0x04 || X || Y).
+ */
+ void setReaderEphemeralPublicKey(in byte[] publicKey);
+
+ /**
+ * Sets the session transcript for the session.
+ *
+ * This can be empty but if it's non-empty it must be valid CBOR.
+ *
+ * This method may only be called once per instance. If called more than once, STATUS_FAILED
+ * must be returned.
+ *
+ * @param sessionTrancsript the session transcript.
+ */
+ void setSessionTranscript(in byte[] sessionTranscript);
+
+ /**
+ * getCredential() retrieves an IIdentityCredential interface for presentation in the
+ * current presentation session.
+ *
+ * On the returned instance only the methods startRetrieval(), startRetrieveEntryValue(),
+ * retrieveEntryValue(), finishRetrieval(), setRequestedNamespaces(), setVerificationToken()
+ * may be called. Other methods will fail with STATUS_FAILED.
+ *
+ * The implementation is expected to get the session transcript, ephemeral key, reader
+ * ephemeral key, and auth challenge from this instance.
+ *
+ * @param credentialData is a CBOR-encoded structure containing metadata about the credential
+ * and an encrypted byte array that contains data used to secure the credential. See the
+ * return argument of the same name in IWritableIdentityCredential.finishAddingEntries().
+ *
+ * Note that the format of credentialData may depend on the feature version.
+ * Implementations must support credentialData created by an earlier feature version.
+ *
+ * @return an IIdentityCredential interface that provides operations on the Credential.
+ */
+ IIdentityCredential getCredential(in byte[] credentialData);
+}
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 22bcf61..1c80cbb 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -127,11 +127,13 @@
* https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
*
* @param attestationChallenge a challenge set by the issuer to ensure freshness. If
- * this is empty, the call fails with STATUS_INVALID_DATA.
+ * this is empty, the call fails with STATUS_INVALID_DATA. Implementations must
+ * support challenges of at least 32 bytes.
*
* @return the X.509 certificate chain for the credentialKey
*/
- Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
+ Certificate[] getAttestationCertificate(
+ in byte[] attestationApplicationId, in byte[] attestationChallenge);
/**
* Start the personalization process.
@@ -183,11 +185,11 @@
* in the secure environment. If this requirement is not met the call fails with
* STATUS_INVALID_DATA.
*
- * @return a structure with the passed-in data and MAC created with storageKey for authenticating
- * the data at a later point in time.
+ * @return a structure with the passed-in data and MAC created with storageKey for
+ * authenticating the data at a later point in time.
*/
SecureAccessControlProfile addAccessControlProfile(in int id, in Certificate readerCertificate,
- in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
+ in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
/**
* Begins the process of adding an entry to the credential. All access control profiles must be
@@ -209,7 +211,7 @@
* is not met this method fails with STATUS_INVALID_DATA.
*/
void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace,
- in @utf8InCpp String name, in int entrySize);
+ in @utf8InCpp String name, in int entrySize);
/**
* Continues the process of adding an entry, providing a value or part of a value.
@@ -221,8 +223,8 @@
* chunk sizes must equal the value of the beginAddEntry() entrySize argument. If this
* requirement is not met the call fails with STATUS_INVALID_DATA.
*
- * @param content is the entry value, encoded as CBOR. In the case the content exceeds gcmChunkSize,
- * this may be partial content up to gcmChunkSize bytes long.
+ * @param content is the entry value, encoded as CBOR. In the case the content exceeds
+ * gcmChunkSize, this may be partial content up to gcmChunkSize bytes long.
*
* @return the encrypted and MACed content. For directly-available credentials the contents are
* implementation-defined. For other credentials, the result contains
@@ -321,8 +323,7 @@
* }
*/
@SuppressWarnings(value={"out-array"})
- void finishAddingEntries(out byte[] credentialData,
- out byte[] proofOfProvisioningSignature);
+ void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
/**
* Sets the expected size of the ProofOfProvisioning returned by finishAddingEntries(). This
@@ -336,4 +337,35 @@
*/
void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
+ /**
+ * Sets the attestation key used to sign the credentialKey certificate. This method is used to
+ * support remotely provisioned attestation keys, removing the credential's dependency on any
+ * factory-provisioned attestation key.
+ *
+ * This method must be called before getAttestationCertificate. After this method is called,
+ * the certificate chain returned by getAttestationCertificate will contain a leaf certificate
+ * signed by attestationKeyBlob and the chain in attestationCertificate will make up the rest
+ * of the returned chain.
+ *
+ * Returns EX_UNSUPPORTED_FUNCTION if remote provisioning is not supported
+ * (see IIdentityCredentialStore.getHardwareInformation()).
+ *
+ * This method was added in API version 4.
+ *
+ * @param attestationKeyBlob is a key blob generated by the IRemotelyProvisionedComponent that
+ * is returned by ICredentialStore.getRemotelyProvisionedComponent. The format is vendor-
+ * specified, and matches the key blob returned by IKeyMintDevice.generateKey.
+ *
+ * @param attestationCertificate contains the X.509 certificate chain that certifies the
+ * attestationKeyBlob. This certificate is expected to have been remotely provisioned
+ * by a trusted authority. This parameter must contain a concatenated chain of DER-encoded
+ * X.509 certificates. The certificates must be ordered such that the attestation key
+ * certificate is first (starting at byte 0). The issuer certificate for the attestation
+ * certificate immediately follows, continuing this chain to the final, root certificate.
+ *
+ * @see getAttestationCertificate
+ * @see android.hardware.identity.ICredentialStore#getRemotelyProvisionedComponent
+ */
+ void setRemotelyProvisionedAttestationKey(
+ in byte[] attestationKeyBlob, in byte[] attestationCertificate);
}
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 3de8d30..32b3543 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -13,6 +13,7 @@
srcs: [
"common/IdentityCredential.cpp",
"common/IdentityCredentialStore.cpp",
+ "common/PresentationSession.cpp",
"common/WritableIdentityCredential.cpp",
],
export_include_dirs: [
@@ -39,8 +40,9 @@
"libsoft_attestation_cert",
"libpuresoftkeymasterdevice",
"android.hardware.identity-support-lib",
- "android.hardware.identity-V3-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.identity-V4-ndk",
+ "android.hardware.keymaster-V4-ndk",
+ "android.hardware.security.keymint-V2-ndk",
],
}
@@ -49,6 +51,7 @@
vendor_available: true,
srcs: [
"libeic/EicCbor.c",
+ "libeic/EicSession.c",
"libeic/EicPresentation.c",
"libeic/EicProvisioning.c",
"EicOpsImpl.cc",
@@ -79,6 +82,9 @@
init_rc: ["identity-default.rc"],
vintf_fragments: ["identity-default.xml"],
vendor: true,
+ defaults: [
+ "keymint_use_latest_hal_aidl_ndk_static",
+ ],
cflags: [
"-Wall",
"-Wextra",
@@ -100,8 +106,8 @@
"libsoft_attestation_cert",
"libpuresoftkeymasterdevice",
"android.hardware.identity-support-lib",
- "android.hardware.identity-V3-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.identity-V4-ndk",
+ "android.hardware.keymaster-V4-ndk",
"android.hardware.identity-libeic-hal-common",
"android.hardware.identity-libeic-library",
],
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
index 8ec4cc9..3fd9f1d 100644
--- a/identity/aidl/default/EicOpsImpl.cc
+++ b/identity/aidl/default/EicOpsImpl.cc
@@ -20,9 +20,13 @@
#include <tuple>
#include <vector>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <string.h>
+
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
-#include <string.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
@@ -63,6 +67,11 @@
return strlen(s);
}
+void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle,
+ size_t needleLen) {
+ return memmem(haystack, haystackLen, needle, needleLen);
+}
+
int eicCryptoMemCmp(const void* s1, const void* s2, size_t n) {
return CRYPTO_memcmp(s1, s2, n);
}
@@ -117,6 +126,25 @@
return true;
}
+bool eicNextId(uint32_t* id) {
+ uint32_t oldId = *id;
+ uint32_t newId = 0;
+
+ do {
+ union {
+ uint8_t value8;
+ uint32_t value32;
+ } value;
+ if (!eicOpsRandom(&value.value8, sizeof(value))) {
+ return false;
+ }
+ newId = value.value32;
+ } while (newId == oldId && newId == 0);
+
+ *id = newId;
+ return true;
+}
+
bool eicOpsEncryptAes128Gcm(
const uint8_t* key, // Must be 16 bytes
const uint8_t* nonce, // Must be 12 bytes
@@ -239,25 +267,42 @@
bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
size_t challengeSize, const uint8_t* applicationId,
- size_t applicationIdSize, bool testCredential, uint8_t* cert,
- size_t* certSize) {
- vector<uint8_t> challengeVec(challengeSize);
- memcpy(challengeVec.data(), challenge, challengeSize);
-
- vector<uint8_t> applicationIdVec(applicationIdSize);
- memcpy(applicationIdVec.data(), applicationId, applicationIdSize);
-
- optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
- android::hardware::identity::support::createEcKeyPairAndAttestation(
- challengeVec, applicationIdVec, testCredential);
- if (!ret) {
- eicDebug("Error generating CredentialKey and attestation");
- return false;
+ size_t applicationIdSize, bool testCredential,
+ const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize,
+ const uint8_t* attestationKeyCert, size_t attestationKeyCertSize,
+ uint8_t* cert, size_t* certSize) {
+ vector<uint8_t> flatChain;
+ vector<uint8_t> keyPair;
+ vector<uint8_t> challengeVec(challenge, challenge + challengeSize);
+ vector<uint8_t> applicationIdVec(applicationId, applicationId + applicationIdSize);
+ if (attestationKeyBlob && attestationKeyBlobSize > 0 && attestationKeyCert &&
+ attestationKeyCertSize > 0) {
+ vector<uint8_t> attestationKeyBlobVec(attestationKeyBlob,
+ attestationKeyBlob + attestationKeyBlobSize);
+ vector<uint8_t> attestationKeyCertVec(attestationKeyCert,
+ attestationKeyCert + attestationKeyCertSize);
+ optional<std::pair<vector<uint8_t>, vector<uint8_t>>> keyAndCert =
+ android::hardware::identity::support::createEcKeyPairWithAttestationKey(
+ challengeVec, applicationIdVec, attestationKeyBlobVec,
+ attestationKeyCertVec, testCredential);
+ if (!keyAndCert) {
+ eicDebug("Error generating CredentialKey and attestation");
+ return false;
+ }
+ keyPair = std::move(keyAndCert->first);
+ flatChain = std::move(keyAndCert->second);
+ } else {
+ optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
+ android::hardware::identity::support::createEcKeyPairAndAttestation(
+ challengeVec, applicationIdVec, testCredential);
+ if (!ret) {
+ eicDebug("Error generating CredentialKey and attestation");
+ return false;
+ }
+ keyPair = std::move(ret->first);
+ flatChain = android::hardware::identity::support::certificateChainJoin(ret->second);
}
- // Extract certificate chain.
- vector<uint8_t> flatChain =
- android::hardware::identity::support::certificateChainJoin(ret.value().second);
if (*certSize < flatChain.size()) {
eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
flatChain.size());
@@ -268,7 +313,7 @@
// Extract private key.
optional<vector<uint8_t>> privKey =
- android::hardware::identity::support::ecKeyPairGetPrivateKey(ret.value().first);
+ android::hardware::identity::support::ecKeyPairGetPrivateKey(keyPair);
if (!privKey) {
eicDebug("Error extracting private key");
return false;
@@ -492,10 +537,12 @@
#ifdef EIC_DEBUG
void eicPrint(const char* format, ...) {
+ char buf[1024];
va_list args;
va_start(args, format);
- vfprintf(stderr, format, args);
+ vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
+ LOG(INFO) << buf;
}
void eicHexdump(const char* message, const uint8_t* data, size_t dataSize) {
diff --git a/identity/aidl/default/EicTests.cpp b/identity/aidl/default/EicTests.cpp
index a28080d..7b69b75 100644
--- a/identity/aidl/default/EicTests.cpp
+++ b/identity/aidl/default/EicTests.cpp
@@ -66,7 +66,8 @@
// Then present data from it...
//
FakeSecureHardwarePresentationProxy presentationProxy;
- ASSERT_TRUE(presentationProxy.initialize(isTestCredential, docType, credData.value()));
+ ASSERT_TRUE(presentationProxy.initialize(0 /* sessionId */, isTestCredential, docType,
+ credData.value()));
AccessCheckResult res =
presentationProxy.startRetrieveEntryValue(nameSpace, name, 1, content.size(), acpIds);
ASSERT_EQ(res, AccessCheckResult::kNoAccessControlProfiles);
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.cpp b/identity/aidl/default/FakeSecureHardwareProxy.cpp
index f0307dc..9b9a749 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.cpp
+++ b/identity/aidl/default/FakeSecureHardwareProxy.cpp
@@ -23,6 +23,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <string.h>
+#include <map>
#include <openssl/sha.h>
@@ -52,47 +53,143 @@
// ----------------------------------------------------------------------
-FakeSecureHardwareProvisioningProxy::FakeSecureHardwareProvisioningProxy() {}
+// The singleton EicProvisioning object used everywhere.
+//
+EicProvisioning FakeSecureHardwareProvisioningProxy::ctx_;
-FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {}
-
-bool FakeSecureHardwareProvisioningProxy::shutdown() {
- LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
- return true;
+FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {
+ if (id_ != 0) {
+ shutdown();
+ }
}
bool FakeSecureHardwareProvisioningProxy::initialize(bool testCredential) {
- LOG(INFO) << "FakeSecureHardwareProvisioningProxy created, sizeof(EicProvisioning): "
- << sizeof(EicProvisioning);
- return eicProvisioningInit(&ctx_, testCredential);
+ if (id_ != 0) {
+ LOG(WARNING) << "Proxy is already initialized";
+ return false;
+ }
+ bool initialized = eicProvisioningInit(&ctx_, testCredential);
+ if (!initialized) {
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "Error getting id";
+ return false;
+ }
+ id_ = id.value();
+ return true;
}
bool FakeSecureHardwareProvisioningProxy::initializeForUpdate(
- bool testCredential, string docType, vector<uint8_t> encryptedCredentialKeys) {
- return eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
- docType.size(),
- encryptedCredentialKeys.data(),
- encryptedCredentialKeys.size());
+ bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) {
+ if (id_ != 0) {
+ LOG(WARNING) << "Proxy is already initialized";
+ return false;
+ }
+ bool initialized = eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
+ docType.size(), encryptedCredentialKeys.data(),
+ encryptedCredentialKeys.size());
+ if (!initialized) {
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "Error getting id";
+ return false;
+ }
+ id_ = id.value();
+ return true;
+}
+
+optional<uint32_t> FakeSecureHardwareProvisioningProxy::getId() {
+ uint32_t id;
+ if (!eicProvisioningGetId(&ctx_, &id)) {
+ return std::nullopt;
+ }
+ return id;
+}
+
+bool FakeSecureHardwareProvisioningProxy::validateId(const string& callerName) {
+ if (id_ == 0) {
+ LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+ << ": While validating expected id is 0";
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+ << ": Error getting id for validating";
+ return false;
+ }
+ if (id.value() != id_) {
+ LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+ << ": While validating expected id " << id_ << " but got " << id.value();
+ return false;
+ }
+ return true;
+}
+
+bool FakeSecureHardwareProvisioningProxy::shutdown() {
+ bool validated = validateId(__func__);
+ id_ = 0;
+ if (!validated) {
+ return false;
+ }
+ if (!eicProvisioningShutdown(&ctx_)) {
+ LOG(INFO) << "Error shutting down provisioning";
+ return false;
+ }
+ return true;
}
// Returns public key certificate.
optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKey(
const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
uint8_t publicKeyCert[4096];
size_t publicKeyCertSize = sizeof publicKeyCert;
if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
applicationId.data(), applicationId.size(),
- publicKeyCert, &publicKeyCertSize)) {
- return {};
+ /*attestationKeyBlob=*/nullptr,
+ /*attestationKeyBlobSize=*/0,
+ /*attestationKeyCert=*/nullptr,
+ /*attestationKeyCertSize=*/0, publicKeyCert,
+ &publicKeyCertSize)) {
+ return std::nullopt;
}
vector<uint8_t> pubKeyCert(publicKeyCertSize);
memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
return pubKeyCert;
}
+optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKeyUsingRkp(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attstationKeyCert) {
+ size_t publicKeyCertSize = 4096;
+ vector<uint8_t> publicKeyCert(publicKeyCertSize);
+ if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
+ applicationId.data(), applicationId.size(),
+ attestationKeyBlob.data(), attestationKeyBlob.size(),
+ attstationKeyCert.data(), attstationKeyCert.size(),
+ publicKeyCert.data(), &publicKeyCertSize)) {
+ LOG(ERROR) << "error creating credential key";
+ return std::nullopt;
+ }
+ publicKeyCert.resize(publicKeyCertSize);
+ return publicKeyCert;
+}
+
bool FakeSecureHardwareProvisioningProxy::startPersonalization(
- int accessControlProfileCount, vector<int> entryCounts, const string& docType,
+ int accessControlProfileCount, const vector<int>& entryCounts, const string& docType,
size_t expectedProofOfProvisioningSize) {
+ if (!validateId(__func__)) {
+ return false;
+ }
if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount,
entryCounts.data(),
@@ -108,13 +205,17 @@
optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addAccessControlProfile(
int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
uint64_t timeoutMillis, uint64_t secureUserId) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> mac(28);
uint8_t scratchSpace[512];
if (!eicProvisioningAddAccessControlProfile(
&ctx_, id, readerCertificate.data(), readerCertificate.size(),
userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(),
scratchSpace, sizeof(scratchSpace))) {
- return {};
+ return std::nullopt;
}
return mac;
}
@@ -122,6 +223,10 @@
bool FakeSecureHardwareProvisioningProxy::beginAddEntry(const vector<int>& accessControlProfileIds,
const string& nameSpace, const string& name,
uint64_t entrySize) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
uint8_t scratchSpace[512];
vector<uint8_t> uint8AccessControlProfileIds;
for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
@@ -138,6 +243,10 @@
optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addEntryValue(
const vector<int>& accessControlProfileIds, const string& nameSpace, const string& name,
const vector<uint8_t>& content) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> eicEncryptedContent;
uint8_t scratchSpace[512];
vector<uint8_t> uint8AccessControlProfileIds;
@@ -150,16 +259,20 @@
&ctx_, uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), content.data(),
content.size(), eicEncryptedContent.data(), scratchSpace, sizeof(scratchSpace))) {
- return {};
+ return std::nullopt;
}
return eicEncryptedContent;
}
// Returns signatureOfToBeSigned (EIC_ECDSA_P256_SIGNATURE_SIZE bytes).
optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishAddingEntries() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
if (!eicProvisioningFinishAddingEntries(&ctx_, signatureOfToBeSigned.data())) {
- return {};
+ return std::nullopt;
}
return signatureOfToBeSigned;
}
@@ -167,11 +280,15 @@
// Returns encryptedCredentialKeys.
optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishGetCredentialData(
const string& docType) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> encryptedCredentialKeys(116);
size_t size = encryptedCredentialKeys.size();
if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(), docType.size(),
encryptedCredentialKeys.data(), &size)) {
- return {};
+ return std::nullopt;
}
encryptedCredentialKeys.resize(size);
return encryptedCredentialKeys;
@@ -179,21 +296,200 @@
// ----------------------------------------------------------------------
-FakeSecureHardwarePresentationProxy::FakeSecureHardwarePresentationProxy() {}
+// The singleton EicSession object used everywhere.
+//
+EicSession FakeSecureHardwareSessionProxy::ctx_;
-FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {}
+FakeSecureHardwareSessionProxy::~FakeSecureHardwareSessionProxy() {
+ if (id_ != 0) {
+ shutdown();
+ }
+}
-bool FakeSecureHardwarePresentationProxy::initialize(bool testCredential, string docType,
- vector<uint8_t> encryptedCredentialKeys) {
- LOG(INFO) << "FakeSecureHardwarePresentationProxy created, sizeof(EicPresentation): "
- << sizeof(EicPresentation);
- return eicPresentationInit(&ctx_, testCredential, docType.c_str(), docType.size(),
- encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
+bool FakeSecureHardwareSessionProxy::initialize() {
+ if (id_ != 0) {
+ LOG(WARNING) << "Proxy is already initialized";
+ return false;
+ }
+ bool initialized = eicSessionInit(&ctx_);
+ if (!initialized) {
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "Error getting id";
+ return false;
+ }
+ id_ = id.value();
+ return true;
+}
+
+optional<uint32_t> FakeSecureHardwareSessionProxy::getId() {
+ uint32_t id;
+ if (!eicSessionGetId(&ctx_, &id)) {
+ return std::nullopt;
+ }
+ return id;
+}
+
+bool FakeSecureHardwareSessionProxy::shutdown() {
+ bool validated = validateId(__func__);
+ id_ = 0;
+ if (!validated) {
+ return false;
+ }
+ if (!eicSessionShutdown(&ctx_)) {
+ LOG(INFO) << "Error shutting down session";
+ return false;
+ }
+ return true;
+}
+
+bool FakeSecureHardwareSessionProxy::validateId(const string& callerName) {
+ if (id_ == 0) {
+ LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+ << ": While validating expected id is 0";
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+ << ": Error getting id for validating";
+ return false;
+ }
+ if (id.value() != id_) {
+ LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+ << ": While validating expected id " << id_ << " but got " << id.value();
+ return false;
+ }
+ return true;
+}
+
+optional<uint64_t> FakeSecureHardwareSessionProxy::getAuthChallenge() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
+ uint64_t authChallenge;
+ if (!eicSessionGetAuthChallenge(&ctx_, &authChallenge)) {
+ return std::nullopt;
+ }
+ return authChallenge;
+}
+
+optional<vector<uint8_t>> FakeSecureHardwareSessionProxy::getEphemeralKeyPair() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
+ vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
+ if (!eicSessionGetEphemeralKeyPair(&ctx_, priv.data())) {
+ return std::nullopt;
+ }
+ return priv;
+}
+
+bool FakeSecureHardwareSessionProxy::setReaderEphemeralPublicKey(
+ const vector<uint8_t>& readerEphemeralPublicKey) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
+ return eicSessionSetReaderEphemeralPublicKey(&ctx_, readerEphemeralPublicKey.data());
+}
+
+bool FakeSecureHardwareSessionProxy::setSessionTranscript(
+ const vector<uint8_t>& sessionTranscript) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
+ return eicSessionSetSessionTranscript(&ctx_, sessionTranscript.data(),
+ sessionTranscript.size());
+}
+
+// ----------------------------------------------------------------------
+
+// The singleton EicPresentation object used everywhere.
+//
+EicPresentation FakeSecureHardwarePresentationProxy::ctx_;
+
+FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {
+ if (id_ != 0) {
+ shutdown();
+ }
+}
+
+bool FakeSecureHardwarePresentationProxy::initialize(
+ uint32_t sessionId, bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) {
+ if (id_ != 0) {
+ LOG(WARNING) << "Proxy is already initialized";
+ return false;
+ }
+ bool initialized =
+ eicPresentationInit(&ctx_, sessionId, testCredential, docType.c_str(), docType.size(),
+ encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
+ if (!initialized) {
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "Error getting id";
+ return false;
+ }
+ id_ = id.value();
+ return true;
+}
+
+optional<uint32_t> FakeSecureHardwarePresentationProxy::getId() {
+ uint32_t id;
+ if (!eicPresentationGetId(&ctx_, &id)) {
+ return std::nullopt;
+ }
+ return id;
+}
+
+bool FakeSecureHardwarePresentationProxy::validateId(const string& callerName) {
+ if (id_ == 0) {
+ LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+ << ": While validating expected id is 0";
+ return false;
+ }
+ optional<uint32_t> id = getId();
+ if (!id) {
+ LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+ << ": Error getting id for validating";
+ return false;
+ }
+ if (id.value() != id_) {
+ LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+ << ": While validating expected id " << id_ << " but got " << id.value();
+ return false;
+ }
+ return true;
+}
+
+bool FakeSecureHardwarePresentationProxy::shutdown() {
+ bool validated = validateId(__func__);
+ id_ = 0;
+ if (!validated) {
+ return false;
+ }
+ if (!eicPresentationShutdown(&ctx_)) {
+ LOG(INFO) << "Error shutting down presentation";
+ return false;
+ }
+ return true;
}
// Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
optional<pair<vector<uint8_t>, vector<uint8_t>>>
-FakeSecureHardwarePresentationProxy::generateSigningKeyPair(string docType, time_t now) {
+FakeSecureHardwarePresentationProxy::generateSigningKeyPair(const string& docType, time_t now) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
uint8_t publicKeyCert[512];
size_t publicKeyCertSize = sizeof(publicKeyCert);
vector<uint8_t> signingKeyBlob(60);
@@ -201,7 +497,7 @@
if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), docType.size(), now,
publicKeyCert, &publicKeyCertSize,
signingKeyBlob.data())) {
- return {};
+ return std::nullopt;
}
vector<uint8_t> cert;
@@ -213,33 +509,44 @@
// Returns private key
optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::createEphemeralKeyPair() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
if (!eicPresentationCreateEphemeralKeyPair(&ctx_, priv.data())) {
- return {};
+ return std::nullopt;
}
return priv;
}
optional<uint64_t> FakeSecureHardwarePresentationProxy::createAuthChallenge() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
uint64_t challenge;
if (!eicPresentationCreateAuthChallenge(&ctx_, &challenge)) {
- return {};
+ return std::nullopt;
}
return challenge;
}
-bool FakeSecureHardwarePresentationProxy::shutdown() {
- LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
- return true;
-}
-
bool FakeSecureHardwarePresentationProxy::pushReaderCert(const vector<uint8_t>& certX509) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
return eicPresentationPushReaderCert(&ctx_, certX509.data(), certX509.size());
}
bool FakeSecureHardwarePresentationProxy::validateRequestMessage(
const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& requestMessage,
int coseSignAlg, const vector<uint8_t>& readerSignatureOfToBeSigned) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
return eicPresentationValidateRequestMessage(
&ctx_, sessionTranscript.data(), sessionTranscript.size(), requestMessage.data(),
requestMessage.size(), coseSignAlg, readerSignatureOfToBeSigned.data(),
@@ -251,6 +558,10 @@
int hardwareAuthenticatorType, uint64_t timeStamp, const vector<uint8_t>& mac,
uint64_t verificationTokenChallenge, uint64_t verificationTokenTimestamp,
int verificationTokenSecurityLevel, const vector<uint8_t>& verificationTokenMac) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
return eicPresentationSetAuthToken(&ctx_, challenge, secureUserId, authenticatorId,
hardwareAuthenticatorType, timeStamp, mac.data(), mac.size(),
verificationTokenChallenge, verificationTokenTimestamp,
@@ -261,6 +572,10 @@
optional<bool> FakeSecureHardwarePresentationProxy::validateAccessControlProfile(
int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
int timeoutMillis, uint64_t secureUserId, const vector<uint8_t>& mac) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
bool accessGranted = false;
uint8_t scratchSpace[512];
if (!eicPresentationValidateAccessControlProfile(&ctx_, id, readerCertificate.data(),
@@ -268,12 +583,16 @@
userAuthenticationRequired, timeoutMillis,
secureUserId, mac.data(), &accessGranted,
scratchSpace, sizeof(scratchSpace))) {
- return {};
+ return std::nullopt;
}
return accessGranted;
}
bool FakeSecureHardwarePresentationProxy::startRetrieveEntries() {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
return eicPresentationStartRetrieveEntries(&ctx_);
}
@@ -281,6 +600,10 @@
const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerEphemeralPublicKey,
const vector<uint8_t>& signingKeyBlob, const string& docType,
unsigned int numNamespacesWithValues, size_t expectedProofOfProvisioningSize) {
+ if (!validateId(__func__)) {
+ return false;
+ }
+
if (signingKeyBlob.size() != 60) {
eicDebug("Unexpected size %zd of signingKeyBlob, expected 60", signingKeyBlob.size());
return false;
@@ -294,6 +617,10 @@
AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue(
const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
int32_t entrySize, const vector<int32_t>& accessControlProfileIds) {
+ if (!validateId(__func__)) {
+ return AccessCheckResult::kFailed;
+ }
+
uint8_t scratchSpace[512];
vector<uint8_t> uint8AccessControlProfileIds;
for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
@@ -324,6 +651,10 @@
optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::retrieveEntryValue(
const vector<uint8_t>& encryptedContent, const string& nameSpace, const string& name,
const vector<int32_t>& accessControlProfileIds) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
uint8_t scratchSpace[512];
vector<uint8_t> uint8AccessControlProfileIds;
for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
@@ -337,16 +668,20 @@
nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
scratchSpace, sizeof(scratchSpace))) {
- return {};
+ return std::nullopt;
}
return content;
}
optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::finishRetrieval() {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> mac(32);
size_t macSize = 32;
if (!eicPresentationFinishRetrieval(&ctx_, mac.data(), &macSize)) {
- return {};
+ return std::nullopt;
}
mac.resize(macSize);
return mac;
@@ -355,11 +690,15 @@
optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::deleteCredential(
const string& docType, const vector<uint8_t>& challenge, bool includeChallenge,
size_t proofOfDeletionCborSize) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), docType.size(), challenge.data(),
challenge.size(), includeChallenge,
proofOfDeletionCborSize, signatureOfToBeSigned.data())) {
- return {};
+ return std::nullopt;
}
return signatureOfToBeSigned;
}
@@ -367,11 +706,15 @@
optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::proveOwnership(
const string& docType, bool testCredential, const vector<uint8_t>& challenge,
size_t proofOfOwnershipCborSize) {
+ if (!validateId(__func__)) {
+ return std::nullopt;
+ }
+
vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), docType.size(), testCredential,
challenge.data(), challenge.size(), proofOfOwnershipCborSize,
signatureOfToBeSigned.data())) {
- return {};
+ return std::nullopt;
}
return signatureOfToBeSigned;
}
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.h b/identity/aidl/default/FakeSecureHardwareProxy.h
index 6852c1a..2512074 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.h
+++ b/identity/aidl/default/FakeSecureHardwareProxy.h
@@ -27,21 +27,28 @@
//
class FakeSecureHardwareProvisioningProxy : public SecureHardwareProvisioningProxy {
public:
- FakeSecureHardwareProvisioningProxy();
+ FakeSecureHardwareProvisioningProxy() = default;
virtual ~FakeSecureHardwareProvisioningProxy();
bool initialize(bool testCredential) override;
- bool initializeForUpdate(bool testCredential, string docType,
- vector<uint8_t> encryptedCredentialKeys) override;
+ bool initializeForUpdate(bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) override;
bool shutdown() override;
+ optional<uint32_t> getId() override;
+
// Returns public key certificate.
optional<vector<uint8_t>> createCredentialKey(const vector<uint8_t>& challenge,
const vector<uint8_t>& applicationId) override;
- bool startPersonalization(int accessControlProfileCount, vector<int> entryCounts,
+ optional<vector<uint8_t>> createCredentialKeyUsingRkp(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationKeyCert) override;
+
+ bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
const string& docType,
size_t expectedProofOfProvisioningSize) override;
@@ -67,21 +74,81 @@
optional<vector<uint8_t>> finishGetCredentialData(const string& docType) override;
protected:
- EicProvisioning ctx_;
+ // See docs for id_.
+ //
+ bool validateId(const string& callerName);
+
+ // We use a singleton libeic object, shared by all proxy instances. This is to
+ // properly simulate a situation where libeic is used on constrained hardware
+ // with only enough RAM for a single instance of the libeic object.
+ //
+ static EicProvisioning ctx_;
+
+ // On the HAL side we keep track of the ID that was assigned to the libeic object
+ // created in secure hardware. For every call into libeic we validate that this
+ // identifier matches what is on the secure side. This is what the validateId()
+ // method does.
+ //
+ uint32_t id_ = 0;
+};
+
+// This implementation uses libEmbeddedIC in-process.
+//
+class FakeSecureHardwareSessionProxy : public SecureHardwareSessionProxy {
+ public:
+ FakeSecureHardwareSessionProxy() = default;
+ virtual ~FakeSecureHardwareSessionProxy();
+
+ bool initialize() override;
+
+ bool shutdown() override;
+
+ optional<uint32_t> getId() override;
+
+ optional<uint64_t> getAuthChallenge() override;
+
+ // Returns private key
+ optional<vector<uint8_t>> getEphemeralKeyPair() override;
+
+ bool setReaderEphemeralPublicKey(const vector<uint8_t>& readerEphemeralPublicKey) override;
+
+ bool setSessionTranscript(const vector<uint8_t>& sessionTranscript) override;
+
+ protected:
+ // See docs for id_.
+ //
+ bool validateId(const string& callerName);
+
+ // We use a singleton libeic object, shared by all proxy instances. This is to
+ // properly simulate a situation where libeic is used on constrained hardware
+ // with only enough RAM for a single instance of the libeic object.
+ //
+ static EicSession ctx_;
+
+ // On the HAL side we keep track of the ID that was assigned to the libeic object
+ // created in secure hardware. For every call into libeic we validate that this
+ // identifier matches what is on the secure side. This is what the validateId()
+ // method does.
+ //
+ uint32_t id_ = 0;
};
// This implementation uses libEmbeddedIC in-process.
//
class FakeSecureHardwarePresentationProxy : public SecureHardwarePresentationProxy {
public:
- FakeSecureHardwarePresentationProxy();
+ FakeSecureHardwarePresentationProxy() = default;
virtual ~FakeSecureHardwarePresentationProxy();
- bool initialize(bool testCredential, string docType,
- vector<uint8_t> encryptedCredentialKeys) override;
+ bool initialize(uint32_t sessionId, bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) override;
+
+ bool shutdown() override;
+
+ optional<uint32_t> getId() override;
// Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
- optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(string docType,
+ optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(const string& docType,
time_t now) override;
// Returns private key
@@ -133,10 +200,23 @@
const vector<uint8_t>& challenge,
size_t proofOfOwnershipCborSize) override;
- bool shutdown() override;
-
protected:
- EicPresentation ctx_;
+ // See docs for id_.
+ //
+ bool validateId(const string& callerName);
+
+ // We use a singleton libeic object, shared by all proxy instances. This is to
+ // properly simulate a situation where libeic is used on constrained hardware
+ // with only enough RAM for a single instance of the libeic object.
+ //
+ static EicPresentation ctx_;
+
+ // On the HAL side we keep track of the ID that was assigned to the libeic object
+ // created in secure hardware. For every call into libeic we validate that this
+ // identifier matches what is on the secure side. This is what the validateId()
+ // method does.
+ //
+ uint32_t id_ = 0;
};
// Factory implementation.
@@ -150,6 +230,10 @@
return new FakeSecureHardwareProvisioningProxy();
}
+ sp<SecureHardwareSessionProxy> createSessionProxy() override {
+ return new FakeSecureHardwareSessionProxy();
+ }
+
sp<SecureHardwarePresentationProxy> createPresentationProxy() override {
return new FakeSecureHardwarePresentationProxy();
}
diff --git a/identity/aidl/default/android.hardware.identity_credential.xml b/identity/aidl/default/android.hardware.identity_credential.xml
index 5149792..20b2710 100644
--- a/identity/aidl/default/android.hardware.identity_credential.xml
+++ b/identity/aidl/default/android.hardware.identity_credential.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<permissions>
- <feature name="android.hardware.identity_credential" version="202101" />
+ <feature name="android.hardware.identity_credential" version="202201" />
</permissions>
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index 95557b5..ff80752 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -72,14 +72,38 @@
testCredential_ = testCredentialItem->value();
encryptedCredentialKeys_ = encryptedCredentialKeysItem->value();
- if (!hwProxy_->initialize(testCredential_, docType_, encryptedCredentialKeys_)) {
- LOG(ERROR) << "hwProxy->initialize failed";
- return false;
+
+ // If in a session, delay the initialization of the proxy.
+ //
+ if (!session_) {
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ LOG(ERROR) << "Error initializing hw proxy";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
}
return IIdentityCredentialStore::STATUS_OK;
}
+ndk::ScopedAStatus IdentityCredential::ensureHwProxy() {
+ if (hwProxy_) {
+ return ndk::ScopedAStatus::ok();
+ }
+ hwProxy_ = hwProxyFactory_->createPresentationProxy();
+ if (!hwProxy_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Error creating hw proxy"));
+ }
+ uint64_t sessionId = session_ ? session_->getSessionId() : EIC_PRESENTATION_ID_UNSET;
+ if (!hwProxy_->initialize(sessionId, testCredential_, docType_, encryptedCredentialKeys_)) {
+ hwProxy_.clear();
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Error initializing hw proxy"));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus IdentityCredential::deleteCredential(
vector<uint8_t>* outProofOfDeletionSignature) {
return deleteCredentialCommon({}, false, outProofOfDeletionSignature);
@@ -93,6 +117,14 @@
ndk::ScopedAStatus IdentityCredential::deleteCredentialCommon(
const vector<uint8_t>& challenge, bool includeChallenge,
vector<uint8_t>* outProofOfDeletionSignature) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
if (challenge.size() > 32) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
@@ -128,6 +160,14 @@
ndk::ScopedAStatus IdentityCredential::proveOwnership(
const vector<uint8_t>& challenge, vector<uint8_t>* outProofOfOwnershipSignature) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
if (challenge.size() > 32) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
@@ -159,6 +199,14 @@
}
ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
optional<vector<uint8_t>> ephemeralPriv = hwProxy_->createEphemeralKeyPair();
if (!ephemeralPriv) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -186,11 +234,23 @@
ndk::ScopedAStatus IdentityCredential::setReaderEphemeralPublicKey(
const vector<uint8_t>& publicKey) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
readerPublicKey_ = publicKey;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus IdentityCredential::createAuthChallenge(int64_t* outChallenge) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
optional<uint64_t> challenge = hwProxy_->createAuthChallenge();
if (!challenge) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -217,16 +277,22 @@
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);
- if (item == nullptr) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_INVALID_DATA,
- "SessionTranscript contains invalid CBOR"));
- }
- sessionTranscriptItem = std::move(item);
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
}
+
+ // If in a session, ensure the passed-in session transcript matches the
+ // session transcript from the session.
+ if (session_) {
+ if (sessionTranscript != session_->getSessionTranscript()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH,
+ "In a session and passed-in SessionTranscript doesn't match the one "
+ "from the session"));
+ }
+ }
+
if (numStartRetrievalCalls_ > 0) {
if (sessionTranscript_ != sessionTranscript) {
LOG(ERROR) << "Session Transcript changed";
@@ -390,32 +456,36 @@
}
}
- // TODO: move this check to the TA
-#if 1
- // To prevent replay-attacks, we check that the public part of the ephemeral
- // key we previously created, is present in the DeviceEngagement part of
- // SessionTranscript as a COSE_Key, in uncompressed form.
- //
- // We do this by just searching for the X and Y coordinates.
- if (sessionTranscript.size() > 0) {
- auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
- if (!getXYSuccess) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
- "Error extracting X and Y from ePub"));
- }
- if (sessionTranscript.size() > 0 &&
- !(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
- ePubX.size()) != nullptr &&
- memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
- ePubY.size()) != nullptr)) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
- "Did not find ephemeral public key's X and Y coordinates in "
- "SessionTranscript (make sure leading zeroes are not used)"));
+ if (session_) {
+ // If presenting in a session, the TA has already done this check.
+
+ } else {
+ // To prevent replay-attacks, we check that the public part of the ephemeral
+ // key we previously created, is present in the DeviceEngagement part of
+ // SessionTranscript as a COSE_Key, in uncompressed form.
+ //
+ // We do this by just searching for the X and Y coordinates.
+ //
+ // Would be nice to move this check to the TA.
+ if (sessionTranscript.size() > 0) {
+ auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
+ if (!getXYSuccess) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+ "Error extracting X and Y from ePub"));
+ }
+ if (sessionTranscript.size() > 0 &&
+ !(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
+ ePubX.size()) != nullptr &&
+ memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
+ ePubY.size()) != nullptr)) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+ "Did not find ephemeral public key's X and Y coordinates in "
+ "SessionTranscript (make sure leading zeroes are not used)"));
+ }
}
}
-#endif
// itemsRequest: If non-empty, contains request data that may be signed by the
// reader. The content can be defined in the way appropriate for the
@@ -537,21 +607,38 @@
// Finally, pass info so the HMAC key can be derived and the TA can start
// creating the DeviceNameSpaces CBOR...
- if (sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0 && signingKeyBlob.size() > 0) {
- // We expect the reader ephemeral public key to be same size and curve
- // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
- // won't work. So its length should be 65 bytes and it should be
- // starting with 0x04.
- if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED,
- "Reader public key is not in expected format"));
+ if (!session_) {
+ if (sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0 &&
+ signingKeyBlob.size() > 0) {
+ // We expect the reader ephemeral public key to be same size and curve
+ // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
+ // won't work. So its length should be 65 bytes and it should be
+ // starting with 0x04.
+ if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Reader public key is not in expected format"));
+ }
+ vector<uint8_t> pubKeyP256(readerPublicKey_.begin() + 1, readerPublicKey_.end());
+ if (!hwProxy_->calcMacKey(sessionTranscript_, pubKeyP256, signingKeyBlob, docType_,
+ numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error starting retrieving entries"));
+ }
}
- vector<uint8_t> pubKeyP256(readerPublicKey_.begin() + 1, readerPublicKey_.end());
- if (!hwProxy_->calcMacKey(sessionTranscript_, pubKeyP256, signingKeyBlob, docType_,
- numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED, "Error starting retrieving entries"));
+ } else {
+ if (session_->getSessionTranscript().size() > 0 &&
+ session_->getReaderEphemeralPublicKey().size() > 0 && signingKeyBlob.size() > 0) {
+ // Don't actually pass the reader ephemeral public key in, the TA will get
+ // it from the session object.
+ //
+ if (!hwProxy_->calcMacKey(sessionTranscript_, {}, signingKeyBlob, docType_,
+ numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error starting retrieving entries"));
+ }
}
}
@@ -665,6 +752,11 @@
ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
const string& nameSpace, const string& name, int32_t entrySize,
const vector<int32_t>& accessControlProfileIds) {
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
+
if (name.empty()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Name cannot be empty"));
@@ -785,6 +877,11 @@
ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<uint8_t>& encryptedContent,
vector<uint8_t>* outContent) {
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
+
optional<vector<uint8_t>> content = hwProxy_->retrieveEntryValue(
encryptedContent, currentNameSpace_, currentName_, currentAccessControlProfileIds_);
if (!content) {
@@ -829,6 +926,11 @@
ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
vector<uint8_t>* outDeviceNameSpaces) {
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
+
if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
deviceNameSpacesMap_.add(currentNameSpace_,
std::move(currentNameSpaceDeviceNameSpacesMap_));
@@ -846,18 +948,23 @@
.c_str()));
}
- // If there's no signing key or no sessionTranscript or no reader ephemeral
- // public key, we return the empty MAC.
+ // If the TA calculated a MAC (it might not have), format it as a COSE_Mac0
+ //
optional<vector<uint8_t>> mac;
- if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
- readerPublicKey_.size() > 0) {
- optional<vector<uint8_t>> digestToBeMaced = hwProxy_->finishRetrieval();
- if (!digestToBeMaced || digestToBeMaced.value().size() != 32) {
+ optional<vector<uint8_t>> digestToBeMaced = hwProxy_->finishRetrieval();
+
+ // The MAC not being set means an error occurred.
+ if (!digestToBeMaced) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA, "Error generating digestToBeMaced"));
+ }
+ // Size 0 means that the MAC isn't set. If it's set, it has to be 32 bytes.
+ if (digestToBeMaced.value().size() != 0) {
+ if (digestToBeMaced.value().size() != 32) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA,
- "Error generating digestToBeMaced"));
+ "Unexpected size for digestToBeMaced"));
}
- // Now construct COSE_Mac0 from the returned MAC...
mac = support::coseMacWithDigest(digestToBeMaced.value(), {} /* data */);
}
@@ -868,6 +975,15 @@
ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ ndk::ScopedAStatus status = ensureHwProxy();
+ if (!status.isOk()) {
+ return status;
+ }
+
time_t now = time(NULL);
optional<pair<vector<uint8_t>, vector<uint8_t>>> pair =
hwProxy_->generateSigningKeyPair(docType_, now);
@@ -885,10 +1001,19 @@
ndk::ScopedAStatus IdentityCredential::updateCredential(
shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
- sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
+ if (session_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+ }
+ sp<SecureHardwareProvisioningProxy> provisioningHwProxy =
+ hwProxyFactory_->createProvisioningProxy();
+ if (!provisioningHwProxy) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Error creating provisioning proxy"));
+ }
shared_ptr<WritableIdentityCredential> wc =
- ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType_,
- testCredential_);
+ ndk::SharedRefBase::make<WritableIdentityCredential>(
+ provisioningHwProxy, docType_, testCredential_, hardwareInformation_);
if (!wc->initializeForUpdate(encryptedCredentialKeys_)) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index ef9d133..5929829 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -30,6 +30,7 @@
#include <cppbor.h>
#include "IdentityCredentialStore.h"
+#include "PresentationSession.h"
#include "SecureHardwareProxy.h"
namespace aidl::android::hardware::identity {
@@ -46,12 +47,14 @@
class IdentityCredential : public BnIdentityCredential {
public:
IdentityCredential(sp<SecureHardwareProxyFactory> hwProxyFactory,
- sp<SecureHardwarePresentationProxy> hwProxy,
- const vector<uint8_t>& credentialData)
+ const vector<uint8_t>& credentialData,
+ std::shared_ptr<PresentationSession> session,
+ HardwareInformation hardwareInformation)
: hwProxyFactory_(hwProxyFactory),
- hwProxy_(hwProxy),
credentialData_(credentialData),
+ session_(std::move(session)),
numStartRetrievalCalls_(0),
+ hardwareInformation_(std::move(hardwareInformation)),
expectedDeviceNameSpacesSize_(0) {}
// Parses and decrypts credentialData_, return a status code from
@@ -94,17 +97,24 @@
bool includeChallenge,
vector<uint8_t>* outProofOfDeletionSignature);
+ // Creates and initializes hwProxy_.
+ ndk::ScopedAStatus ensureHwProxy();
+
// Set by constructor
sp<SecureHardwareProxyFactory> hwProxyFactory_;
- sp<SecureHardwarePresentationProxy> hwProxy_;
vector<uint8_t> credentialData_;
+ shared_ptr<PresentationSession> session_;
int numStartRetrievalCalls_;
+ HardwareInformation hardwareInformation_;
// Set by initialize()
string docType_;
bool testCredential_;
vector<uint8_t> encryptedCredentialKeys_;
+ // Set by ensureHwProxy()
+ sp<SecureHardwarePresentationProxy> hwProxy_;
+
// Set by createEphemeralKeyPair()
vector<uint8_t> ephemeralPublicKey_;
diff --git a/identity/aidl/default/common/IdentityCredentialStore.cpp b/identity/aidl/default/common/IdentityCredentialStore.cpp
index e6b5466..bbc2cef 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/common/IdentityCredentialStore.cpp
@@ -17,22 +17,33 @@
#define LOG_TAG "IdentityCredentialStore"
#include <android-base/logging.h>
+#include <android/binder_manager.h>
#include "IdentityCredential.h"
#include "IdentityCredentialStore.h"
+#include "PresentationSession.h"
#include "WritableIdentityCredential.h"
namespace aidl::android::hardware::identity {
+using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+
+IdentityCredentialStore::IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+ optional<string> remotelyProvisionedComponent)
+ : hwProxyFactory_(hwProxyFactory),
+ remotelyProvisionedComponentName_(remotelyProvisionedComponent) {
+ hardwareInformation_.credentialStoreName = "Identity Credential Reference Implementation";
+ hardwareInformation_.credentialStoreAuthorName = "Google";
+ hardwareInformation_.dataChunkSize = kGcmChunkSize;
+ hardwareInformation_.isDirectAccess = false;
+ hardwareInformation_.supportedDocTypes = {};
+ hardwareInformation_.isRemoteKeyProvisioningSupported =
+ remotelyProvisionedComponentName_.has_value();
+}
+
ndk::ScopedAStatus IdentityCredentialStore::getHardwareInformation(
HardwareInformation* hardwareInformation) {
- HardwareInformation hw;
- hw.credentialStoreName = "Identity Credential Reference Implementation";
- hw.credentialStoreAuthorName = "Google";
- hw.dataChunkSize = kGcmChunkSize;
- hw.isDirectAccess = false;
- hw.supportedDocTypes = {};
- *hardwareInformation = hw;
+ *hardwareInformation = hardwareInformation_;
return ndk::ScopedAStatus::ok();
}
@@ -41,7 +52,8 @@
shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
shared_ptr<WritableIdentityCredential> wc =
- ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential);
+ ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential,
+ hardwareInformation_);
if (!wc->initialize()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
@@ -61,9 +73,8 @@
"Unsupported cipher suite"));
}
- sp<SecureHardwarePresentationProxy> hwProxy = hwProxyFactory_->createPresentationProxy();
- shared_ptr<IdentityCredential> credential =
- ndk::SharedRefBase::make<IdentityCredential>(hwProxyFactory_, hwProxy, credentialData);
+ shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
+ hwProxyFactory_, credentialData, nullptr /* session */, hardwareInformation_);
auto ret = credential->initialize();
if (ret != IIdentityCredentialStore::STATUS_OK) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -73,4 +84,44 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus IdentityCredentialStore::createPresentationSession(
+ CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) {
+ // 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) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED,
+ "Unsupported cipher suite"));
+ }
+
+ sp<SecureHardwareSessionProxy> hwProxy = hwProxyFactory_->createSessionProxy();
+ shared_ptr<PresentationSession> session = ndk::SharedRefBase::make<PresentationSession>(
+ hwProxyFactory_, hwProxy, hardwareInformation_);
+ auto ret = session->initialize();
+ if (ret != IIdentityCredentialStore::STATUS_OK) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ int(ret), "Error initializing PresentationSession"));
+ }
+ *outSession = session;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredentialStore::getRemotelyProvisionedComponent(
+ shared_ptr<IRemotelyProvisionedComponent>* outRemotelyProvisionedComponent) {
+ if (!remotelyProvisionedComponentName_) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+ }
+
+ ndk::SpAIBinder binder(
+ AServiceManager_waitForService(remotelyProvisionedComponentName_->c_str()));
+ if (binder.get() == nullptr) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Unable to get remotely provisioned component"));
+ }
+
+ *outRemotelyProvisionedComponent = IRemotelyProvisionedComponent::fromBinder(binder);
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/IdentityCredentialStore.h b/identity/aidl/default/common/IdentityCredentialStore.h
index d35e632..dd1261b 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.h
+++ b/identity/aidl/default/common/IdentityCredentialStore.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
#include <aidl/android/hardware/identity/BnIdentityCredentialStore.h>
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include "SecureHardwareProxy.h"
@@ -25,14 +26,18 @@
using ::android::sp;
using ::android::hardware::identity::SecureHardwareProxyFactory;
+using ::std::optional;
using ::std::shared_ptr;
using ::std::string;
using ::std::vector;
class IdentityCredentialStore : public BnIdentityCredentialStore {
public:
- IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory)
- : hwProxyFactory_(hwProxyFactory) {}
+ // If remote key provisioning is supported, pass the service name for the correct
+ // IRemotelyProvisionedComponent to the remotelyProvisionedComponent parameter. Else
+ // pass std::nullopt to indicate remote key provisioning is not supported.
+ IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+ optional<string> remotelyProvisionedComponent);
// The GCM chunk size used by this implementation is 64 KiB.
static constexpr size_t kGcmChunkSize = 64 * 1024;
@@ -47,8 +52,17 @@
ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
shared_ptr<IIdentityCredential>* outCredential) override;
+ ndk::ScopedAStatus createPresentationSession(
+ CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) override;
+
+ ndk::ScopedAStatus getRemotelyProvisionedComponent(
+ shared_ptr<::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent>*
+ outRemotelyProvisionedComponent) override;
+
private:
sp<SecureHardwareProxyFactory> hwProxyFactory_;
+ optional<string> remotelyProvisionedComponentName_;
+ HardwareInformation hardwareInformation_;
};
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/PresentationSession.cpp b/identity/aidl/default/common/PresentationSession.cpp
new file mode 100644
index 0000000..2eb7f2e
--- /dev/null
+++ b/identity/aidl/default/common/PresentationSession.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PresentationSession"
+
+#include "PresentationSession.h"
+#include "IdentityCredentialStore.h"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <string.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include "FakeSecureHardwareProxy.h"
+#include "IdentityCredential.h"
+#include "PresentationSession.h"
+
+namespace aidl::android::hardware::identity {
+
+using ::std::optional;
+
+using namespace ::android::hardware::identity;
+
+PresentationSession::~PresentationSession() {}
+
+int PresentationSession::initialize() {
+ if (!hwProxy_->initialize()) {
+ LOG(ERROR) << "hwProxy->initialize failed";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
+
+ optional<uint64_t> id = hwProxy_->getId();
+ if (!id) {
+ LOG(ERROR) << "Error getting id for session";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
+ id_ = id.value();
+
+ optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair();
+ if (!ephemeralKeyPriv) {
+ LOG(ERROR) << "Error getting ephemeral private key for session";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
+ optional<vector<uint8_t>> ephemeralKeyPair =
+ support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value());
+ if (!ephemeralKeyPair) {
+ LOG(ERROR) << "Error creating ephemeral key-pair";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
+ ephemeralKeyPair_ = ephemeralKeyPair.value();
+
+ optional<uint64_t> authChallenge = hwProxy_->getAuthChallenge();
+ if (!authChallenge) {
+ LOG(ERROR) << "Error getting authChallenge for session";
+ return IIdentityCredentialStore::STATUS_FAILED;
+ }
+ authChallenge_ = authChallenge.value();
+
+ return IIdentityCredentialStore::STATUS_OK;
+}
+
+ndk::ScopedAStatus PresentationSession::getEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
+ *outKeyPair = ephemeralKeyPair_;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::getAuthChallenge(int64_t* outChallenge) {
+ *outChallenge = authChallenge_;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::setReaderEphemeralPublicKey(
+ const vector<uint8_t>& publicKey) {
+ // We expect the reader ephemeral public key to be same size and curve
+ // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
+ // won't work. So its length should be 65 bytes and it should be
+ // starting with 0x04.
+ if (publicKey.size() != 65 || publicKey[0] != 0x04) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Reader public key is not in expected format"));
+ }
+ readerPublicKey_ = publicKey;
+ vector<uint8_t> pubKeyP256(publicKey.begin() + 1, publicKey.end());
+ if (!hwProxy_->setReaderEphemeralPublicKey(pubKeyP256)) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error setting readerEphemeralPublicKey for session"));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::setSessionTranscript(
+ const vector<uint8_t>& sessionTranscript) {
+ sessionTranscript_ = sessionTranscript;
+ if (!hwProxy_->setSessionTranscript(sessionTranscript)) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error setting SessionTranscript for session"));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::getCredential(
+ const vector<uint8_t>& credentialData, shared_ptr<IIdentityCredential>* outCredential) {
+ shared_ptr<PresentationSession> p = ref<PresentationSession>();
+ shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
+ hwProxyFactory_, credentialData, p, hardwareInformation_);
+ int ret = credential->initialize();
+ if (ret != IIdentityCredentialStore::STATUS_OK) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ ret, "Error initializing IdentityCredential"));
+ }
+ *outCredential = std::move(credential);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+uint64_t PresentationSession::getSessionId() {
+ return id_;
+}
+
+vector<uint8_t> PresentationSession::getSessionTranscript() {
+ return sessionTranscript_;
+}
+
+vector<uint8_t> PresentationSession::getReaderEphemeralPublicKey() {
+ return readerPublicKey_;
+}
+
+} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/PresentationSession.h b/identity/aidl/default/common/PresentationSession.h
new file mode 100644
index 0000000..4cb174a
--- /dev/null
+++ b/identity/aidl/default/common/PresentationSession.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_IDENTITY_PRESENTATIONSESSION_H
+#define ANDROID_HARDWARE_IDENTITY_PRESENTATIONSESSION_H
+
+#include <aidl/android/hardware/identity/BnPresentationSession.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <vector>
+
+#include <cppbor.h>
+
+#include "IdentityCredentialStore.h"
+#include "SecureHardwareProxy.h"
+
+namespace aidl::android::hardware::identity {
+
+using ::aidl::android::hardware::keymaster::HardwareAuthToken;
+using ::aidl::android::hardware::keymaster::VerificationToken;
+using ::android::sp;
+using ::android::hardware::identity::SecureHardwareSessionProxy;
+using ::std::vector;
+
+class PresentationSession : public BnPresentationSession {
+ public:
+ PresentationSession(sp<SecureHardwareProxyFactory> hwProxyFactory,
+ sp<SecureHardwareSessionProxy> hwProxy,
+ HardwareInformation hardwareInformation)
+ : hwProxyFactory_(std::move(hwProxyFactory)),
+ hwProxy_(std::move(hwProxy)),
+ hardwareInformation_(std::move(hardwareInformation)) {}
+
+ virtual ~PresentationSession();
+
+ // Creates ephemeral key and auth-challenge in TA. Returns a status code from
+ // IIdentityCredentialStore. Must be called right after construction.
+ int initialize();
+
+ uint64_t getSessionId();
+
+ vector<uint8_t> getSessionTranscript();
+ vector<uint8_t> getReaderEphemeralPublicKey();
+
+ // Methods from IPresentationSession follow.
+ ndk::ScopedAStatus getEphemeralKeyPair(vector<uint8_t>* outKeyPair) override;
+ ndk::ScopedAStatus getAuthChallenge(int64_t* outChallenge) override;
+ ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
+ ndk::ScopedAStatus setSessionTranscript(const vector<uint8_t>& sessionTranscript) override;
+
+ ndk::ScopedAStatus getCredential(const vector<uint8_t>& credentialData,
+ shared_ptr<IIdentityCredential>* outCredential) override;
+
+ private:
+ // Set by constructor
+ sp<SecureHardwareProxyFactory> hwProxyFactory_;
+ sp<SecureHardwareSessionProxy> hwProxy_;
+ HardwareInformation hardwareInformation_;
+
+ // Set by initialize()
+ uint64_t id_;
+ vector<uint8_t> ephemeralKeyPair_;
+ uint64_t authChallenge_;
+
+ // Set by setReaderEphemeralPublicKey()
+ vector<uint8_t> readerPublicKey_;
+
+ // Set by setSessionTranscript()
+ vector<uint8_t> sessionTranscript_;
+};
+
+} // namespace aidl::android::hardware::identity
+
+#endif // ANDROID_HARDWARE_IDENTITY_PRESENTATIONSESSION_H
diff --git a/identity/aidl/default/common/SecureHardwareProxy.h b/identity/aidl/default/common/SecureHardwareProxy.h
index a1ed1ef..9f63ad8 100644
--- a/identity/aidl/default/common/SecureHardwareProxy.h
+++ b/identity/aidl/default/common/SecureHardwareProxy.h
@@ -42,6 +42,7 @@
// Forward declare.
//
class SecureHardwareProvisioningProxy;
+class SecureHardwareSessionProxy;
class SecureHardwarePresentationProxy;
// This is a class used to create proxies.
@@ -52,6 +53,7 @@
virtual ~SecureHardwareProxyFactory() {}
virtual sp<SecureHardwareProvisioningProxy> createProvisioningProxy() = 0;
+ virtual sp<SecureHardwareSessionProxy> createSessionProxy() = 0;
virtual sp<SecureHardwarePresentationProxy> createPresentationProxy() = 0;
};
@@ -64,8 +66,12 @@
virtual bool initialize(bool testCredential) = 0;
- virtual bool initializeForUpdate(bool testCredential, string docType,
- vector<uint8_t> encryptedCredentialKeys) = 0;
+ virtual bool initializeForUpdate(bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) = 0;
+
+ virtual optional<uint32_t> getId() = 0;
+
+ virtual bool shutdown() = 0;
// Returns public key certificate chain with attestation.
//
@@ -76,7 +82,19 @@
virtual optional<vector<uint8_t>> createCredentialKey(const vector<uint8_t>& challenge,
const vector<uint8_t>& applicationId) = 0;
- virtual bool startPersonalization(int accessControlProfileCount, vector<int> entryCounts,
+ // Returns public key certificate with a remotely provisioned attestation key.
+ //
+ // This returns a single certificate that is signed by the given |attestationKeyBlob|.
+ // The implementation of eicOpsCreateCredentialKey() on the TA side must coordinate
+ // with its corresponding keymint implementation to sign using the attestation key. The
+ // |attestationKeyCert| parameter is the certificates for |attestationKeyBlob|,
+ // formatted as concatenated, DER-encoded, X.509 certificates.
+ virtual optional<vector<uint8_t>> createCredentialKeyUsingRkp(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationKeyCert) = 0;
+
+ virtual bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
const string& docType,
size_t expectedProofOfProvisioningSize) = 0;
@@ -98,8 +116,6 @@
// Returns encryptedCredentialKeys (80 bytes).
virtual optional<vector<uint8_t>> finishGetCredentialData(const string& docType) = 0;
-
- virtual bool shutdown() = 0;
};
enum AccessCheckResult {
@@ -110,6 +126,30 @@
kReaderAuthenticationFailed,
};
+// The proxy used for sessions.
+//
+class SecureHardwareSessionProxy : public RefBase {
+ public:
+ SecureHardwareSessionProxy() {}
+
+ virtual ~SecureHardwareSessionProxy() {}
+
+ virtual bool initialize() = 0;
+
+ virtual optional<uint32_t> getId() = 0;
+
+ virtual bool shutdown() = 0;
+
+ virtual optional<uint64_t> getAuthChallenge() = 0;
+
+ // Returns private key
+ virtual optional<vector<uint8_t>> getEphemeralKeyPair() = 0;
+
+ virtual bool setReaderEphemeralPublicKey(const vector<uint8_t>& readerEphemeralPublicKey) = 0;
+
+ virtual bool setSessionTranscript(const vector<uint8_t>& sessionTranscript) = 0;
+};
+
// The proxy used for presentation.
//
class SecureHardwarePresentationProxy : public RefBase {
@@ -117,12 +157,16 @@
SecureHardwarePresentationProxy() {}
virtual ~SecureHardwarePresentationProxy() {}
- virtual bool initialize(bool testCredential, string docType,
- vector<uint8_t> encryptedCredentialKeys) = 0;
+ virtual bool initialize(uint32_t sessionId, bool testCredential, const string& docType,
+ const vector<uint8_t>& encryptedCredentialKeys) = 0;
+
+ virtual optional<uint32_t> getId() = 0;
+
+ virtual bool shutdown() = 0;
// Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
- virtual optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(string docType,
- time_t now) = 0;
+ virtual optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(
+ const string& docType, time_t now) = 0;
// Returns private key
virtual optional<vector<uint8_t>> createEphemeralKeyPair() = 0;
@@ -174,8 +218,6 @@
virtual optional<vector<uint8_t>> proveOwnership(const string& docType, bool testCredential,
const vector<uint8_t>& challenge,
size_t proofOfOwnershipCborSize) = 0;
-
- virtual bool shutdown() = 0;
};
} // namespace android::hardware::identity
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 200ee61..e420a7b 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -79,8 +79,15 @@
IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge can not be empty"));
}
- optional<vector<uint8_t>> certChain =
- hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+ optional<vector<uint8_t>> certChain;
+ if (attestationKeyBlob_ && attestationCertificateChain_) {
+ certChain = hwProxy_->createCredentialKeyUsingRkp(
+ attestationChallenge, attestationApplicationId, *attestationKeyBlob_,
+ attestationCertificateChain_->at(0));
+ } else {
+ certChain = hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+ }
+
if (!certChain) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
@@ -95,8 +102,14 @@
}
*outCertificateChain = vector<Certificate>();
- for (const vector<uint8_t>& cert : certs.value()) {
- Certificate c = Certificate();
+ for (vector<uint8_t>& cert : certs.value()) {
+ Certificate c;
+ c.encodedCertificate = std::move(cert);
+ outCertificateChain->push_back(std::move(c));
+ }
+
+ for (const vector<uint8_t>& cert : *attestationCertificateChain_) {
+ Certificate c;
c.encodedCertificate = cert;
outCertificateChain->push_back(std::move(c));
}
@@ -402,4 +415,36 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus WritableIdentityCredential::setRemotelyProvisionedAttestationKey(
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationCertificateChain) {
+ if (!hardwareInformation_.isRemoteKeyProvisioningSupported) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+ }
+
+ if (attestationKeyBlob.empty() || attestationCertificateChain.empty()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Empty data passed to setRemotlyProvisionedAttestationKey"));
+ }
+
+ if (attestationKeyBlob_.has_value()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Attestation key already set"));
+ }
+
+ optional<vector<vector<uint8_t>>> certs =
+ support::certificateChainSplit(attestationCertificateChain);
+ if (!certs) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error splitting chain into separate certificates"));
+ }
+
+ attestationKeyBlob_ = attestationKeyBlob;
+ attestationCertificateChain_ = *certs;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/WritableIdentityCredential.h b/identity/aidl/default/common/WritableIdentityCredential.h
index 36ad430..39d32c9 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.h
+++ b/identity/aidl/default/common/WritableIdentityCredential.h
@@ -30,6 +30,7 @@
using ::android::sp;
using ::android::hardware::identity::SecureHardwareProvisioningProxy;
+using ::std::optional;
using ::std::set;
using ::std::string;
using ::std::vector;
@@ -41,8 +42,11 @@
// For an updated credential, call initializeForUpdate() right after construction.
//
WritableIdentityCredential(sp<SecureHardwareProvisioningProxy> hwProxy, const string& docType,
- bool testCredential)
- : hwProxy_(hwProxy), docType_(docType), testCredential_(testCredential) {}
+ bool testCredential, HardwareInformation hardwareInformation)
+ : hwProxy_(hwProxy),
+ docType_(docType),
+ testCredential_(testCredential),
+ hardwareInformation_(std::move(hardwareInformation)) {}
~WritableIdentityCredential();
@@ -78,11 +82,16 @@
vector<uint8_t>* outCredentialData,
vector<uint8_t>* outProofOfProvisioningSignature) override;
+ ndk::ScopedAStatus setRemotelyProvisionedAttestationKey(
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationCertificateChain) override;
+
private:
// Set by constructor.
sp<SecureHardwareProvisioningProxy> hwProxy_;
string docType_;
bool testCredential_;
+ HardwareInformation hardwareInformation_;
// This is set in initialize().
bool startPersonalizationCalled_;
@@ -109,6 +118,10 @@
vector<int32_t> entryAccessControlProfileIds_;
vector<uint8_t> entryBytes_;
set<string> allNameSpaces_;
+
+ // Remotely provisioned attestation data, set via setRemotelyProvisionedAttestationKey
+ optional<vector<uint8_t>> attestationKeyBlob_;
+ optional<vector<vector<uint8_t>>> attestationCertificateChain_;
};
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/identity-default.xml b/identity/aidl/default/identity-default.xml
index a074250..cc0ddc7 100644
--- a/identity/aidl/default/identity-default.xml
+++ b/identity/aidl/default/identity-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.identity</name>
- <version>3</version>
+ <version>4</version>
<interface>
<name>IIdentityCredentialStore</name>
<instance>default</instance>
diff --git a/identity/aidl/default/libeic/EicCommon.h b/identity/aidl/default/libeic/EicCommon.h
index 476276e..2a08a35 100644
--- a/identity/aidl/default/libeic/EicCommon.h
+++ b/identity/aidl/default/libeic/EicCommon.h
@@ -21,6 +21,9 @@
#ifndef ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H
#define ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H
+// KeyMint auth-challenges are 64-bit numbers and 0 typically means unset.
+#define EIC_KM_AUTH_CHALLENGE_UNSET 0
+
// Feature version 202009:
//
// CredentialKeys = [
diff --git a/identity/aidl/default/libeic/EicOps.h b/identity/aidl/default/libeic/EicOps.h
index d4fcf0e..df96c7d 100644
--- a/identity/aidl/default/libeic/EicOps.h
+++ b/identity/aidl/default/libeic/EicOps.h
@@ -141,6 +141,10 @@
// String length, see strlen(3).
size_t eicStrLen(const char* s);
+// Locate a substring, see memmem(3)
+void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle,
+ size_t needleLen);
+
// Memory compare, see CRYPTO_memcmp(3SSL)
//
// It takes an amount of time dependent on len, but independent of the contents of the
@@ -151,6 +155,12 @@
// Random number generation.
bool eicOpsRandom(uint8_t* buf, size_t numBytes);
+// Creates a new non-zero identifier in |id|.
+//
+// Is guaranteed to be non-zero and different than what is already in |id|.
+//
+bool eicNextId(uint32_t* id);
+
// If |testCredential| is true, returns the 128-bit AES Hardware-Bound Key (16 bytes).
//
// Otherwise returns all zeroes (16 bytes).
@@ -186,13 +196,19 @@
// Generates CredentialKey plus an attestation certificate.
//
-// The attestation certificate will be signed by the attestation keys the secure
-// area has been provisioned with. The given |challenge| and |applicationId|
-// will be used as will |testCredential|.
+// If |attestationKeyBlob| is non-NULL, the certificate must be signed by the
+// the provided attestation key. Else, the certificate must be signed by the
+// attestation key that the secure area has been factory provisioned with. The
+// given |challenge|, |applicationId|, and |testCredential| must be signed
+// into the attestation.
//
-// The generated certificate will be in X.509 format and returned in |cert|
-// and |certSize| must be set to the size of this array and this function will
-// set it to the size of the certification chain on successfully return.
+// When |attestationKeyBlob| is non-NULL, then |attestationKeyCert| must
+// also be passed so that the underlying implementation can properly chain up
+// the newly-generated certificate to the existing chain.
+//
+// The generated certificate must be in X.509 format and returned in |cert|
+// and |certSize| must be set to the size of this array. This function must
+// set |certSize| to the size of the certification chain on successfully return.
//
// This may return either a single certificate or an entire certificate
// chain. If it returns only a single certificate, the implementation of
@@ -201,8 +217,10 @@
//
bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
size_t challengeSize, const uint8_t* applicationId,
- size_t applicationIdSize, bool testCredential, uint8_t* cert,
- size_t* certSize); // inout
+ size_t applicationIdSize, bool testCredential,
+ const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize,
+ const uint8_t* attestationKeyCert, size_t attestationKeyCertSize,
+ uint8_t* /*out*/ cert, size_t* /*inout*/ certSize);
// Generate an X.509 certificate for the key identified by |publicKey| which
// must be of the form returned by eicOpsCreateEcKey().
@@ -295,6 +313,8 @@
int verificationTokenSecurityLevel,
const uint8_t* verificationTokenMac, size_t verificationTokenMacSize);
+// Also see eicOpsLookupActiveSessionFromId() defined in EicSession.h
+
#ifdef __cplusplus
}
#endif
diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c
index 0d03ae9..104a559 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -16,11 +16,17 @@
#include "EicPresentation.h"
#include "EicCommon.h"
+#include "EicSession.h"
#include <inttypes.h>
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
- size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
+// Global used for assigning ids for presentation objects.
+//
+static uint32_t gPresentationLastIdAssigned = 0;
+
+bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential,
+ const char* docType, size_t docTypeLength,
+ const uint8_t* encryptedCredentialKeys,
size_t encryptedCredentialKeysSize) {
uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101];
bool expectPopSha256 = false;
@@ -39,6 +45,13 @@
}
eicMemSet(ctx, '\0', sizeof(EicPresentation));
+ ctx->sessionId = sessionId;
+
+ if (!eicNextId(&gPresentationLastIdAssigned)) {
+ eicDebug("Error getting id for object");
+ return false;
+ }
+ ctx->id = gPresentationLastIdAssigned;
if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys,
encryptedCredentialKeysSize,
@@ -86,6 +99,23 @@
if (expectPopSha256) {
eicMemCpy(ctx->proofOfProvisioningSha256, credentialKeys + 54, EIC_SHA256_DIGEST_SIZE);
}
+
+ eicDebug("Initialized presentation with id %" PRIu32, ctx->id);
+ return true;
+}
+
+bool eicPresentationShutdown(EicPresentation* ctx) {
+ if (ctx->id == 0) {
+ eicDebug("Trying to shut down presentation with id 0");
+ return false;
+ }
+ eicDebug("Shut down presentation with id %" PRIu32, ctx->id);
+ eicMemSet(ctx, '\0', sizeof(EicPresentation));
+ return true;
+}
+
+bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId) {
+ *outId = ctx->id;
return true;
}
@@ -174,7 +204,7 @@
eicDebug("Failed generating random challenge");
return false;
}
- } while (ctx->authChallenge == 0);
+ } while (ctx->authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET);
eicDebug("Created auth challenge %" PRIu64, ctx->authChallenge);
*authChallenge = ctx->authChallenge;
return true;
@@ -190,6 +220,24 @@
int coseSignAlg,
const uint8_t* readerSignatureOfToBeSigned,
size_t readerSignatureOfToBeSignedSize) {
+ if (ctx->sessionId != 0) {
+ EicSession* session = eicSessionGetForId(ctx->sessionId);
+ if (session == NULL) {
+ eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+ return false;
+ }
+ EicSha256Ctx sha256;
+ uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+ eicOpsSha256Init(&sha256);
+ eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+ eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+ if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+ EIC_SHA256_DIGEST_SIZE) != 0) {
+ eicDebug("SessionTranscript mismatch");
+ return false;
+ }
+ }
+
if (ctx->readerPublicKeySize == 0) {
eicDebug("No public key for reader");
return false;
@@ -330,6 +378,20 @@
return true;
}
+static bool getChallenge(EicPresentation* ctx, uint64_t* outAuthChallenge) {
+ // Use authChallenge from session if applicable.
+ *outAuthChallenge = ctx->authChallenge;
+ if (ctx->sessionId != 0) {
+ EicSession* session = eicSessionGetForId(ctx->sessionId);
+ if (session == NULL) {
+ eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+ return false;
+ }
+ *outAuthChallenge = session->authChallenge;
+ }
+ return true;
+}
+
bool eicPresentationSetAuthToken(EicPresentation* ctx, uint64_t challenge, uint64_t secureUserId,
uint64_t authenticatorId, int hardwareAuthenticatorType,
uint64_t timeStamp, const uint8_t* mac, size_t macSize,
@@ -338,14 +400,19 @@
int verificationTokenSecurityLevel,
const uint8_t* verificationTokenMac,
size_t verificationTokenMacSize) {
+ uint64_t authChallenge;
+ if (!getChallenge(ctx, &authChallenge)) {
+ return false;
+ }
+
// It doesn't make sense to accept any tokens if eicPresentationCreateAuthChallenge()
// was never called.
- if (ctx->authChallenge == 0) {
- eicDebug("Trying validate tokens when no auth-challenge was previously generated");
+ if (authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET) {
+ eicDebug("Trying to validate tokens when no auth-challenge was previously generated");
return false;
}
// At least the verification-token must have the same challenge as what was generated.
- if (verificationTokenChallenge != ctx->authChallenge) {
+ if (verificationTokenChallenge != authChallenge) {
eicDebug("Challenge in verification token does not match the challenge "
"previously generated");
return false;
@@ -354,6 +421,7 @@
challenge, secureUserId, authenticatorId, hardwareAuthenticatorType, timeStamp, mac,
macSize, verificationTokenChallenge, verificationTokenTimestamp,
verificationTokenSecurityLevel, verificationTokenMac, verificationTokenMacSize)) {
+ eicDebug("Error validating authToken");
return false;
}
ctx->authTokenChallenge = challenge;
@@ -377,11 +445,16 @@
// Only ACP with auth-on-every-presentation - those with timeout == 0 - need the
// challenge to match...
if (timeoutMillis == 0) {
- if (ctx->authTokenChallenge != ctx->authChallenge) {
+ uint64_t authChallenge;
+ if (!getChallenge(ctx, &authChallenge)) {
+ return false;
+ }
+
+ if (ctx->authTokenChallenge != authChallenge) {
eicDebug("Challenge in authToken (%" PRIu64
") doesn't match the challenge "
"that was created (%" PRIu64 ") for this session",
- ctx->authTokenChallenge, ctx->authChallenge);
+ ctx->authTokenChallenge, authChallenge);
return false;
}
}
@@ -490,6 +563,25 @@
const uint8_t signingKeyBlob[60], const char* docType,
size_t docTypeLength, unsigned int numNamespacesWithValues,
size_t expectedDeviceNamespacesSize) {
+ if (ctx->sessionId != 0) {
+ EicSession* session = eicSessionGetForId(ctx->sessionId);
+ if (session == NULL) {
+ eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+ return false;
+ }
+ EicSha256Ctx sha256;
+ uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+ eicOpsSha256Init(&sha256);
+ eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+ eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+ if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+ EIC_SHA256_DIGEST_SIZE) != 0) {
+ eicDebug("SessionTranscript mismatch");
+ return false;
+ }
+ readerEphemeralPublicKey = session->readerEphemeralPublicKey;
+ }
+
uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE];
if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType,
docTypeLength, signingKeyPriv)) {
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index 6f7f432..a031890 100644
--- a/identity/aidl/default/libeic/EicPresentation.h
+++ b/identity/aidl/default/libeic/EicPresentation.h
@@ -30,7 +30,13 @@
// The maximum size we support for public keys in reader certificates.
#define EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE 65
+// Constant used to convey that no session is associated with a presentation.
+#define EIC_PRESENTATION_ID_UNSET 0
+
typedef struct {
+ // A non-zero number unique for this EicPresentation instance
+ uint32_t id;
+
int featureLevel;
uint8_t storageKey[EIC_AES_128_KEY_SIZE];
@@ -38,6 +44,10 @@
uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE];
+ // If non-zero (not EIC_PRESENTATION_ID_UNSET), the id of the EicSession object this
+ // presentation object is associated with.
+ uint32_t sessionId;
+
// The challenge generated with eicPresentationCreateAuthChallenge()
uint64_t authChallenge;
@@ -93,10 +103,18 @@
EicCbor cbor;
} EicPresentation;
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
- size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
+// If sessionId is zero (EIC_PRESENTATION_ID_UNSET), the presentation object is not associated
+// with a session object. Otherwise it's the id of the session object.
+//
+bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential,
+ const char* docType, size_t docTypeLength,
+ const uint8_t* encryptedCredentialKeys,
size_t encryptedCredentialKeysSize);
+bool eicPresentationShutdown(EicPresentation* ctx);
+
+bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId);
+
bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType,
size_t docTypeLength, time_t now,
uint8_t* publicKeyCert, size_t* publicKeyCertSize,
diff --git a/identity/aidl/default/libeic/EicProvisioning.c b/identity/aidl/default/libeic/EicProvisioning.c
index c9df4fd..ff009dd 100644
--- a/identity/aidl/default/libeic/EicProvisioning.c
+++ b/identity/aidl/default/libeic/EicProvisioning.c
@@ -17,8 +17,21 @@
#include "EicProvisioning.h"
#include "EicCommon.h"
+#include <inttypes.h>
+
+// Global used for assigning ids for provisioning objects.
+//
+static uint32_t gProvisioningLastIdAssigned = 0;
+
bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) {
eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+
+ if (!eicNextId(&gProvisioningLastIdAssigned)) {
+ eicDebug("Error getting id for object");
+ return false;
+ }
+ ctx->id = gProvisioningLastIdAssigned;
+
ctx->testCredential = testCredential;
if (!eicOpsRandom(ctx->storageKey, EIC_AES_128_KEY_SIZE)) {
return false;
@@ -47,6 +60,13 @@
}
eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+
+ if (!eicNextId(&gProvisioningLastIdAssigned)) {
+ eicDebug("Error getting id for object");
+ return false;
+ }
+ ctx->id = gProvisioningLastIdAssigned;
+
ctx->testCredential = testCredential;
if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys,
@@ -96,9 +116,27 @@
return true;
}
+bool eicProvisioningShutdown(EicProvisioning* ctx) {
+ if (ctx->id == 0) {
+ eicDebug("Trying to shut down provsioning with id 0");
+ return false;
+ }
+ eicDebug("Shut down provsioning with id %" PRIu32, ctx->id);
+ eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+ return true;
+}
+
+bool eicProvisioningGetId(EicProvisioning* ctx, uint32_t* outId) {
+ *outId = ctx->id;
+ return true;
+}
+
bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge,
size_t challengeSize, const uint8_t* applicationId,
- size_t applicationIdSize, uint8_t* publicKeyCert,
+ size_t applicationIdSize, const uint8_t* attestationKeyBlob,
+ size_t attestationKeyBlobSize,
+ const uint8_t* attestationKeyCert,
+ size_t attestationKeyCertSize, uint8_t* publicKeyCert,
size_t* publicKeyCertSize) {
if (ctx->isUpdate) {
eicDebug("Cannot create CredentialKey on update");
@@ -107,7 +145,9 @@
if (!eicOpsCreateCredentialKey(ctx->credentialPrivateKey, challenge, challengeSize,
applicationId, applicationIdSize, ctx->testCredential,
- publicKeyCert, publicKeyCertSize)) {
+ attestationKeyBlob, attestationKeyBlobSize, attestationKeyCert,
+ attestationKeyCertSize, publicKeyCert, publicKeyCertSize)) {
+ eicDebug("Error creating credential key");
return false;
}
return true;
diff --git a/identity/aidl/default/libeic/EicProvisioning.h b/identity/aidl/default/libeic/EicProvisioning.h
index 92f1e4a..2619bfc 100644
--- a/identity/aidl/default/libeic/EicProvisioning.h
+++ b/identity/aidl/default/libeic/EicProvisioning.h
@@ -31,6 +31,9 @@
#define EIC_MAX_NUM_ACCESS_CONTROL_PROFILE_IDS 32
typedef struct {
+ // A non-zero number unique for this EicProvisioning instance
+ uint32_t id;
+
// Set by eicCreateCredentialKey() OR eicProvisioningInitForUpdate()
uint8_t credentialPrivateKey[EIC_P256_PRIV_KEY_SIZE];
@@ -68,9 +71,16 @@
size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
size_t encryptedCredentialKeysSize);
+bool eicProvisioningShutdown(EicProvisioning* ctx);
+
+bool eicProvisioningGetId(EicProvisioning* ctx, uint32_t* outId);
+
bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge,
size_t challengeSize, const uint8_t* applicationId,
- size_t applicationIdSize, uint8_t* publicKeyCert,
+ size_t applicationIdSize, const uint8_t* attestationKeyBlob,
+ size_t attestationKeyBlobSize,
+ const uint8_t* attestationKeyCert,
+ size_t attestationKeyCertSize, uint8_t* publicKeyCert,
size_t* publicKeyCertSize);
bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount,
diff --git a/identity/aidl/default/libeic/EicSession.c b/identity/aidl/default/libeic/EicSession.c
new file mode 100644
index 0000000..d0c7a0d
--- /dev/null
+++ b/identity/aidl/default/libeic/EicSession.c
@@ -0,0 +1,120 @@
+/*
+ * 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 <inttypes.h>
+
+#include "EicCommon.h"
+#include "EicSession.h"
+
+// Global used for assigning ids for session objects.
+//
+static uint32_t gSessionLastIdAssigned = 0;
+
+// The current session object or NULL if never initialized or if it has been shut down.
+//
+static EicSession* gSessionCurrent = NULL;
+
+EicSession* eicSessionGetForId(uint32_t sessionId) {
+ if (gSessionCurrent != NULL && gSessionCurrent->id == sessionId) {
+ return gSessionCurrent;
+ }
+ return NULL;
+}
+
+bool eicSessionInit(EicSession* ctx) {
+ eicMemSet(ctx, '\0', sizeof(EicSession));
+
+ if (!eicNextId(&gSessionLastIdAssigned)) {
+ eicDebug("Error getting id for object");
+ return false;
+ }
+ ctx->id = gSessionLastIdAssigned;
+
+ do {
+ if (!eicOpsRandom((uint8_t*)&(ctx->authChallenge), sizeof(ctx->authChallenge))) {
+ eicDebug("Failed generating random challenge");
+ return false;
+ }
+ } while (ctx->authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET);
+
+ if (!eicOpsCreateEcKey(ctx->ephemeralPrivateKey, ctx->ephemeralPublicKey)) {
+ eicDebug("Error creating ephemeral key-pair");
+ return false;
+ }
+
+ gSessionCurrent = ctx;
+ eicDebug("Initialized session with id %" PRIu32, ctx->id);
+ return true;
+}
+
+bool eicSessionShutdown(EicSession* ctx) {
+ if (ctx->id == 0) {
+ eicDebug("Trying to shut down session with id 0");
+ return false;
+ }
+ eicDebug("Shut down session with id %" PRIu32, ctx->id);
+ eicMemSet(ctx, '\0', sizeof(EicSession));
+ gSessionCurrent = NULL;
+ return true;
+}
+
+bool eicSessionGetId(EicSession* ctx, uint32_t* outId) {
+ *outId = ctx->id;
+ return true;
+}
+
+bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge) {
+ *outAuthChallenge = ctx->authChallenge;
+ return true;
+}
+
+bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
+ uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]) {
+ eicMemCpy(ephemeralPrivateKey, ctx->ephemeralPrivateKey, EIC_P256_PRIV_KEY_SIZE);
+ return true;
+}
+
+bool eicSessionSetReaderEphemeralPublicKey(
+ EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]) {
+ eicMemCpy(ctx->readerEphemeralPublicKey, readerEphemeralPublicKey, EIC_P256_PUB_KEY_SIZE);
+ return true;
+}
+
+bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
+ size_t sessionTranscriptSize) {
+ // Only accept the SessionTranscript if X and Y from the ephemeral key
+ // we created is somewhere in SessionTranscript...
+ //
+ if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
+ EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+ eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
+ return false;
+ }
+ if (eicMemMem(sessionTranscript, sessionTranscriptSize,
+ ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
+ EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+ eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
+ return false;
+ }
+
+ // To save space we only store the SHA-256 of SessionTranscript
+ //
+ EicSha256Ctx shaCtx;
+ eicOpsSha256Init(&shaCtx);
+ eicOpsSha256Update(&shaCtx, sessionTranscript, sessionTranscriptSize);
+ eicOpsSha256Final(&shaCtx, ctx->sessionTranscriptSha256);
+ return true;
+}
diff --git a/identity/aidl/default/libeic/EicSession.h b/identity/aidl/default/libeic/EicSession.h
new file mode 100644
index 0000000..0303dae
--- /dev/null
+++ b/identity/aidl/default/libeic/EicSession.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION)
+#error "Never include this file directly, include libeic.h instead."
+#endif
+
+#ifndef ANDROID_HARDWARE_IDENTITY_EIC_SESSION_H
+#define ANDROID_HARDWARE_IDENTITY_EIC_SESSION_H
+
+#include "EicOps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ // A non-zero number unique for this EicSession instance
+ uint32_t id;
+
+ // The challenge generated at construction time by eicSessionInit().
+ uint64_t authChallenge;
+
+ uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE];
+ uint8_t ephemeralPublicKey[EIC_P256_PUB_KEY_SIZE];
+
+ uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE];
+
+ uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+
+} EicSession;
+
+bool eicSessionInit(EicSession* ctx);
+
+bool eicSessionShutdown(EicSession* ctx);
+
+bool eicSessionGetId(EicSession* ctx, uint32_t* outId);
+
+bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge);
+
+bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
+ uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]);
+
+bool eicSessionSetReaderEphemeralPublicKey(
+ EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]);
+
+bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
+ size_t sessionTranscriptSize);
+
+// Looks up an active session with the given id.
+//
+// Returns NULL if no active session with the given id is found.
+//
+EicSession* eicSessionGetForId(uint32_t sessionId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H
diff --git a/identity/aidl/default/libeic/libeic.h b/identity/aidl/default/libeic/libeic.h
index 20c8896..d89fc9a 100644
--- a/identity/aidl/default/libeic/libeic.h
+++ b/identity/aidl/default/libeic/libeic.h
@@ -27,10 +27,11 @@
*/
#define EIC_INSIDE_LIBEIC_H
#include "EicCbor.h"
+#include "EicCommon.h"
#include "EicOps.h"
#include "EicPresentation.h"
#include "EicProvisioning.h"
-#include "EicCommon.h"
+#include "EicSession.h"
#undef EIC_INSIDE_LIBEIC_H
#ifdef __cplusplus
diff --git a/identity/aidl/default/service.cpp b/identity/aidl/default/service.cpp
index c290c08..ed3c4cb 100644
--- a/identity/aidl/default/service.cpp
+++ b/identity/aidl/default/service.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "android.hardware.identity-service"
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -26,24 +27,39 @@
using ::android::sp;
using ::android::base::InitLogging;
+using ::android::base::LogdLogger;
+using ::android::base::LogId;
+using ::android::base::LogSeverity;
using ::android::base::StderrLogger;
using ::aidl::android::hardware::identity::IdentityCredentialStore;
+using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
using ::android::hardware::identity::FakeSecureHardwareProxyFactory;
using ::android::hardware::identity::SecureHardwareProxyFactory;
+void ComboLogger(LogId id, LogSeverity severity, const char* tag, const char* file,
+ unsigned int line, const char* message) {
+ StderrLogger(id, severity, tag, file, line, message);
+
+ static LogdLogger logdLogger;
+ logdLogger(id, severity, tag, file, line, message);
+}
+
int main(int /*argc*/, char* argv[]) {
- InitLogging(argv, StderrLogger);
+ InitLogging(argv, ComboLogger);
sp<SecureHardwareProxyFactory> hwProxyFactory = new FakeSecureHardwareProxyFactory();
+ const std::string remotelyProvisionedComponentName =
+ std::string(IRemotelyProvisionedComponent::descriptor) + "/default";
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<IdentityCredentialStore> store =
- ndk::SharedRefBase::make<IdentityCredentialStore>(hwProxyFactory);
+ ndk::SharedRefBase::make<IdentityCredentialStore>(hwProxyFactory,
+ remotelyProvisionedComponentName);
const std::string instance = std::string() + IdentityCredentialStore::descriptor + "/default";
binder_status_t status = AServiceManager_addService(store->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index e5de91e..20faeee 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -11,6 +11,8 @@
name: "VtsHalIdentityTargetTest",
defaults: [
"VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_cpp_static",
+ "keymint_use_latest_hal_aidl_ndk_static",
"use_libaidlvintf_gtest_helper_static",
],
cflags: [
@@ -28,26 +30,44 @@
"EndToEndTests.cpp",
"TestCredentialTests.cpp",
"AuthenticationKeyTests.cpp",
+ "PresentationSessionTests.cpp",
],
shared_libs: [
"libbinder",
+ "libbinder_ndk",
"libcrypto",
],
static_libs: [
+ "android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
"libcppcose_rkp",
"libkeymaster_portable",
+ "libkeymint_vts_test_utils",
"libpuresoftkeymasterdevice",
"android.hardware.keymaster@4.0",
"android.hardware.identity-support-lib",
- "android.hardware.identity-V3-cpp",
- "android.hardware.keymaster-V3-cpp",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.identity-V4-cpp",
+ "android.hardware.keymaster-V4-cpp",
+ "android.hardware.keymaster-V4-ndk",
"libkeymaster4support",
"libkeymaster4_1support",
+ "libkeymint_remote_prov_support",
],
test_suites: [
"general-tests",
"vts",
],
}
+
+java_test_host {
+ name: "IdentityCredentialImplementedTest",
+ libs: [
+ "tradefed",
+ "vts-core-tradefed-harness",
+ ],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "vts",
+ ],
+ test_config: "IdentityCredentialImplementedTest.xml",
+}
diff --git a/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index 7627c9c..a126463 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -146,7 +146,9 @@
credentialData_, &credential)
.isOk());
- vector<uint8_t> challenge = {65, 66, 67};
+ // Implementations must support at least 32 bytes.
+ string challengeString = "0123456789abcdef0123456789abcdef";
+ vector<uint8_t> challenge(challengeString.begin(), challengeString.end());
vector<uint8_t> proofOfDeletionSignature;
ASSERT_TRUE(
credential->deleteCredentialWithChallenge(challenge, &proofOfDeletionSignature).isOk());
@@ -154,8 +156,13 @@
support::coseSignGetPayload(proofOfDeletionSignature);
ASSERT_TRUE(proofOfDeletion);
string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
- EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {0x41, 0x42, 0x43}, true, ]",
- cborPretty);
+ EXPECT_EQ(
+ "['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {"
+ "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+ "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, "
+ "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+ "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}, true, ]",
+ cborPretty);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {}, // Additional data
credentialPubKey_));
}
diff --git a/identity/aidl/vts/IdentityCredentialImplementedTest.xml b/identity/aidl/vts/IdentityCredentialImplementedTest.xml
new file mode 100644
index 0000000..1d76a74
--- /dev/null
+++ b/identity/aidl/vts/IdentityCredentialImplementedTest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs IdentityCredentialImplementedTest">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="IdentityCredentialImplementedTest.jar" />
+ </test>
+</configuration>
diff --git a/identity/aidl/vts/PresentationSessionTests.cpp b/identity/aidl/vts/PresentationSessionTests.cpp
new file mode 100644
index 0000000..88acb26
--- /dev/null
+++ b/identity/aidl/vts/PresentationSessionTests.cpp
@@ -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.
+ */
+
+#define LOG_TAG "PresentationSessionTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+#include <utility>
+
+#include "Util.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::make_pair;
+using std::map;
+using std::optional;
+using std::pair;
+using std::string;
+using std::tie;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::android::hardware::keymaster::HardwareAuthToken;
+using ::android::hardware::keymaster::VerificationToken;
+
+class PresentationSessionTests : public testing::TestWithParam<string> {
+ public:
+ virtual void SetUp() override {
+ credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+ String16(GetParam().c_str()));
+ ASSERT_NE(credentialStore_, nullptr);
+ halApiVersion_ = credentialStore_->getInterfaceVersion();
+ }
+
+ void provisionData();
+
+ void provisionSingleDocument(const string& docType, vector<uint8_t>* outCredentialData,
+ vector<uint8_t>* outCredentialPubKey);
+
+ // Set by provisionData
+ vector<uint8_t> credential1Data_;
+ vector<uint8_t> credential1PubKey_;
+ vector<uint8_t> credential2Data_;
+ vector<uint8_t> credential2PubKey_;
+
+ sp<IIdentityCredentialStore> credentialStore_;
+ int halApiVersion_;
+};
+
+void PresentationSessionTests::provisionData() {
+ provisionSingleDocument("org.iso.18013-5.2019.mdl", &credential1Data_, &credential1PubKey_);
+ provisionSingleDocument("org.blah.OtherhDocTypeXX", &credential2Data_, &credential2PubKey_);
+}
+
+void PresentationSessionTests::provisionSingleDocument(const string& docType,
+ vector<uint8_t>* outCredentialData,
+ vector<uint8_t>* outCredentialPubKey) {
+ bool testCredential = true;
+ sp<IWritableIdentityCredential> wc;
+ ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
+
+ vector<uint8_t> attestationApplicationId;
+ vector<uint8_t> attestationChallenge = {1};
+ vector<Certificate> certChain;
+ ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
+ &certChain)
+ .isOk());
+
+ optional<vector<uint8_t>> optCredentialPubKey =
+ support::certificateChainGetTopMostKey(certChain[0].encodedCertificate);
+ ASSERT_TRUE(optCredentialPubKey);
+ *outCredentialPubKey = optCredentialPubKey.value();
+
+ size_t proofOfProvisioningSize = 106;
+ // Not in v1 HAL, may fail
+ wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
+
+ ASSERT_TRUE(wc->startPersonalization(1 /* numAccessControlProfiles */,
+ {1} /* numDataElementsPerNamespace */)
+ .isOk());
+
+ // Access control profile 0: open access - don't care about the returned SACP
+ SecureAccessControlProfile sacp;
+ ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
+
+ // Single entry - don't care about the returned encrypted data
+ ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
+ vector<uint8_t> encryptedData;
+ ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
+
+ vector<uint8_t> proofOfProvisioningSignature;
+ Status status = wc->finishAddingEntries(outCredentialData, &proofOfProvisioningSignature);
+ EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+}
+
+// This checks that any methods called on an IIdentityCredential obtained via a session
+// returns STATUS_FAILED except for startRetrieval(), startRetrieveEntryValue(),
+// retrieveEntryValue(), finishRetrieval(), setRequestedNamespaces(), setVerificationToken()
+//
+TEST_P(PresentationSessionTests, returnsFailureOnUnsupportedMethods) {
+ if (halApiVersion_ < 4) {
+ GTEST_SKIP() << "Need HAL API version 4, have " << halApiVersion_;
+ }
+
+ provisionData();
+
+ sp<IPresentationSession> session;
+ ASSERT_TRUE(credentialStore_
+ ->createPresentationSession(
+ CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+ &session)
+ .isOk());
+
+ sp<IIdentityCredential> credential;
+ ASSERT_TRUE(session->getCredential(credential1Data_, &credential).isOk());
+
+ Status result;
+
+ vector<uint8_t> signatureProofOfDeletion;
+ result = credential->deleteCredential(&signatureProofOfDeletion);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ vector<uint8_t> ephemeralKeyPair;
+ result = credential->createEphemeralKeyPair(&ephemeralKeyPair);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ result = credential->setReaderEphemeralPublicKey({});
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ int64_t authChallenge;
+ result = credential->createAuthChallenge(&authChallenge);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ Certificate certificate;
+ vector<uint8_t> signingKeyBlob;
+ result = credential->generateSigningKeyPair(&signingKeyBlob, &certificate);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ result = credential->deleteCredentialWithChallenge({}, &signatureProofOfDeletion);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ vector<uint8_t> signatureProofOfOwnership;
+ result = credential->proveOwnership({}, &signatureProofOfOwnership);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+ sp<IWritableIdentityCredential> writableCredential;
+ result = credential->updateCredential(&writableCredential);
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+}
+
+// TODO: need to add tests to check that the returned IIdentityCredential works
+// as intended.
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresentationSessionTests);
+INSTANTIATE_TEST_SUITE_P(
+ Identity, PresentationSessionTests,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+ android::PrintInstanceNameToString);
+
+} // namespace android::hardware::identity
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index c622193..f8ec670 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -125,14 +125,22 @@
credentialData_, &credential)
.isOk());
- vector<uint8_t> challenge = {17, 18};
+ // Implementations must support at least 32 bytes.
+ string challengeString = "0123456789abcdef0123456789abcdef";
+ vector<uint8_t> challenge(challengeString.begin(), challengeString.end());
vector<uint8_t> proofOfOwnershipSignature;
ASSERT_TRUE(credential->proveOwnership(challenge, &proofOfOwnershipSignature).isOk());
optional<vector<uint8_t>> proofOfOwnership =
support::coseSignGetPayload(proofOfOwnershipSignature);
ASSERT_TRUE(proofOfOwnership);
string cborPretty = cppbor::prettyPrint(proofOfOwnership.value(), 32, {});
- EXPECT_EQ("['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {0x11, 0x12}, true, ]", cborPretty);
+ EXPECT_EQ(
+ "['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {"
+ "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+ "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, "
+ "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+ "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}, true, ]",
+ cborPretty);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfOwnershipSignature, {}, // Additional data
credentialPubKey_));
}
diff --git a/identity/aidl/vts/Util.cpp b/identity/aidl/vts/Util.cpp
index 1148cb0..f3d7c30 100644
--- a/identity/aidl/vts/Util.cpp
+++ b/identity/aidl/vts/Util.cpp
@@ -20,12 +20,16 @@
#include <android-base/logging.h>
+#include <KeyMintAidlTestBase.h>
#include <aidl/Gtest.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
#include <android-base/stringprintf.h>
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymasterV4_1/attestation_record.h>
-#include <charconv>
+#include <keymint_support/openssl_utils.h>
+#include <openssl/evp.h>
+#include <charconv>
#include <map>
namespace android::hardware::identity::test_utils {
@@ -36,10 +40,13 @@
using std::string;
using std::vector;
+using ::aidl::android::hardware::security::keymint::test::check_maced_pubkey;
+using ::aidl::android::hardware::security::keymint::test::p256_pub_key;
using ::android::sp;
using ::android::String16;
using ::android::base::StringPrintf;
using ::android::binder::Status;
+using ::android::hardware::security::keymint::MacedPublicKey;
using ::keymaster::X509_Ptr;
bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
@@ -58,6 +65,77 @@
}
}
+optional<vector<vector<uint8_t>>> createFakeRemotelyProvisionedCertificateChain(
+ const MacedPublicKey& macedPublicKey) {
+ // The helper library uses the NDK symbols, so play a little trickery here to convert
+ // the data into the proper type so we can reuse the helper function to get the pubkey.
+ ::aidl::android::hardware::security::keymint::MacedPublicKey ndkMacedPublicKey;
+ ndkMacedPublicKey.macedKey = macedPublicKey.macedKey;
+
+ vector<uint8_t> publicKeyBits;
+ check_maced_pubkey(ndkMacedPublicKey, /*testMode=*/true, &publicKeyBits);
+
+ ::aidl::android::hardware::security::keymint::EVP_PKEY_Ptr publicKey;
+ p256_pub_key(publicKeyBits, &publicKey);
+
+ // Generate an arbitrary root key for our chain
+ bssl::UniquePtr<EC_KEY> ecRootKey(EC_KEY_new());
+ bssl::UniquePtr<EVP_PKEY> rootKey(EVP_PKEY_new());
+ if (ecRootKey.get() == nullptr || rootKey.get() == nullptr) {
+ LOG(ERROR) << "Memory allocation failed";
+ return {};
+ }
+
+ bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ if (group.get() == nullptr) {
+ LOG(ERROR) << "Error creating EC group by curve name";
+ return {};
+ }
+
+ if (EC_KEY_set_group(ecRootKey.get(), group.get()) != 1 ||
+ EC_KEY_generate_key(ecRootKey.get()) != 1 || EC_KEY_check_key(ecRootKey.get()) < 0) {
+ LOG(ERROR) << "Error generating key";
+ return {};
+ }
+
+ if (EVP_PKEY_set1_EC_KEY(rootKey.get(), ecRootKey.get()) != 1) {
+ LOG(ERROR) << "Error getting private key";
+ return {};
+ }
+
+ // The VTS test does not fully validate the chain, so we're ok without the proper CA extensions.
+ map<string, vector<uint8_t>> extensions;
+
+ // Now make a self-signed cert
+ optional<vector<uint8_t>> root = support::ecPublicKeyGenerateCertificate(
+ rootKey.get(), rootKey.get(),
+ /*serialDecimal=*/"31415",
+ /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+ /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+ /*validityNotBefore=*/time(nullptr),
+ /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
+ if (!root) {
+ LOG(ERROR) << "Error generating root cert";
+ return std::nullopt;
+ }
+
+ // Now sign a CA cert so that we have a chain that's good enough to satisfy
+ // the VTS tests.
+ optional<vector<uint8_t>> intermediate = support::ecPublicKeyGenerateCertificate(
+ publicKey.get(), rootKey.get(),
+ /*serialDecimal=*/"42",
+ /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+ /*subject=*/"Android IdentityCredential VTS Test Attestation Certificate",
+ /*validityNotBefore=*/time(nullptr),
+ /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
+ if (!intermediate) {
+ LOG(ERROR) << "Error generating intermediate cert";
+ return std::nullopt;
+ }
+
+ return vector<vector<uint8_t>>{std::move(*intermediate), std::move(*root)};
+}
+
optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
vector<uint8_t> privKey;
return generateReaderCertificate(serialDecimal, &privKey);
diff --git a/identity/aidl/vts/Util.h b/identity/aidl/vts/Util.h
index 80e52a2..b120dc9 100644
--- a/identity/aidl/vts/Util.h
+++ b/identity/aidl/vts/Util.h
@@ -19,6 +19,7 @@
#include <android/hardware/identity/IIdentityCredentialStore.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <android/hardware/security/keymint/MacedPublicKey.h>
#include <cppbor.h>
#include <cppbor_parse.h>
#include <gtest/gtest.h>
@@ -97,6 +98,9 @@
bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
sp<IIdentityCredentialStore>& credentialStore, bool testCredential);
+optional<vector<vector<uint8_t>>> createFakeRemotelyProvisionedCertificateChain(
+ const ::android::hardware::security::keymint::MacedPublicKey& macedPublicKey);
+
optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index e12fe05..7caa259 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -66,7 +66,8 @@
ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
false /* testCredential */));
- string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+ // Must support at least 32 bytes.
+ string challenge = "0123456789abcdef0123456789abcdef";
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
vector<Certificate> attestationCertificate;
string applicationId = "Attestation Verification";
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index bc37020..94d4c88 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -18,6 +18,8 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
#include <android-base/logging.h>
#include <android/hardware/identity/IIdentityCredentialStore.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
@@ -42,6 +44,8 @@
using ::android::sp;
using ::android::String16;
using ::android::binder::Status;
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using ::android::hardware::security::keymint::MacedPublicKey;
class IdentityCredentialTests : public testing::TestWithParam<string> {
public:
@@ -101,6 +105,103 @@
attestationApplicationId, false);
}
+TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithRemoteProvisioning) {
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ if (!hwInfo.isRemoteKeyProvisioningSupported) {
+ GTEST_SKIP() << "Remote provisioning is not supported";
+ }
+
+ Status result;
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
+
+ sp<IRemotelyProvisionedComponent> rpc;
+ result = credentialStore_->getRemotelyProvisionedComponent(&rpc);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ MacedPublicKey macedPublicKey;
+ std::vector<uint8_t> attestationKey;
+ result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
+ test_utils::createFakeRemotelyProvisionedCertificateChain(macedPublicKey);
+ ASSERT_TRUE(remotelyProvisionedCertChain);
+
+ vector<uint8_t> concatenatedCerts;
+ for (const vector<uint8_t>& cert : *remotelyProvisionedCertChain) {
+ concatenatedCerts.insert(concatenatedCerts.end(), cert.begin(), cert.end());
+ }
+ result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+ concatenatedCerts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+ vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+ vector<Certificate> attestationCertificate;
+ vector<uint8_t> attestationApplicationId = {1};
+
+ result = writableCredential->getAttestationCertificate(
+ attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
+ attestationApplicationId, false);
+
+ ASSERT_EQ(remotelyProvisionedCertChain->size() + 1, attestationCertificate.size());
+ for (size_t i = 0; i < remotelyProvisionedCertChain->size(); ++i) {
+ ASSERT_EQ(remotelyProvisionedCertChain->at(i),
+ attestationCertificate[i + 1].encodedCertificate)
+ << "Certificate mismatch (cert index " << i + 1 << " out of "
+ << attestationCertificate.size() << " total certs)";
+ }
+}
+
+TEST_P(IdentityCredentialTests, verifyRemotelyProvisionedKeyMayOnlyBeSetOnce) {
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ if (!hwInfo.isRemoteKeyProvisioningSupported) {
+ GTEST_SKIP() << "Remote provisioning is not supported";
+ }
+
+ sp<IRemotelyProvisionedComponent> rpc;
+ Status result = credentialStore_->getRemotelyProvisionedComponent(&rpc);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ MacedPublicKey macedPublicKey;
+ std::vector<uint8_t> attestationKey;
+ result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
+ test_utils::createFakeRemotelyProvisionedCertificateChain(macedPublicKey);
+ ASSERT_TRUE(remotelyProvisionedCertChain);
+
+ vector<uint8_t> concatenatedCerts;
+ for (const vector<uint8_t>& cert : *remotelyProvisionedCertChain) {
+ concatenatedCerts.insert(concatenatedCerts.end(), cert.begin(), cert.end());
+ }
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ /*testCredential=*/false));
+
+ result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+ concatenatedCerts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+ // Now try again, and verify that the implementation rejects it.
+ result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+ concatenatedCerts);
+ EXPECT_FALSE(result.isOk());
+}
+
TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
Status result;
diff --git a/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java b/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java
new file mode 100644
index 0000000..19568af
--- /dev/null
+++ b/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java
@@ -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.
+ */
+package com.android.tests.security.identity;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.RequiresDevice;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class IdentityCredentialImplementedTest extends BaseHostJUnit4Test {
+ // Returns the ro.vendor.api_level or 0 if not set.
+ //
+ // Throws NumberFormatException if ill-formatted.
+ //
+ // Throws DeviceNotAvailableException if device is not available.
+ //
+ private int getVendorApiLevel() throws NumberFormatException, DeviceNotAvailableException {
+ String vendorApiLevelString =
+ getDevice().executeShellCommand("getprop ro.vendor.api_level").trim();
+ if (vendorApiLevelString.isEmpty()) {
+ return 0;
+ }
+ return Integer.parseInt(vendorApiLevelString);
+ }
+
+ // As of Android 13 (API level 32), Identity Credential is required at feature version 202201
+ // or newer.
+ //
+ @RequiresDevice
+ @Test
+ public void testIdentityCredentialIsImplemented() throws Exception {
+ int vendorApiLevel = getVendorApiLevel();
+ assumeTrue(vendorApiLevel >= 32);
+
+ final String minimumFeatureVersionNeeded = "202201";
+
+ String result = getDevice().executeShellCommand(
+ "pm has-feature android.hardware.identity_credential "
+ + minimumFeatureVersionNeeded);
+ if (!result.trim().equals("true")) {
+ fail("Identity Credential feature version " + minimumFeatureVersionNeeded
+ + " required but not found");
+ }
+ }
+}
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index db1a945..4e3d1f7 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -86,6 +86,9 @@
cc_test {
name: "cppbor_test",
+ tidy_timeout_srcs: [
+ "tests/cppbor_test.cpp",
+ ],
srcs: [
"tests/cppbor_test.cpp",
],
@@ -101,6 +104,9 @@
cc_test_host {
name: "cppbor_host_test",
+ tidy_timeout_srcs: [
+ "tests/cppbor_test.cpp",
+ ],
srcs: [
"tests/cppbor_test.cpp",
],
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 3b91de6..952b69a 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -17,6 +17,8 @@
#ifndef IDENTITY_SUPPORT_INCLUDE_IDENTITY_CREDENTIAL_UTILS_H_
#define IDENTITY_SUPPORT_INCLUDE_IDENTITY_CREDENTIAL_UTILS_H_
+#include <openssl/evp.h>
+
#include <cstdint>
#include <map>
#include <optional>
@@ -128,6 +130,15 @@
const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
bool isTestCredential);
+// Alternate version of createEcKeyPairAndAttestation that accepts an attestation key
+// blob to sign the generated key. Only a single certificate is returned, rather than
+// a full chain.
+//
+optional<std::pair<vector<uint8_t>, vector<uint8_t>>> createEcKeyPairWithAttestationKey(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attestationKeyCert,
+ bool isTestCredential);
+
// (TODO: remove when no longer used by 3rd party.)
optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
@@ -240,6 +251,13 @@
time_t validityNotBefore, time_t validityNotAfter,
const map<string, vector<uint8_t>>& extensions);
+// Identical behavior to the above version of ecPublicKeyGenerateCertificate, except this
+// overload takes OpenSSL key parameters instead of key bitstrings as inputs.
+optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
+ EVP_PKEY* publicKey, EVP_PKEY* signingKey, const string& serialDecimal,
+ const string& issuer, const string& subject, time_t validityNotBefore,
+ time_t validityNotAfter, const map<string, vector<uint8_t>>& extensions);
+
// Performs Elliptic-curve Diffie-Helman using |publicKey| (which must be in the
// format returned by ecKeyPairGetPublicKey()) and |privateKey| (which must be
// in the format returned by ecKeyPairGetPrivateKey()).
@@ -389,6 +407,10 @@
// may be smaller than |maxChunkSize|.
vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize);
+// Extract the issuer subject name from the leaf cert in the given chain,
+// returning it as DER-encoded bytes.
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate);
+
} // namespace support
} // namespace identity
} // namespace hardware
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
index a755db1..af5d82e 100644
--- a/identity/support/include/cppbor/cppbor.h
+++ b/identity/support/include/cppbor/cppbor.h
@@ -274,7 +274,7 @@
virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
private:
- uint64_t addlInfo() const { return -1ll - mValue; }
+ uint64_t addlInfo() const { return -1LL - mValue; }
int64_t mValue;
};
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 7f4674d..4c2f186 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -54,6 +54,7 @@
#include <keymaster/contexts/pure_soft_keymaster_context.h>
#include <keymaster/contexts/soft_attestation_cert.h>
#include <keymaster/keymaster_tags.h>
+#include <keymaster/km_openssl/asymmetric_key.h>
#include <keymaster/km_openssl/attestation_utils.h>
#include <keymaster/km_openssl/certificate_utils.h>
@@ -168,6 +169,254 @@
using X509_NAME_Ptr = bssl::UniquePtr<X509_NAME>;
using X509_EXTENSION_Ptr = bssl::UniquePtr<X509_EXTENSION>;
+namespace {
+
+EVP_PKEY_Ptr generateP256Key() {
+ EC_KEY_Ptr ec_key(EC_KEY_new());
+ EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+ EC_GROUP_Ptr group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+
+ if (ec_key.get() == nullptr || pkey.get() == nullptr) {
+ LOG(ERROR) << "Memory allocation failed";
+ return {};
+ }
+
+ if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+ EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+ LOG(ERROR) << "Error generating key";
+ return {};
+ }
+
+ if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
+ LOG(ERROR) << "Error getting private key";
+ return {};
+ }
+
+ return pkey;
+}
+
+optional<vector<uint8_t>> derEncodeKeyPair(const EVP_PKEY& pkey) {
+ int size = i2d_PrivateKey(&pkey, nullptr);
+ if (size == 0) {
+ LOG(ERROR) << "Error generating public key encoding";
+ return std::nullopt;
+ }
+
+ vector<uint8_t> keyPair(size);
+ unsigned char* p = keyPair.data();
+ i2d_PrivateKey(&pkey, &p);
+
+ return keyPair;
+}
+
+// Generates the attestation certificate with the parameters passed in. Note
+// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
+// milli seconds since epoch. We are setting them to milliseconds due to
+// requirement in AuthorizationSet KM_DATE fields. The certificate created is
+// actually in seconds.
+//
+optional<vector<vector<uint8_t>>> signAttestationCertificate(
+ const ::keymaster::PureSoftKeymasterContext& context, const EVP_PKEY* key,
+ const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& derAttestationCertSubjectName, uint64_t activeTimeMilliSeconds,
+ uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+ ::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_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
+ .Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
+ .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
+ challenge.size())
+ .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
+ // Even though identity attestation hal said the application
+ // id should be in software enforced authentication set,
+ // keymaster portable lib expect the input in this
+ // parameter because the software enforced in input to keymaster
+ // refers to the key software enforced properties. And this
+ // parameter refers to properties of the attestation which
+ // 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,
+ // so we don't need to set those or application id.
+ ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
+ ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
+
+ ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
+ ::keymaster::AuthorizationSetBuilder()
+ .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
+ .Authorization(::keymaster::TAG_KEY_SIZE, 256)
+ .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
+ .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
+ .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
+ .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
+ .Authorization(::keymaster::TAG_OS_VERSION, 42)
+ .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
+
+ // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
+ if (!isTestCredential) {
+ hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
+ }
+ ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
+
+ keymaster_error_t error;
+ ::keymaster::AttestKeyInfo attestKeyInfo;
+ ::keymaster::KeymasterBlob issuerSubjectNameBlob;
+ if (!attestationKeyBlob.empty()) {
+ ::keymaster::KeymasterKeyBlob blob(attestationKeyBlob.data(), attestationKeyBlob.size());
+ ::keymaster::UniquePtr<::keymaster::Key> parsedKey;
+ error = context.ParseKeyBlob(blob, /*additional_params=*/{}, &parsedKey);
+ if (error != KM_ERROR_OK) {
+ LOG(ERROR) << "Error loading attestation key: " << error;
+ return std::nullopt;
+ }
+
+ attestKeyInfo.signing_key =
+ static_cast<::keymaster::AsymmetricKey&>(*parsedKey).InternalToEvp();
+ issuerSubjectNameBlob = ::keymaster::KeymasterBlob(derAttestationCertSubjectName.data(),
+ derAttestationCertSubjectName.size());
+ attestKeyInfo.issuer_subject = &issuerSubjectNameBlob;
+ }
+
+ ::keymaster::CertificateChain certChain = generate_attestation(
+ key, swEnforced, hwEnforced, auth_set, std::move(attestKeyInfo), context, &error);
+
+ if (KM_ERROR_OK != error) {
+ LOG(ERROR) << "Error generating attestation from EVP key: " << error;
+ return std::nullopt;
+ }
+
+ vector<vector<uint8_t>> vectors(certChain.entry_count);
+ for (std::size_t i = 0; i < certChain.entry_count; i++) {
+ vectors[i] = {certChain.entries[i].data,
+ certChain.entries[i].data + certChain.entries[i].data_length};
+ }
+ return vectors;
+}
+
+int parseDigits(const char** s, int numDigits) {
+ int result;
+ auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+ if (ec != std::errc()) {
+ LOG(ERROR) << "Error parsing " << numDigits << " digits "
+ << " from " << s;
+ return 0;
+ }
+ *s += numDigits;
+ return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+ struct tm tm;
+
+ memset(&tm, '\0', sizeof(tm));
+ const char* timeStr = (const char*)asn1Time->data;
+ const char* s = timeStr;
+ if (asn1Time->type == V_ASN1_UTCTIME) {
+ tm.tm_year = parseDigits(&s, 2);
+ if (tm.tm_year < 70) {
+ tm.tm_year += 100;
+ }
+ } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+ tm.tm_year = parseDigits(&s, 4) - 1900;
+ tm.tm_year -= 1900;
+ } else {
+ LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+ return false;
+ }
+ tm.tm_mon = parseDigits(&s, 2) - 1;
+ tm.tm_mday = parseDigits(&s, 2);
+ tm.tm_hour = parseDigits(&s, 2);
+ tm.tm_min = parseDigits(&s, 2);
+ tm.tm_sec = parseDigits(&s, 2);
+ // This may need to be updated if someone create certificates using +/- instead of Z.
+ //
+ if (*s != 'Z') {
+ LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
+ return false;
+ }
+
+ time_t t = timegm(&tm);
+ if (t == -1) {
+ LOG(ERROR) << "Error converting broken-down time to time_t";
+ return false;
+ }
+ *outTime = t;
+ return true;
+}
+
+optional<uint64_t> getCertificateExpiryAsMillis(const uint8_t* derCert, size_t derCertSize) {
+ X509_Ptr x509Cert(d2i_X509(nullptr, &derCert, derCertSize));
+ if (!x509Cert) {
+ LOG(ERROR) << "Error parsing certificate";
+ return std::nullopt;
+ }
+
+ time_t notAfter;
+ if (!parseAsn1Time(X509_get0_notAfter(x509Cert.get()), ¬After)) {
+ LOG(ERROR) << "Error getting notAfter from batch certificate";
+ return std::nullopt;
+ }
+
+ return notAfter * 1000;
+}
+
+optional<vector<vector<uint8_t>>> createAttestation(EVP_PKEY* pkey,
+ const vector<uint8_t>& challenge,
+ const vector<uint8_t>& applicationId,
+ bool isTestCredential) {
+ // Pretend to be implemented in a trusted environment just so we can pass
+ // the VTS tests. Of course, this is a pretend-only game since hopefully no
+ // relying party is ever going to trust our batch key and those keys above
+ // it.
+ ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
+ KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+
+ keymaster_error_t error;
+ ::keymaster::CertificateChain attestation_chain =
+ context.GetAttestationChain(KM_ALGORITHM_EC, &error);
+ if (KM_ERROR_OK != error) {
+ LOG(ERROR) << "Error getting attestation chain " << error;
+ return std::nullopt;
+ }
+
+ if (attestation_chain.entry_count < 1) {
+ LOG(ERROR) << "Expected at least one entry in attestation chain";
+ return std::nullopt;
+ }
+
+ uint64_t activeTimeMs = time(nullptr) * 1000;
+ optional<uint64_t> expireTimeMs = getCertificateExpiryAsMillis(
+ attestation_chain.entries[0].data, attestation_chain.entries[0].data_length);
+ if (!expireTimeMs) {
+ LOG(ERROR) << "Error getting expiration time for batch cert";
+ return std::nullopt;
+ }
+
+ return signAttestationCertificate(context, pkey, applicationId, challenge,
+ /*attestationKeyBlob=*/{},
+ /*derAttestationCertSubjectName=*/{}, activeTimeMs,
+ *expireTimeMs, isTestCredential);
+}
+
+} // namespace
+
// bool getRandom(size_t numBytes, vector<uint8_t>& output) {
optional<vector<uint8_t>> getRandom(size_t numBytes) {
vector<uint8_t> output;
@@ -577,69 +826,30 @@
return hmac;
}
-int parseDigits(const char** s, int numDigits) {
- int result;
- auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
- if (ec != std::errc()) {
- LOG(ERROR) << "Error parsing " << numDigits << " digits "
- << " from " << s;
- return 0;
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ bool isTestCredential) {
+ EVP_PKEY_Ptr pkey = generateP256Key();
+
+ optional<vector<vector<uint8_t>>> attestationCertChain =
+ createAttestation(pkey.get(), challenge, applicationId, isTestCredential);
+ if (!attestationCertChain) {
+ LOG(ERROR) << "Error create attestation from key and challenge";
+ return {};
}
- *s += numDigits;
- return result;
+
+ optional<vector<uint8_t>> keyPair = derEncodeKeyPair(*pkey);
+ if (!keyPair) {
+ return std::nullopt;
+ }
+
+ return make_pair(*keyPair, *attestationCertChain);
}
-bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
- struct tm tm;
-
- memset(&tm, '\0', sizeof(tm));
- const char* timeStr = (const char*)asn1Time->data;
- const char* s = timeStr;
- if (asn1Time->type == V_ASN1_UTCTIME) {
- tm.tm_year = parseDigits(&s, 2);
- if (tm.tm_year < 70) {
- tm.tm_year += 100;
- }
- } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
- tm.tm_year = parseDigits(&s, 4) - 1900;
- tm.tm_year -= 1900;
- } else {
- LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
- return false;
- }
- tm.tm_mon = parseDigits(&s, 2) - 1;
- tm.tm_mday = parseDigits(&s, 2);
- tm.tm_hour = parseDigits(&s, 2);
- tm.tm_min = parseDigits(&s, 2);
- tm.tm_sec = parseDigits(&s, 2);
- // This may need to be updated if someone create certificates using +/- instead of Z.
- //
- if (*s != 'Z') {
- LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
- return false;
- }
-
- time_t t = timegm(&tm);
- if (t == -1) {
- LOG(ERROR) << "Error converting broken-down time to time_t";
- return false;
- }
- *outTime = t;
- return true;
-}
-
-// Generates the attestation certificate with the parameters passed in. Note
-// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
-// milli seconds since epoch. We are setting them to milliseconds due to
-// requirement in AuthorizationSet KM_DATE fields. The certificate created is
-// actually in seconds.
-//
-// If 0 is passed for expiration time, the expiration time from batch
-// certificate will be used.
-//
-optional<vector<vector<uint8_t>>> createAttestation(
- const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
- uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+optional<std::pair<vector<uint8_t>, vector<uint8_t>>> createEcKeyPairWithAttestationKey(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attestationKeyCert,
+ bool isTestCredential) {
// Pretend to be implemented in a trusted environment just so we can pass
// the VTS tests. Of course, this is a pretend-only game since hopefully no
// relying party is ever going to trust our batch key and those keys above
@@ -647,148 +857,45 @@
::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
- keymaster_error_t error;
- ::keymaster::CertificateChain attestation_chain =
- context.GetAttestationChain(KM_ALGORITHM_EC, &error);
- if (KM_ERROR_OK != error) {
- LOG(ERROR) << "Error getting attestation chain " << error;
- return {};
- }
- if (expireTimeMilliSeconds == 0) {
- if (attestation_chain.entry_count < 1) {
- LOG(ERROR) << "Expected at least one entry in attestation chain";
- return {};
- }
- keymaster_blob_t* bcBlob = &(attestation_chain.entries[0]);
- const uint8_t* bcData = bcBlob->data;
- auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
- time_t bcNotAfter;
- if (!parseAsn1Time(X509_get0_notAfter(bc.get()), &bcNotAfter)) {
- LOG(ERROR) << "Error getting notAfter from batch certificate";
- return {};
- }
- expireTimeMilliSeconds = bcNotAfter * 1000;
+ EVP_PKEY_Ptr pkey = generateP256Key();
+
+ uint64_t validFromMs = time(nullptr) * 1000;
+ optional<uint64_t> notAfterMs =
+ getCertificateExpiryAsMillis(attestationKeyCert.data(), attestationKeyCert.size());
+ if (!notAfterMs) {
+ LOG(ERROR) << "Error getting expiration time for attestation cert";
+ return std::nullopt;
}
- ::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 {};
+ optional<vector<uint8_t>> derIssuerSubject =
+ support::extractDerSubjectFromCertificate(attestationKeyCert);
+ if (!derIssuerSubject) {
+ LOG(ERROR) << "Error error extracting issuer name from the given certificate chain";
+ return std::nullopt;
}
- 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_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
- .Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
- .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
- challenge.size())
- .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
- // Even though identity attestation hal said the application
- // id should be in software enforced authentication set,
- // keymaster portable lib expect the input in this
- // parameter because the software enforced in input to keymaster
- // refers to the key software enforced properties. And this
- // parameter refers to properties of the attestation which
- // 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,
- // so we don't need to set those or application id.
- ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
- ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
-
- ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
- ::keymaster::AuthorizationSetBuilder()
- .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(::keymaster::TAG_KEY_SIZE, 256)
- .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
- .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
- .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
- .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
- .Authorization(::keymaster::TAG_OS_VERSION, 42)
- .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
-
- // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
- if (!isTestCredential) {
- hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
+ optional<vector<vector<uint8_t>>> attestationCertChain = signAttestationCertificate(
+ context, pkey.get(), applicationId, challenge, attestationKeyBlob, *derIssuerSubject,
+ validFromMs, *notAfterMs, isTestCredential);
+ if (!attestationCertChain) {
+ LOG(ERROR) << "Error signing attestation certificate";
+ return std::nullopt;
}
- ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
-
- ::keymaster::CertificateChain cert_chain_out = generate_attestation(
- key, swEnforced, hwEnforced, auth_set, {} /* attest_key */, context, &error);
-
- if (KM_ERROR_OK != error) {
- LOG(ERROR) << "Error generating attestation from EVP key: " << error;
- return {};
- }
-
- // translate certificate format from keymaster_cert_chain_t to vector<vector<uint8_t>>.
- vector<vector<uint8_t>> attestationCertificate;
- for (std::size_t i = 0; i < cert_chain_out.entry_count; i++) {
- attestationCertificate.insert(
- attestationCertificate.end(),
- vector<uint8_t>(
- cert_chain_out.entries[i].data,
- cert_chain_out.entries[i].data + cert_chain_out.entries[i].data_length));
- }
-
- return attestationCertificate;
-}
-
-optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
- const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
- bool isTestCredential) {
- auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
- auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
- auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-
- if (ec_key.get() == nullptr || pkey.get() == nullptr) {
- LOG(ERROR) << "Memory allocation failed";
- return {};
- }
-
- if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
- EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
- LOG(ERROR) << "Error generating key";
- return {};
- }
-
- if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
- LOG(ERROR) << "Error getting private key";
- return {};
- }
-
- uint64_t nowMs = time(nullptr) * 1000;
- uint64_t expireTimeMs = 0; // Set to same as batch certificate
-
- optional<vector<vector<uint8_t>>> attestationCert = createAttestation(
- pkey.get(), applicationId, challenge, nowMs, expireTimeMs, isTestCredential);
- if (!attestationCert) {
+ if (!attestationCertChain) {
LOG(ERROR) << "Error create attestation from key and challenge";
- return {};
+ return std::nullopt;
+ }
+ if (attestationCertChain->size() != 1) {
+ LOG(ERROR) << "Expected exactly one attestation cert, got " << attestationCertChain->size();
+ return std::nullopt;
}
- int size = i2d_PrivateKey(pkey.get(), nullptr);
- if (size == 0) {
- LOG(ERROR) << "Error generating public key encoding";
- return {};
+ optional<vector<uint8_t>> keyPair = derEncodeKeyPair(*pkey);
+ if (!keyPair) {
+ return std::nullopt;
}
- vector<uint8_t> keyPair(size);
- unsigned char* p = keyPair.data();
- i2d_PrivateKey(pkey.get(), &p);
-
- return make_pair(keyPair, attestationCert.value());
+ return make_pair(*keyPair, attestationCertChain->at(0));
}
optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
@@ -820,12 +927,8 @@
return {};
}
- uint64_t nowMs = time(nullptr) * 1000;
- uint64_t expireTimeMs = 0; // Set to same as batch certificate
-
optional<vector<vector<uint8_t>>> attestationCert =
- createAttestation(pkey.get(), applicationId, challenge, nowMs, expireTimeMs,
- false /* isTestCredential */);
+ createAttestation(pkey.get(), applicationId, challenge, false /* isTestCredential */);
if (!attestationCert) {
LOG(ERROR) << "Error create attestation from key and challenge";
return {};
@@ -1134,6 +1237,14 @@
return {};
}
+ return ecPublicKeyGenerateCertificate(pkey.get(), privPkey.get(), serialDecimal, issuer,
+ subject, validityNotBefore, validityNotAfter, extensions);
+}
+
+optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
+ EVP_PKEY* publicKey, EVP_PKEY* signingKey, const string& serialDecimal,
+ const string& issuer, const string& subject, time_t validityNotBefore,
+ time_t validityNotAfter, const map<string, vector<uint8_t>>& extensions) {
auto x509 = X509_Ptr(X509_new());
if (!x509.get()) {
LOG(ERROR) << "Error creating X509 certificate";
@@ -1145,7 +1256,7 @@
return {};
}
- if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
+ if (X509_set_pubkey(x509.get(), publicKey) != 1) {
LOG(ERROR) << "Error setting public key";
return {};
}
@@ -1220,7 +1331,7 @@
}
}
- if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
+ if (X509_sign(x509.get(), signingKey, EVP_sha256()) == 0) {
LOG(ERROR) << "Error signing X509 certificate";
return {};
}
@@ -2182,6 +2293,36 @@
return testHardwareBoundKey;
}
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate) {
+ const uint8_t* input = certificate.data();
+ X509_Ptr cert(d2i_X509(/*cert=*/nullptr, &input, certificate.size()));
+ if (!cert) {
+ LOG(ERROR) << "Failed to parse certificate";
+ return std::nullopt;
+ }
+
+ X509_NAME* subject = X509_get_subject_name(cert.get());
+ if (!subject) {
+ LOG(ERROR) << "Failed to retrieve subject name";
+ return std::nullopt;
+ }
+
+ int encodedSubjectLength = i2d_X509_NAME(subject, /*out=*/nullptr);
+ if (encodedSubjectLength < 0) {
+ LOG(ERROR) << "Error obtaining encoded subject name length";
+ return std::nullopt;
+ }
+
+ vector<uint8_t> encodedSubject(encodedSubjectLength);
+ uint8_t* out = encodedSubject.data();
+ if (encodedSubjectLength != i2d_X509_NAME(subject, &out)) {
+ LOG(ERROR) << "Error encoding subject name";
+ return std::nullopt;
+ }
+
+ return encodedSubject;
+}
+
} // namespace support
} // namespace identity
} // namespace hardware
diff --git a/ir/OWNERS b/ir/OWNERS
new file mode 100644
index 0000000..04de9ef
--- /dev/null
+++ b/ir/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 163905
+connoro@google.com
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
new file mode 100644
index 0000000..a623491
--- /dev/null
+++ b/ir/aidl/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.ir",
+ vendor_available: true,
+ srcs: ["android/hardware/ir/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ ndk: {
+ vndk: {
+ // TODO(b/206116595) enable this
+ enabled: false,
+ },
+ },
+ },
+}
diff --git a/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl
new file mode 100644
index 0000000..4a0d286
--- /dev/null
+++ b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.ir;
+@VintfStability
+parcelable ConsumerIrFreqRange {
+ int minHz;
+ int maxHz;
+}
diff --git a/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl
new file mode 100644
index 0000000..07bf4b4
--- /dev/null
+++ b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.ir;
+@VintfStability
+interface IConsumerIr {
+ android.hardware.ir.ConsumerIrFreqRange[] getCarrierFreqs();
+ void transmit(in int carrierFreqHz, in int[] pattern);
+}
diff --git a/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl b/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl
new file mode 100644
index 0000000..ab0276a
--- /dev/null
+++ b/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ir;
+
+@VintfStability
+parcelable ConsumerIrFreqRange {
+ int minHz;
+ int maxHz;
+}
diff --git a/ir/aidl/android/hardware/ir/IConsumerIr.aidl b/ir/aidl/android/hardware/ir/IConsumerIr.aidl
new file mode 100644
index 0000000..f6f9742
--- /dev/null
+++ b/ir/aidl/android/hardware/ir/IConsumerIr.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ir;
+
+import android.hardware.ir.ConsumerIrFreqRange;
+
+@VintfStability
+interface IConsumerIr {
+ /**
+ * Enumerates which frequencies the IR transmitter supports.
+ *
+ * @return - an array of all supported frequency ranges.
+ */
+ ConsumerIrFreqRange[] getCarrierFreqs();
+
+ /**
+ * Sends an IR pattern at a given frequency in HZ.
+ * This call must return when the transmit is complete or encounters an error.
+ *
+ * @param carrierFreq - Frequency of the transmission in HZ.
+ *
+ * @param pattern - Alternating series of on and off periods measured in
+ * microseconds. The carrier should be turned off at the end of a transmit
+ * even if there are an odd number of entries in the pattern array.
+ *
+ * @throws EX_UNSUPPORTED_OPERATION when the frequency is not supported.
+ */
+ void transmit(in int carrierFreqHz, in int[] pattern);
+}
diff --git a/ir/aidl/default/Android.bp b/ir/aidl/default/Android.bp
new file mode 100644
index 0000000..a4fb439
--- /dev/null
+++ b/ir/aidl/default/Android.bp
@@ -0,0 +1,42 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Example binder service of the ir HAL.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+ name: "android.hardware.ir-service.example",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.ir-service.example.rc"],
+ vendor: true,
+ vintf_fragments: ["android.hardware.ir-service.example.xml"],
+
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "android.hardware.ir-V1-ndk",
+ ],
+
+ srcs: ["main.cpp"],
+}
diff --git a/ir/aidl/default/android.hardware.ir-service.example.rc b/ir/aidl/default/android.hardware.ir-service.example.rc
new file mode 100644
index 0000000..56def64
--- /dev/null
+++ b/ir/aidl/default/android.hardware.ir-service.example.rc
@@ -0,0 +1,4 @@
+service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.example
+ class hal
+ user nobody
+ group nobody
diff --git a/ir/aidl/default/android.hardware.ir-service.example.xml b/ir/aidl/default/android.hardware.ir-service.example.xml
new file mode 100644
index 0000000..1a63520
--- /dev/null
+++ b/ir/aidl/default/android.hardware.ir-service.example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.ir</name>
+ <version>1</version>
+ <fqname>IConsumerIr/default</fqname>
+ </hal>
+</manifest>
diff --git a/ir/aidl/default/main.cpp b/ir/aidl/default/main.cpp
new file mode 100644
index 0000000..7c4a816
--- /dev/null
+++ b/ir/aidl/default/main.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/ir/BnConsumerIr.h>
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <numeric>
+
+namespace aidl::android::hardware::ir {
+
+const std::vector<ConsumerIrFreqRange> kSupportedFreqs = {
+ {2000, 4000},
+ {10000, 30000},
+};
+
+class ConsumerIr : public BnConsumerIr {
+ ::ndk::ScopedAStatus getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) override;
+ ::ndk::ScopedAStatus transmit(int32_t in_carrierFreqHz,
+ const std::vector<int32_t>& in_pattern) override;
+};
+
+::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) {
+ *_aidl_return = kSupportedFreqs;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+bool isSupportedFreq(int32_t freq) {
+ for (const auto& range : kSupportedFreqs) {
+ if (freq >= range.minHz && freq <= range.maxHz) return true;
+ }
+ return false;
+}
+
+::ndk::ScopedAStatus ConsumerIr::transmit(int32_t in_carrierFreqHz,
+ const std::vector<int32_t>& in_pattern) {
+ if (isSupportedFreq(in_carrierFreqHz)) {
+ // trasmit the pattern, each integer is number of microseconds in an
+ // alternating on/off state.
+ usleep(std::accumulate(in_pattern.begin(), in_pattern.end(), 0));
+ return ::ndk::ScopedAStatus::ok();
+ } else {
+ // unsupported operation
+ return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::ir
+
+using aidl::android::hardware::ir::ConsumerIr;
+
+int main() {
+ auto binder = ::ndk::SharedRefBase::make<ConsumerIr>();
+ const std::string name = std::string() + ConsumerIr::descriptor + "/default";
+ CHECK_EQ(STATUS_OK, AServiceManager_addService(binder->asBinder().get(), name.c_str()))
+ << "Failed to register " << name;
+
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ ABinderProcess_joinThreadPool();
+
+ return EXIT_FAILURE; // should not reached
+}
diff --git a/ir/aidl/vts/Android.bp b/ir/aidl/vts/Android.bp
new file mode 100644
index 0000000..c2491b8
--- /dev/null
+++ b/ir/aidl/vts/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalIrTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalIrTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.ir-V1-ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/ir/aidl/vts/VtsHalIrTargetTest.cpp b/ir/aidl/vts/VtsHalIrTargetTest.cpp
new file mode 100644
index 0000000..3527625
--- /dev/null
+++ b/ir/aidl/vts/VtsHalIrTargetTest.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ir_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/ir/IConsumerIr.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <vector>
+
+using ::aidl::android::hardware::ir::ConsumerIrFreqRange;
+using ::aidl::android::hardware::ir::IConsumerIr;
+using ::ndk::SpAIBinder;
+
+class ConsumerIrTest : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mIr = IConsumerIr::fromBinder(
+ SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(mIr, nullptr);
+ }
+
+ std::shared_ptr<IConsumerIr> mIr;
+};
+
+// Test transmit() for the min and max frequency of every available range
+TEST_P(ConsumerIrTest, TransmitTest) {
+ std::vector<ConsumerIrFreqRange> ranges;
+ const auto& ret = mIr->getCarrierFreqs(&ranges);
+ ASSERT_TRUE(ret.isOk());
+
+ if (ranges.size() > 0) {
+ uint32_t len = 16;
+ std::vector<int32_t> vec;
+ vec.resize(len);
+ std::fill(vec.begin(), vec.end(), 1000);
+ for (auto range = ranges.begin(); range != ranges.end(); range++) {
+ EXPECT_TRUE(mIr->transmit(range->minHz, vec).isOk());
+ EXPECT_TRUE(mIr->transmit(range->maxHz, vec).isOk());
+ }
+ }
+}
+
+// Test transmit() when called with invalid frequencies
+TEST_P(ConsumerIrTest, BadFreqTest) {
+ uint32_t len = 16;
+ std::vector<int32_t> vec;
+ vec.resize(len);
+ std::fill(vec.begin(), vec.end(), 1);
+ const auto& res = mIr->transmit(-1, vec);
+ EXPECT_FALSE(res.isOk());
+ EXPECT_EQ(res.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConsumerIrTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ConsumerIrTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IConsumerIr::descriptor)),
+ ::android::PrintInstanceNameToString);
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index e2ae803..fde32a7 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
cc_test {
name: "VtsHalKeymasterV3_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "keymaster_hidl_hal_test.cpp",
+ ],
srcs: [
"authorization_set.cpp",
"attestation_record.cpp",
@@ -38,5 +41,11 @@
"libcrypto_static",
"libsoftkeymasterdevice",
],
- test_suites: ["general-tests", "vts"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ sanitize: {
+ cfi: false,
+ },
}
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index dfde060..1c6ae47 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -1254,7 +1254,8 @@
* 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.
+ * generation function and the digest specified with Tag:DIGEST in inputParams must also 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
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 8e5a0ff..f9a02ba 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
cc_test {
name: "VtsHalKeymasterV4_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "keymaster_hidl_hal_test.cpp",
+ ],
srcs: [
"HmacKeySharingTest.cpp",
"VerificationTokenTest.cpp",
@@ -50,6 +53,9 @@
cc_test_library {
name: "libkeymaster4vtstest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "KeymasterHidlTest.cpp",
+ ],
srcs: [
"KeymasterHidlTest.cpp",
],
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index d0ad433..5c3576e 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -443,6 +443,98 @@
AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
}
+void KeymasterHidlTest::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+ int message_size) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(block_mode)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ for (int increment = 1; increment <= message_size; ++increment) {
+ string message(message_size, '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;
+ size_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;
+ }
+ }
+}
+
void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac) {
SCOPED_TRACE("CheckHmacTestVector");
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 2ca7ea7..ad30aa7 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -166,6 +166,8 @@
string MacMessage(const string& message, Digest digest, size_t mac_length);
+ void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
void CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac);
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 773715e..14c756d 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -946,7 +946,11 @@
* UNSUPPORTED_KEY_SIZE.
*/
TEST_P(NewKeyGenerationTest, AesInvalidKeySize) {
+ int32_t firstApiLevel = property_get_int32("ro.board.first_api_level", 0);
for (auto key_size : InvalidKeySizes(Algorithm::AES)) {
+ if (key_size == 192 && SecLevel() == SecurityLevel::STRONGBOX && firstApiLevel < 31) {
+ continue;
+ }
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -1708,6 +1712,7 @@
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);
+ EXPECT_GT(EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, md), 0);
break;
case PaddingMode::RSA_PKCS1_1_5_SIGN:
// PKCS1 is the default; don't need to set anything.
@@ -2927,105 +2932,39 @@
}
/*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
*
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
*/
-TEST_P(EncryptionOperationsTest, AesIncremental) {
- auto block_modes = {
- BlockMode::ECB, BlockMode::CBC, BlockMode::CTR, BlockMode::GCM,
- };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
- 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)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
- 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 */;
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
- AuthorizationSet output_params;
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
- string ciphertext;
- size_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;
- }
- }
- }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
}
struct AesCtrSp80038aTestVector {
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index c650bec..547ce38 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -48,4 +48,7 @@
"general-tests",
"vts",
],
+ sanitize: {
+ cfi: false,
+ },
}
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
index a860bf4..54e1316 100644
--- a/light/aidl/default/main.cpp
+++ b/light/aidl/default/main.cpp
@@ -28,7 +28,7 @@
const std::string instance = std::string() + Lights::descriptor + "/default";
binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reached
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 eddf83f..6caac63 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
@@ -203,9 +203,8 @@
}
int64_t delayUs = finishBy - android::ALooper::GetNowUs();
if (delayUs < 0) return toStatus(android::TIMED_OUT);
- (timeoutUs < 0)
- ? msgCondition.wait(msgLock)
- : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
+ (timeoutUs < 0) ? msgCondition.wait(msgLock)
+ : msgCondition.waitRelative(msgLock, delayUs * 1000LL);
}
}
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index 9d4d092..7b8ec9d 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalMediaOmxV1_0TargetComponentTest",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
+ tidy_timeout_srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
test_suites: [
"vts",
diff --git a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index e73196c..d9a6363 100644
--- a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -20,7 +20,9 @@
#endif
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <android/api-level.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
@@ -264,11 +266,13 @@
// Make sure role name follows expected format based on type and
// isEncoder
- const std::string role_name(
- ::android::GetComponentRole(role.isEncoder, role.type.c_str()));
- EXPECT_EQ(role_name, role.role) << "Role \"" << role.role << "\" does not match "
- << (role.isEncoder ? "an encoder " : "a decoder ")
- << "for mime type \"" << role.type << ".";
+ const char* role_name = ::android::GetComponentRole(role.isEncoder, role.type.c_str());
+ if (role_name != nullptr) {
+ EXPECT_EQ(std::string(role_name), role.role)
+ << "Role \"" << role.role << "\" does not match "
+ << (role.isEncoder ? "an encoder " : "a decoder ") << "for media type \""
+ << role.type << ".";
+ }
// Check the nodes for this role
std::set<const std::string> nodeKeys;
@@ -369,6 +373,31 @@
}
}
+static int getFirstApiLevel() {
+ return android::base::GetIntProperty("ro.product.first_api_level", __ANDROID_API_T__);
+}
+
+// list components and roles.
+TEST_P(StoreHidlTest, OmxCodecAllowedTest) {
+ hidl_vec<IOmx::ComponentInfo> componentInfos = getComponentInfoList(omx);
+ for (IOmx::ComponentInfo info : componentInfos) {
+ for (std::string role : info.mRoles) {
+ if (role.find("video_decoder") != std::string::npos ||
+ role.find("video_encoder") != std::string::npos) {
+ ASSERT_LT(getFirstApiLevel(), __ANDROID_API_S__)
+ << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+ << " not allowed for devices launching with Android S and above";
+ }
+ if (role.find("audio_decoder") != std::string::npos ||
+ role.find("audio_encoder") != std::string::npos) {
+ ASSERT_LT(getFirstApiLevel(), __ANDROID_API_T__)
+ << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+ << " not allowed for devices launching with Android T and above";
+ }
+ }
+ }
+}
+
// list components and roles.
TEST_P(StoreHidlTest, ListNodes) {
description("enumerate component and roles");
diff --git a/memtrack/OWNERS b/memtrack/OWNERS
new file mode 100644
index 0000000..a182ed9
--- /dev/null
+++ b/memtrack/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+connoro@google.com
diff --git a/memtrack/aidl/default/main.cpp b/memtrack/aidl/default/main.cpp
index d063d2a..5cf5f94 100644
--- a/memtrack/aidl/default/main.cpp
+++ b/memtrack/aidl/default/main.cpp
@@ -29,7 +29,7 @@
const std::string instance = std::string() + Memtrack::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // Unreachable
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 31cdded..ad30e30 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -31,16 +31,11 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "android.hardware.neuralnetworks@1.0",
"libarect",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
],
- shared_libs: [
- "android.hardware.neuralnetworks@1.0",
- ],
- export_static_lib_headers: [
- "neuralnetworks_utils_hal_common",
- ],
target: {
android: {
shared_libs: ["libnativewindow"],
@@ -55,19 +50,14 @@
static_libs: [
"android.hardware.neuralnetworks@1.0",
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
],
shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libbase",
"libcutils",
- "libfmq",
"libhidlbase",
- "libhidlmemory",
"liblog",
"libutils",
],
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
index 8bd2fbe..cef76c6 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
@@ -45,12 +45,15 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
private:
const nn::SharedPreparedModel kPreparedModel;
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
index 0a6ca3e..d7c43ef 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -65,8 +65,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
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
index bdb5b54..337c132 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
@@ -49,18 +49,23 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
diff --git a/neuralnetworks/1.0/utils/src/Burst.cpp b/neuralnetworks/1.0/utils/src/Burst.cpp
index 1284721..3642bc6 100644
--- a/neuralnetworks/1.0/utils/src/Burst.cpp
+++ b/neuralnetworks/1.0/utils/src/Burst.cpp
@@ -50,15 +50,20 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const {
- return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
}
nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
- return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration);
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
}
} // 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
index b0c236e..620d040 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -143,7 +143,9 @@
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 {
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that model is ready for IPC.
std::optional<nn::Model> maybeModelInShared;
const nn::Model& modelInShared =
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index 00e7d22..b8055fc 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -59,7 +59,9 @@
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::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -94,19 +96,22 @@
}
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::OptionalDuration& /*loopTimeoutDuration*/,
- const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
<< "IPreparedModel::executeFenced is not supported on 1.0 HAL service";
}
nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
const nn::Request& request, nn::MeasureTiming /*measure*/,
- const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
diff --git a/neuralnetworks/1.0/utils/test/DeviceTest.cpp b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
index 83e555f..9e9db16 100644
--- a/neuralnetworks/1.0/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
@@ -380,7 +380,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -399,7 +399,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -417,7 +417,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -435,7 +435,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -452,7 +452,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -469,7 +469,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -488,7 +488,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
index 7820c06..e03a98d 100644
--- a/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
@@ -121,7 +121,7 @@
.WillOnce(Invoke(makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
@@ -138,7 +138,7 @@
V1_0::ErrorStatus::GENERAL_FAILURE)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -155,7 +155,7 @@
makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -171,7 +171,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -187,7 +187,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -205,7 +205,7 @@
EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -218,7 +218,7 @@
const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -235,7 +235,7 @@
.WillRepeatedly(Invoke(makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -258,7 +258,7 @@
V1_0::ErrorStatus::GENERAL_FAILURE)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -279,7 +279,7 @@
makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -299,7 +299,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -319,7 +319,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -341,7 +341,7 @@
EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -358,7 +358,7 @@
const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
index 737ff58..4b8999f 100644
--- a/neuralnetworks/1.1/utils/Android.bp
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -31,17 +31,12 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
"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",
- ],
}
cc_test {
@@ -52,20 +47,15 @@
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
"neuralnetworks_utils_hal_1_1",
],
shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libbase",
"libcutils",
- "libfmq",
"libhidlbase",
- "libhidlmemory",
"liblog",
"libutils",
],
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
index d6bd36a..38ca138 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -64,8 +64,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index 3effa84..28f3276 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -143,7 +143,9 @@
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 {
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that model is ready for IPC.
std::optional<nn::Model> maybeModelInShared;
const nn::Model& modelInShared =
diff --git a/neuralnetworks/1.1/utils/test/DeviceTest.cpp b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
index 2248da6..8ab87bc 100644
--- a/neuralnetworks/1.1/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
@@ -390,7 +390,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -409,7 +409,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -427,7 +427,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -445,7 +445,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -462,7 +462,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -479,7 +479,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -498,7 +498,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 4eefb0f..e7d514f 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -31,47 +31,35 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "libfmq",
"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",
- "libfmq",
- ],
- export_static_lib_headers: [
- "neuralnetworks_utils_hal_common",
- ],
product_variables: {
debuggable: { // eng and userdebug builds
cflags: ["-DNN_DEBUGGABLE"],
},
},
- target: {
- host: {
- cflags: [
- "-D__INTRODUCED_IN(x)=",
- "-D__assert(a,b,c)=",
- // We want all the APIs to be available on the host.
- "-D__ANDROID_API__=10000",
- ],
- },
- },
}
cc_test {
name: "neuralnetworks_utils_hal_1_2_test",
host_supported: true,
+ tidy_timeout_srcs: [
+ "test/DeviceTest.cpp",
+ "test/PreparedModelTest.cpp",
+ ],
srcs: ["test/*.cpp"],
static_libs: [
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
@@ -79,13 +67,10 @@
"neuralnetworks_utils_hal_1_2",
],
shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libbase",
"libcutils",
"libfmq",
"libhidlbase",
- "libhidlmemory",
"liblog",
"libutils",
],
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
index ac9411c..1b28476 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
@@ -170,13 +170,16 @@
// See IBurst::execute for information on this method.
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
// See IBurst::createReusableExecution for information on this method.
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
// If fallback is not nullptr, this method will invoke the fallback function to try another
// execution path if the packet could not be sent. Otherwise, failing to send the packet will
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
index c3348aa..4f13adc 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -37,7 +37,7 @@
GeneralResult<Operand::ExtraParams> unvalidatedConvert(
const hal::V1_2::Operand::ExtraParams& extraParams);
GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model);
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape);
GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming);
@@ -78,7 +78,7 @@
const nn::Operand::ExtraParams& extraParams);
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
- const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+ const nn::ExtensionNameAndPrefix& extensionNameAndPrefix);
nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape);
nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming);
nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing);
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
index e7ac172..d92cf50 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -83,8 +83,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
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
index 1150e5e..72a5b2f 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -49,18 +49,23 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
diff --git a/neuralnetworks/1.2/utils/src/Burst.cpp b/neuralnetworks/1.2/utils/src/Burst.cpp
index 911fbfa..23e8070 100644
--- a/neuralnetworks/1.2/utils/src/Burst.cpp
+++ b/neuralnetworks/1.2/utils/src/Burst.cpp
@@ -305,8 +305,9 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// This is the first point when we know an execution is occurring, so begin to collect
// systraces. Note that the first point we can begin collecting systraces in
// ExecutionBurstServer is when the RequestChannelReceiver realizes there is data in the FMQ, so
@@ -317,7 +318,7 @@
// fall back to another execution path
if (!compliantVersion(request).ok()) {
// fallback to another execution path if the packet could not be sent
- return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
+ return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
}
// ensure that request is ready for IPC
@@ -346,7 +347,7 @@
// send request packet
const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots);
const auto fallback = [this, &request, measure, &deadline, &loopTimeoutDuration] {
- return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
+ return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
};
return executeInternal(requestPacket, relocation, fallback);
}
@@ -354,14 +355,17 @@
// See IBurst::createReusableExecution for information on this method.
nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "Burst::createReusableExecution");
// if the request is valid but of a higher version than what's supported in burst execution,
// fall back to another execution path
if (!compliantVersion(request).ok()) {
// fallback to another execution path if the packet could not be sent
- return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration);
+ return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, {},
+ {});
}
// ensure that request is ready for IPC
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index 838d9c4..62ec2ed 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -212,9 +212,9 @@
};
}
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
- return Model::ExtensionNameAndPrefix{
+ return ExtensionNameAndPrefix{
.name = extensionNameAndPrefix.name,
.prefix = extensionNameAndPrefix.prefix,
};
@@ -495,7 +495,7 @@
}
nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
- const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+ const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
return Model::ExtensionNameAndPrefix{
.name = extensionNameAndPrefix.name,
.prefix = extensionNameAndPrefix.prefix,
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index e7acecd..3a58d2c 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -236,7 +236,9 @@
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 {
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that model is ready for IPC.
std::optional<nn::Model> maybeModelInShared;
const nn::Model& modelInShared =
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index 6df3df3..feb3951 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -91,7 +91,9 @@
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::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -123,19 +125,22 @@
}
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::OptionalDuration& /*loopTimeoutDuration*/,
- const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(
+ const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+ nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
<< "IPreparedModel::executeFenced is not supported on 1.2 HAL service";
}
nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
diff --git a/neuralnetworks/1.2/utils/test/DeviceTest.cpp b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
index 1dc6285..0d8c141 100644
--- a/neuralnetworks/1.2/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
@@ -636,7 +636,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -655,7 +655,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -673,7 +673,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -691,7 +691,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -708,7 +708,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -725,7 +725,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -746,7 +746,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
index 5e2ad79..a5ec9d3 100644
--- a/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
@@ -154,7 +154,7 @@
.WillOnce(Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
@@ -172,7 +172,7 @@
makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -189,7 +189,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -206,7 +206,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -224,7 +224,7 @@
V1_0::ErrorStatus::NONE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
@@ -243,7 +243,7 @@
kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -261,7 +261,7 @@
V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -278,7 +278,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -295,7 +295,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -314,7 +314,7 @@
EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -328,7 +328,7 @@
PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -347,7 +347,7 @@
Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -371,7 +371,7 @@
makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -392,7 +392,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -413,7 +413,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -436,7 +436,7 @@
V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -461,7 +461,7 @@
kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -483,7 +483,7 @@
V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -504,7 +504,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -525,7 +525,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -548,7 +548,7 @@
EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -566,7 +566,7 @@
PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 52d51e2..2177924 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -44,6 +44,9 @@
cc_test {
name: "VtsHalNeuralnetworksV1_2TargetTest",
defaults: ["neuralnetworks_vts_functional_defaults"],
+ tidy_timeout_srcs: [
+ "CompilationCachingTests.cpp",
+ ],
srcs: [
"BasicTests.cpp",
"CompilationCachingTests.cpp",
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index 7acb4fc..05413e6 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -31,37 +31,26 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ "libfmq",
"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",
- "libfmq",
- ],
- export_static_lib_headers: [
- "neuralnetworks_utils_hal_common",
- ],
- target: {
- host: {
- cflags: [
- "-D__INTRODUCED_IN(x)=",
- "-D__assert(a,b,c)=",
- // We want all the APIs to be available on the host.
- "-D__ANDROID_API__=10000",
- ],
- },
- },
}
cc_test {
name: "neuralnetworks_utils_hal_1_3_test",
host_supported: true,
+ tidy_timeout_srcs: [
+ "test/DeviceTest.cpp",
+ "test/PreparedModelTest.cpp",
+ ],
srcs: ["test/*.cpp"],
static_libs: [
"android.hardware.neuralnetworks@1.0",
@@ -69,7 +58,6 @@
"android.hardware.neuralnetworks@1.2",
"android.hardware.neuralnetworks@1.3",
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
@@ -78,13 +66,10 @@
"neuralnetworks_utils_hal_1_3",
],
shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libbase",
"libcutils",
"libfmq",
"libhidlbase",
- "libhidlmemory",
"liblog",
"libutils",
],
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
index c3c6fc4..cf5e5ea0 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -66,8 +66,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
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
index 480438d..124cc43 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -48,18 +48,23 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index a1d414c..09e9d80 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -396,7 +396,7 @@
}
nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
- const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+ const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
}
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 9517fda..824cec6 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -187,7 +187,9 @@
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 {
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that model is ready for IPC.
std::optional<nn::Model> maybeModelInShared;
const nn::Model& modelInShared =
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index ce977e5..b92f877 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -135,8 +135,9 @@
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::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -174,10 +175,13 @@
}
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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const {
+PreparedModel::executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -230,7 +234,9 @@
nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
diff --git a/neuralnetworks/1.3/utils/test/DeviceTest.cpp b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
index 7eba4bc..6f48837 100644
--- a/neuralnetworks/1.3/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
@@ -658,7 +658,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -677,7 +677,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -695,7 +695,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -713,7 +713,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -730,7 +730,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -747,7 +747,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -768,7 +768,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
index 6dbbd6b..51b5d29 100644
--- a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
@@ -182,7 +182,7 @@
.WillOnce(Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
@@ -200,7 +200,7 @@
makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -217,7 +217,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -234,7 +234,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -252,7 +252,7 @@
V1_3::ErrorStatus::NONE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
@@ -271,7 +271,7 @@
kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -289,7 +289,7 @@
V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -306,7 +306,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -323,7 +323,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -344,7 +344,7 @@
.WillOnce(InvokeWithoutArgs(ret));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -366,7 +366,7 @@
.WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -396,7 +396,7 @@
.WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -422,7 +422,7 @@
makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -439,7 +439,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -456,7 +456,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -475,7 +475,7 @@
Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -499,7 +499,7 @@
makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -520,7 +520,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -541,7 +541,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -564,7 +564,7 @@
V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE, {}, kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -589,7 +589,7 @@
kNoTiming)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -611,7 +611,7 @@
V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -628,7 +628,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -649,7 +649,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -674,7 +674,7 @@
.WillOnce(InvokeWithoutArgs(ret));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -702,7 +702,7 @@
Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -738,7 +738,7 @@
.WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -768,7 +768,7 @@
makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -789,7 +789,7 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -810,7 +810,7 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 8951760..9fa0f0a 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -45,6 +45,10 @@
cc_test {
name: "VtsHalNeuralnetworksV1_3TargetTest",
defaults: ["neuralnetworks_vts_functional_defaults"],
+ tidy_timeout_srcs: [
+ "CompilationCachingTests.cpp",
+ "MemoryDomainTests.cpp",
+ ],
srcs: [
"BasicTests.cpp",
"CompilationCachingTests.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
index e2fa6e4..af3641a 100644
--- a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -1158,12 +1158,15 @@
auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0}, kTestOperand.dimensions);
if (buffer == nullptr) return;
- Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
- Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+ // Use an incompatible dimension and make sure the length matches with the bad dimension.
auto badDimensions = kTestOperand.dimensions;
badDimensions[0] = 2;
+ const uint32_t badTestOperandDataSize = kTestOperandDataSize * 2;
+
+ Request::MemoryPool sharedMemory = createSharedMemoryPool(badTestOperandDataSize);
+ Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
RequestArgument sharedMemoryArg = {
- .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize},
+ .location = {.poolIndex = 0, .offset = 0, .length = badTestOperandDataSize},
.dimensions = badDimensions};
RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
RequestArgument deviceMemoryArgWithBadDimensions = {.location = {.poolIndex = 1},
diff --git a/neuralnetworks/OWNERS b/neuralnetworks/OWNERS
index def3ea9..04c5d72 100644
--- a/neuralnetworks/OWNERS
+++ b/neuralnetworks/OWNERS
@@ -1,10 +1,2 @@
# Bug component: 195575
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-ianhua@google.com
-jeanluc@google.com
-miaowang@google.com
-pszczepaniak@google.com
-xusongw@google.com
+include platform/packages/modules/NeuralNetworks:/NNAPI_OWNERS # Neuralnetworks team
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index 065105a..aa4c4b6 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -38,5 +38,6 @@
versions: [
"1",
"2",
+ "3",
],
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash
new file mode 100644
index 0000000..3b9f018
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash
@@ -0,0 +1 @@
+8c2c4ca2327e6f779dad6119c03d832ea4e1def1
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl
new file mode 100644
index 0000000..05cec76
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable BufferDesc {
+ int[] dimensions;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl
new file mode 100644
index 0000000..10a6b75
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable BufferRole {
+ int modelIndex;
+ int ioIndex;
+ float probability;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl
new file mode 100644
index 0000000..30877c0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Capabilities {
+ android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
+ android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+ android.hardware.neuralnetworks.OperandPerformance[] operandPerformance;
+ android.hardware.neuralnetworks.PerformanceInfo ifPerformance;
+ android.hardware.neuralnetworks.PerformanceInfo whilePerformance;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.aidl
new file mode 100644
index 0000000..db49a38
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable DataLocation {
+ int poolIndex;
+ long offset;
+ long length;
+ long padding;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.aidl
new file mode 100644
index 0000000..7cdd6db
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable DeviceBuffer {
+ android.hardware.neuralnetworks.IBuffer buffer;
+ int token;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.aidl
new file mode 100644
index 0000000..82fe8ae
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum DeviceType {
+ OTHER = 1,
+ CPU = 2,
+ GPU = 3,
+ ACCELERATOR = 4,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.aidl
new file mode 100644
index 0000000..57d5d6e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum ErrorStatus {
+ NONE = 0,
+ DEVICE_UNAVAILABLE = 1,
+ GENERAL_FAILURE = 2,
+ OUTPUT_INSUFFICIENT_SIZE = 3,
+ INVALID_ARGUMENT = 4,
+ MISSED_DEADLINE_TRANSIENT = 5,
+ MISSED_DEADLINE_PERSISTENT = 6,
+ RESOURCE_EXHAUSTED_TRANSIENT = 7,
+ RESOURCE_EXHAUSTED_PERSISTENT = 8,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl
new file mode 100644
index 0000000..4352d8f
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum ExecutionPreference {
+ LOW_POWER = 0,
+ FAST_SINGLE_ANSWER = 1,
+ SUSTAINED_SPEED = 2,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl
new file mode 100644
index 0000000..44e9922
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExecutionResult {
+ boolean outputSufficientSize;
+ android.hardware.neuralnetworks.OutputShape[] outputShapes;
+ android.hardware.neuralnetworks.Timing timing;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.aidl
new file mode 100644
index 0000000..c47028d
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Extension {
+ String name;
+ android.hardware.neuralnetworks.ExtensionOperandTypeInformation[] operandTypes;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
new file mode 100644
index 0000000..6c287fd
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExtensionNameAndPrefix {
+ String name;
+ char prefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
new file mode 100644
index 0000000..a3680aa
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExtensionOperandTypeInformation {
+ char type;
+ boolean isTensor;
+ int byteSize;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl
new file mode 100644
index 0000000..7952b34
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable FencedExecutionResult {
+ android.hardware.neuralnetworks.IFencedExecutionCallback callback;
+ @nullable ParcelFileDescriptor syncFence;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.aidl
new file mode 100644
index 0000000..7e61bbb
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum FusedActivationFunc {
+ NONE = 0,
+ RELU = 1,
+ RELU1 = 2,
+ RELU6 = 3,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.aidl
new file mode 100644
index 0000000..f10e7e2
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IBuffer {
+ void copyFrom(in android.hardware.neuralnetworks.Memory src, in int[] dimensions);
+ void copyTo(in android.hardware.neuralnetworks.Memory dst);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl
new file mode 100644
index 0000000..eb3d0b0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IBurst {
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
+ void releaseMemoryResource(in long memoryIdentifierToken);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl
new file mode 100644
index 0000000..c9c67f2
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IDevice {
+ android.hardware.neuralnetworks.DeviceBuffer allocate(in android.hardware.neuralnetworks.BufferDesc desc, in android.hardware.neuralnetworks.IPreparedModelParcel[] preparedModels, in android.hardware.neuralnetworks.BufferRole[] inputRoles, in android.hardware.neuralnetworks.BufferRole[] outputRoles);
+ android.hardware.neuralnetworks.Capabilities getCapabilities();
+ android.hardware.neuralnetworks.NumberOfCacheFiles getNumberOfCacheFilesNeeded();
+ android.hardware.neuralnetworks.Extension[] getSupportedExtensions();
+ boolean[] getSupportedOperations(in android.hardware.neuralnetworks.Model model);
+ android.hardware.neuralnetworks.DeviceType getType();
+ String getVersionString();
+ void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+ void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+ const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+ const int MAX_NUMBER_OF_CACHE_FILES = 32;
+ const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15;
+ const int EXTENSION_TYPE_LOW_BITS_TYPE = 16;
+ const int OPERAND_TYPE_BASE_MAX = 65535;
+ const int OPERATION_TYPE_BASE_MAX = 65535;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
new file mode 100644
index 0000000..0bfb80a
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IFencedExecutionCallback {
+ android.hardware.neuralnetworks.ErrorStatus getExecutionInfo(out android.hardware.neuralnetworks.Timing timingLaunched, out android.hardware.neuralnetworks.Timing timingFenced);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl
new file mode 100644
index 0000000..fccb5dc
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IPreparedModel {
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
+ android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs);
+ android.hardware.neuralnetworks.IBurst configureExecutionBurst();
+ const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
+ const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
new file mode 100644
index 0000000..e0c763b
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IPreparedModelCallback {
+ void notify(in android.hardware.neuralnetworks.ErrorStatus status, in android.hardware.neuralnetworks.IPreparedModel preparedModel);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
new file mode 100644
index 0000000..dbedf12
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable IPreparedModelParcel {
+ android.hardware.neuralnetworks.IPreparedModel preparedModel;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl
new file mode 100644
index 0000000..37fa102
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+union Memory {
+ android.hardware.common.Ashmem ashmem;
+ android.hardware.common.MappableFile mappableFile;
+ android.hardware.graphics.common.HardwareBuffer hardwareBuffer;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.aidl
new file mode 100644
index 0000000..30d8dda
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Model {
+ android.hardware.neuralnetworks.Subgraph main;
+ android.hardware.neuralnetworks.Subgraph[] referenced;
+ byte[] operandValues;
+ android.hardware.neuralnetworks.Memory[] pools;
+ boolean relaxComputationFloat32toFloat16;
+ android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
new file mode 100644
index 0000000..9314760
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable NumberOfCacheFiles {
+ int numModelCache;
+ int numDataCache;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl
new file mode 100644
index 0000000..1d9bdd8
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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 FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Operand {
+ android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32;
+ int[] dimensions;
+ float scale;
+ int zeroPoint;
+ android.hardware.neuralnetworks.OperandLifeTime lifetime = android.hardware.neuralnetworks.OperandLifeTime.TEMPORARY_VARIABLE;
+ android.hardware.neuralnetworks.DataLocation location;
+ @nullable android.hardware.neuralnetworks.OperandExtraParams extraParams;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.aidl
new file mode 100644
index 0000000..14792cf
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+union OperandExtraParams {
+ android.hardware.neuralnetworks.SymmPerChannelQuantParams channelQuant;
+ byte[] extension;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl
new file mode 100644
index 0000000..40adfb1
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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 FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperandLifeTime {
+ TEMPORARY_VARIABLE = 0,
+ SUBGRAPH_INPUT = 1,
+ SUBGRAPH_OUTPUT = 2,
+ CONSTANT_COPY = 3,
+ CONSTANT_POOL = 4,
+ NO_VALUE = 5,
+ SUBGRAPH = 6,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.aidl
new file mode 100644
index 0000000..ebb361b
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable OperandPerformance {
+ android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32;
+ android.hardware.neuralnetworks.PerformanceInfo info;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl
new file mode 100644
index 0000000..9f2c759
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperandType {
+ FLOAT32 = 0,
+ INT32 = 1,
+ UINT32 = 2,
+ TENSOR_FLOAT32 = 3,
+ TENSOR_INT32 = 4,
+ TENSOR_QUANT8_ASYMM = 5,
+ BOOL = 6,
+ TENSOR_QUANT16_SYMM = 7,
+ TENSOR_FLOAT16 = 8,
+ TENSOR_BOOL8 = 9,
+ FLOAT16 = 10,
+ TENSOR_QUANT8_SYMM_PER_CHANNEL = 11,
+ TENSOR_QUANT16_ASYMM = 12,
+ TENSOR_QUANT8_SYMM = 13,
+ TENSOR_QUANT8_ASYMM_SIGNED = 14,
+ SUBGRAPH = 15,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl
new file mode 100644
index 0000000..a4a3fbe
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Operation {
+ android.hardware.neuralnetworks.OperationType type = android.hardware.neuralnetworks.OperationType.ADD;
+ int[] inputs;
+ int[] outputs;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl
new file mode 100644
index 0000000..34506c8
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl
@@ -0,0 +1,143 @@
+/*
+ * 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 FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperationType {
+ ADD = 0,
+ AVERAGE_POOL_2D = 1,
+ CONCATENATION = 2,
+ CONV_2D = 3,
+ DEPTHWISE_CONV_2D = 4,
+ DEPTH_TO_SPACE = 5,
+ DEQUANTIZE = 6,
+ EMBEDDING_LOOKUP = 7,
+ FLOOR = 8,
+ FULLY_CONNECTED = 9,
+ HASHTABLE_LOOKUP = 10,
+ L2_NORMALIZATION = 11,
+ L2_POOL_2D = 12,
+ LOCAL_RESPONSE_NORMALIZATION = 13,
+ LOGISTIC = 14,
+ LSH_PROJECTION = 15,
+ LSTM = 16,
+ MAX_POOL_2D = 17,
+ MUL = 18,
+ RELU = 19,
+ RELU1 = 20,
+ RELU6 = 21,
+ RESHAPE = 22,
+ RESIZE_BILINEAR = 23,
+ RNN = 24,
+ SOFTMAX = 25,
+ SPACE_TO_DEPTH = 26,
+ SVDF = 27,
+ TANH = 28,
+ BATCH_TO_SPACE_ND = 29,
+ DIV = 30,
+ MEAN = 31,
+ PAD = 32,
+ SPACE_TO_BATCH_ND = 33,
+ SQUEEZE = 34,
+ STRIDED_SLICE = 35,
+ SUB = 36,
+ TRANSPOSE = 37,
+ ABS = 38,
+ ARGMAX = 39,
+ ARGMIN = 40,
+ AXIS_ALIGNED_BBOX_TRANSFORM = 41,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 42,
+ BIDIRECTIONAL_SEQUENCE_RNN = 43,
+ BOX_WITH_NMS_LIMIT = 44,
+ CAST = 45,
+ CHANNEL_SHUFFLE = 46,
+ DETECTION_POSTPROCESSING = 47,
+ EQUAL = 48,
+ EXP = 49,
+ EXPAND_DIMS = 50,
+ GATHER = 51,
+ GENERATE_PROPOSALS = 52,
+ GREATER = 53,
+ GREATER_EQUAL = 54,
+ GROUPED_CONV_2D = 55,
+ HEATMAP_MAX_KEYPOINT = 56,
+ INSTANCE_NORMALIZATION = 57,
+ LESS = 58,
+ LESS_EQUAL = 59,
+ LOG = 60,
+ LOGICAL_AND = 61,
+ LOGICAL_NOT = 62,
+ LOGICAL_OR = 63,
+ LOG_SOFTMAX = 64,
+ MAXIMUM = 65,
+ MINIMUM = 66,
+ NEG = 67,
+ NOT_EQUAL = 68,
+ PAD_V2 = 69,
+ POW = 70,
+ PRELU = 71,
+ QUANTIZE = 72,
+ QUANTIZED_16BIT_LSTM = 73,
+ RANDOM_MULTINOMIAL = 74,
+ REDUCE_ALL = 75,
+ REDUCE_ANY = 76,
+ REDUCE_MAX = 77,
+ REDUCE_MIN = 78,
+ REDUCE_PROD = 79,
+ REDUCE_SUM = 80,
+ ROI_ALIGN = 81,
+ ROI_POOLING = 82,
+ RSQRT = 83,
+ SELECT = 84,
+ SIN = 85,
+ SLICE = 86,
+ SPLIT = 87,
+ SQRT = 88,
+ TILE = 89,
+ TOPK_V2 = 90,
+ TRANSPOSE_CONV_2D = 91,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 93,
+ RESIZE_NEAREST_NEIGHBOR = 94,
+ QUANTIZED_LSTM = 95,
+ IF = 96,
+ WHILE = 97,
+ ELU = 98,
+ HARD_SWISH = 99,
+ FILL = 100,
+ RANK = 101,
+ BATCH_MATMUL = 102,
+ PACK = 103,
+ MIRROR_PAD = 104,
+ REVERSE = 105,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.aidl
new file mode 100644
index 0000000..f733505
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable OutputShape {
+ int[] dimensions;
+ boolean isSufficient;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.aidl
new file mode 100644
index 0000000..04910f5
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable PerformanceInfo {
+ float execTime;
+ float powerUsage;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl
new file mode 100644
index 0000000..8f35709
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum Priority {
+ LOW = 0,
+ MEDIUM = 1,
+ HIGH = 2,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl
new file mode 100644
index 0000000..39ec7a9
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Request {
+ android.hardware.neuralnetworks.RequestArgument[] inputs;
+ android.hardware.neuralnetworks.RequestArgument[] outputs;
+ android.hardware.neuralnetworks.RequestMemoryPool[] pools;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl
new file mode 100644
index 0000000..e3541c0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable RequestArgument {
+ boolean hasNoValue;
+ android.hardware.neuralnetworks.DataLocation location;
+ int[] dimensions;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.aidl
new file mode 100644
index 0000000..312f581
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+union RequestMemoryPool {
+ android.hardware.neuralnetworks.Memory pool;
+ int token;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.aidl
new file mode 100644
index 0000000..b7d4451
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Subgraph {
+ android.hardware.neuralnetworks.Operand[] operands;
+ android.hardware.neuralnetworks.Operation[] operations;
+ int[] inputIndexes;
+ int[] outputIndexes;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
new file mode 100644
index 0000000..02d68f9
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable SymmPerChannelQuantParams {
+ float[] scales;
+ int channelDim;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.aidl
new file mode 100644
index 0000000..bcc83cf
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable Timing {
+ long timeOnDeviceNs;
+ long timeInDriverNs;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
new file mode 100644
index 0000000..cb85743
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExecutionConfig {
+ boolean measureTiming;
+ long loopTimeoutDurationNs;
+ android.hardware.neuralnetworks.TokenValuePair[] executionHints;
+ android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
index eb3d0b0..461fdfa 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
@@ -36,4 +36,5 @@
interface IBurst {
android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
void releaseMemoryResource(in long memoryIdentifierToken);
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronouslyWithConfig(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs);
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
index c9c67f2..c0fba47 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
@@ -43,6 +43,7 @@
String getVersionString();
void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+ void prepareModelWithConfig(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.PrepareModelConfig config, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
const int MAX_NUMBER_OF_CACHE_FILES = 32;
const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15;
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
new file mode 100644
index 0000000..ab5275e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IExecution {
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in long deadlineNs);
+ android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in ParcelFileDescriptor[] waitFor, in long deadlineNs, in long durationNs);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
index fccb5dc..fb0c372 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -37,6 +37,9 @@
android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs);
android.hardware.neuralnetworks.IBurst configureExecutionBurst();
+ android.hardware.neuralnetworks.IExecution createReusableExecution(in android.hardware.neuralnetworks.Request request, in android.hardware.neuralnetworks.ExecutionConfig config);
+ android.hardware.neuralnetworks.ExecutionResult executeSynchronouslyWithConfig(in android.hardware.neuralnetworks.Request request, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs);
+ android.hardware.neuralnetworks.FencedExecutionResult executeFencedWithConfig(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs, in long durationNs);
const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
new file mode 100644
index 0000000..1f44ba7
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable PrepareModelConfig {
+ android.hardware.neuralnetworks.ExecutionPreference preference;
+ android.hardware.neuralnetworks.Priority priority;
+ long deadlineNs;
+ ParcelFileDescriptor[] modelCache;
+ ParcelFileDescriptor[] dataCache;
+ byte[32] cacheToken;
+ android.hardware.neuralnetworks.TokenValuePair[] compilationHints;
+ android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+ const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
new file mode 100644
index 0000000..e477d6e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable TokenValuePair {
+ int token;
+ byte[] value;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl
new file mode 100644
index 0000000..00f1e11
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExtensionNameAndPrefix;
+import android.hardware.neuralnetworks.TokenValuePair;
+
+/**
+ * A type that is used to represent all configuration related to
+ * an Execution.
+ */
+@VintfStability
+parcelable ExecutionConfig {
+ /**
+ * Specifies whether or not to measure duration of the execution.
+ * For {@link IPreparedModel::executeSynchronouslyWithConfig}, the duration runs from the time
+ * the driver sees the corresponding call to the execute function to the time the driver returns
+ * from the function. For {@link IPreparedModel::executeFencedWithConfig}, please refer to
+ * {@link IPreparedModelCallback} for details.
+ */
+ boolean measureTiming;
+ /**
+ * The maximum amount of time in nanoseconds that should be spent
+ * executing a {@link OperationType::WHILE} operation. If a loop
+ * condition model does not output false within this duration,
+ * the execution must be aborted. If -1 is provided, the maximum
+ * amount of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}.
+ * Other negative values are invalid. When provided, the duration
+ * must not exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+ */
+ long loopTimeoutDurationNs;
+ /**
+ * A vector of token / value pairs represent vendor specific
+ * execution hints or metadata. The provided TokenValuePairs must not
+ * contain the same token twice. The driver must validate the
+ * data and ignore invalid hints. It is up to the driver to
+ * decide whether to respect the provided hints or not.
+ */
+ TokenValuePair[] executionHints;
+ /**
+ * The mapping between extension names and prefixes of token values.
+ * The driver must ignore the corresponding execution hint, if
+ * the extension is not supported.
+ */
+ ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
index 20109bd..9f70a53 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
@@ -20,6 +20,10 @@
/**
* Information about an extension.
+ *
+ * The extension can provide zero or more operation types (which are not enumerated), zero or more
+ * operand types (which are enumerated in {@link Extension::operandTypes}, and compilation and
+ * execution hints (which are not enumerated).
*/
@VintfStability
parcelable Extension {
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
index 29be93f..6c296e0 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
@@ -17,7 +17,8 @@
package android.hardware.neuralnetworks;
/**
- * The mapping between extension names and prefixes of operand and operation type values.
+ * The mapping between extension names and prefixes of values like operand and operation type, and
+ * token in {@link TokenValuePair}.
*
* An operand or operation whose numeric type value is above {@link IDevice::OPERAND_TYPE_BASE_MAX}
* or {@link IDevice::OPERATION_TYPE_BASE_MAX} respectively should be interpreted as an extension
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
index decdc48..a05a7fb 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
@@ -17,6 +17,7 @@
package android.hardware.neuralnetworks;
import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionConfig;
import android.hardware.neuralnetworks.ExecutionResult;
import android.hardware.neuralnetworks.Request;
@@ -68,6 +69,8 @@
*
* Only a single execution on a given burst object may be active at any time.
*
+ * Also see {@link IBurst::executeSynchronouslyWithConfig}.
+ *
* @param request The input and output information on which the prepared model is to be
* executed.
* @param memoryIdentifierTokens A list of tokens where each token is a non-negative number
@@ -78,10 +81,10 @@
* runs from the time the driver sees the call to the executeSynchronously
* function to the time the driver returns from the function.
* @param deadlineNs The time by which the execution is expected to complete. The time is
- * measured in nanoseconds since epoch of the steady clock (as from
- * std::chrono::steady_clock). If the execution cannot be finished by the
- * deadline, the execution may be aborted. Passing -1 means the deadline is
- * omitted. Other negative values are invalid.
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
* @param loopTimeoutDurationNs The maximum amount of time in nanoseconds that should be spent
* executing a {@link OperationType::WHILE} operation. If a loop
* condition model does not output false within this duration, the
@@ -117,4 +120,13 @@
* - INVALID_ARGUMENT if one of the input arguments is invalid
*/
void releaseMemoryResource(in long memoryIdentifierToken);
+
+ /**
+ * For detailed specification, please refer to {@link IBurst::executeSynchronously}. The
+ * difference between the two methods is that executeSynchronouslyWithConfig takes {@link
+ * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+ * more configuration parameters than are passed to executeSynchronously.
+ */
+ ExecutionResult executeSynchronouslyWithConfig(in Request request,
+ in long[] memoryIdentifierTokens, in ExecutionConfig config, in long deadlineNs);
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
index 72e2623..7808fc2 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
@@ -28,6 +28,7 @@
import android.hardware.neuralnetworks.IPreparedModelParcel;
import android.hardware.neuralnetworks.Model;
import android.hardware.neuralnetworks.NumberOfCacheFiles;
+import android.hardware.neuralnetworks.PrepareModelConfig;
import android.hardware.neuralnetworks.Priority;
/**
@@ -38,7 +39,7 @@
/**
* The byte size of the cache token.
*/
- const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+ const int BYTE_SIZE_OF_CACHE_TOKEN = PrepareModelConfig.BYTE_SIZE_OF_CACHE_TOKEN;
/**
* The maximum number of files for each type of cache in compilation caching.
*/
@@ -148,7 +149,7 @@
*
* If the device reports that caching is not supported, the user may avoid calling
* IDevice::prepareModelFromCache or providing cache file descriptors to
- * IDevice::prepareModel.
+ * IDevice::prepareModel or IDevice::prepareModelWithConfig.
*
* @return NumberOfCacheFiles structure indicating how many files for model and data cache the
* driver needs to cache a single prepared model. It must be less than or equal to
@@ -302,6 +303,8 @@
*
* Multiple threads may call prepareModel on the same model concurrently.
*
+ * Also see {@link IDevice::prepareModelWithConfig}.
+ *
* @param model The model to be prepared for execution.
* @param preference Indicates the intended execution behavior of a prepared model.
* @param priority The priority of the prepared model relative to other prepared models owned by
@@ -403,17 +406,17 @@
* @param modelCache A vector of file descriptors for the security-sensitive cache. The length
* of the vector must match the numModelCache returned from
* getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
- * the same order as with prepareModel.
+ * the same order as with prepareModel or prepareModelWithConfig.
* @param dataCache A vector of file descriptors for the constants' cache. The length of the
* vector must match the numDataCache returned from
* getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
- * the same order as with prepareModel.
+ * the same order as with prepareModel or prepareModelWithConfig.
* @param token A caching token of length BYTE_SIZE_OF_CACHE_TOKEN identifying the prepared
* model. It is the same token provided when saving the cache files with
- * prepareModel. Tokens should be chosen to have a low rate of collision for a
- * particular application. The driver cannot detect a collision; a collision will
- * result in a failed execution or in a successful execution that produces
- * incorrect output values.
+ * prepareModel or prepareModelWithConfig. Tokens should be chosen to have a low
+ * rate of collision for a particular application. The driver cannot detect a
+ * collision; a collision will result in a failed execution or in a successful
+ * execution that produces incorrect output values.
* @param callback A callback object used to return the error status of preparing the model for
* execution and the prepared model if successful, nullptr otherwise. The
* callback object's notify function must be called exactly once, even if the
@@ -429,4 +432,28 @@
void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache,
in ParcelFileDescriptor[] dataCache, in byte[] token,
in IPreparedModelCallback callback);
+
+ /**
+ * For detailed specification, please refer to {@link IDevice::prepareModel}. The only
+ * difference between the two methods is that prepareModelWithConfig takes {@link
+ * PrepareModelConfig} instead of standalone configuration parameters, which allows vendor
+ * specific compilation metadata to be passed.
+ *
+ * @param model The model to be prepared for execution.
+ * @param config Configuration parameters to prepare the model.
+ * @param callback A callback object used to return the error status of preparing the model for
+ * execution and the prepared model if successful, nullptr otherwise. The
+ * callback object's notify function must be called exactly once, even if the
+ * model could not be prepared.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments related to preparing the model is
+ * invalid
+ * - MISSED_DEADLINE_* if the preparation is aborted because the model cannot be prepared by
+ * the deadline
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ void prepareModelWithConfig(
+ in Model model, in PrepareModelConfig config, in IPreparedModelCallback callback);
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl
new file mode 100644
index 0000000..3cb9c1a
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExecutionResult;
+import android.hardware.neuralnetworks.FencedExecutionResult;
+
+/**
+ * IExecution represents a reusable execution object with request and most other execution
+ * properties fixed. It is used to launch executions.
+ *
+ * At most one execution may occur on a reusable execution object at any given time, either by
+ * means of executeSynchronously or executeFenced.
+ *
+ * An IExecution object is used to control a set of executions on the same prepared model with
+ * the same request and properties. IExecution objects enable some optimizations:
+ * (1) An IExecution object can preserve resources between executions. For example, a driver can
+ * map a memory object when the IExecution object is created and cache the mapping for reuse in
+ * subsequent executions. Any cached resource can be released when the IExecution object is
+ * destroyed.
+ * (2) Because an IExecution object may be used for at most one execution at a time, any transient
+ * execution resources such as intermediate tensors can be allocated once when the IExecution
+ * object is created and freed when the IExecution object is destroyed.
+ * (3) An IExecution object is created for a fixed request. This enables the implementation to apply
+ * request-specific optimizations. For example, an implementation can avoid request validation
+ * and conversions when the IExecution object is reused. An implementation may also choose to
+ * specialize the dynamic tensor shapes in the IExecution object according to the request.
+ */
+@VintfStability
+interface IExecution {
+ /**
+ * Performs a synchronous execution on the reusable execution object.
+ *
+ * The execution is performed synchronously with respect to the caller. executeSynchronously
+ * must verify the inputs to the function are correct, and the usages of memory pools allocated
+ * by IDevice::allocate are valid. If there is an error, executeSynchronously must immediately
+ * return a service specific exception with the appropriate ErrorStatus value. If the inputs to
+ * the function are valid and there is no error, executeSynchronously must perform the
+ * execution, and must not return until the execution is complete.
+ *
+ * The caller must not change the content of any data object referenced by the 'request'
+ * provided in {@link IPreparedModel::createReusableExecution} (described by the
+ * {@link DataLocation} of a {@link RequestArgument}) until executeSynchronously returns.
+ * executeSynchronously must not change the content of any of the data objects corresponding to
+ * 'request' inputs.
+ *
+ * If the execution object was configured from a prepared model wherein all tensor operands have
+ * fully specified dimensions, and the inputs to the function are valid, and at execution time
+ * every operation's input operands have legal values, then the execution should complete
+ * successfully: there must be no failure unless the device itself is in a bad state.
+ *
+ * If the execution object was created with measureTiming being true and the execution is
+ * successful, the driver may report the timing information in the returning
+ * {@link ExecutionResult}. The duration runs from the time the driver sees the call to the time
+ * the driver returns from the function.
+ *
+ * executeSynchronously may be called with an optional deadline. If the execution is not able to
+ * be completed before the provided deadline, the execution may be aborted, and either
+ * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+ * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+ * sent the same way as other errors, described above.
+ *
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
+ * @return ExecutionResult parcelable, containing the status of the execution, output shapes
+ * and timing information.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid
+ * - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+ * deadline
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ ExecutionResult executeSynchronously(in long deadlineNs);
+
+ /**
+ * Launch a fenced asynchronous execution on the reusable execution object.
+ *
+ * The execution is performed asynchronously with respect to the caller. executeFenced must
+ * verify the inputs to the function are correct, and the usages of memory pools allocated by
+ * IDevice::allocate are valid. If there is an error, executeFenced must immediately return a
+ * service specific exception with the corresponding ErrorStatus. If the inputs to the function
+ * are valid and there is no error, executeFenced must dispatch an asynchronous task to perform
+ * the execution in the background, and immediately return a {@link FencedExecutionResult}
+ * containing two fields: a callback (which can be used by the client to query the duration and
+ * runtime error status) and a sync fence (which will be signaled once the execution is
+ * completed). If the task has finished before the call returns, syncFence file descriptor may
+ * be set to -1. The execution must wait for all the sync fences (if any) in waitFor to be
+ * signaled before starting the actual execution.
+ *
+ * When the asynchronous task has finished its execution, it must immediately signal the
+ * syncFence returned from the executeFenced call. After the syncFence is signaled, the task
+ * must not modify the content of any data object referenced by the 'request' provided in
+ * IPreparedModel::createReusableExecution (described by the {@link DataLocation} of a
+ * {@link RequestArgument}).
+ *
+ * executeFenced may be called with an optional deadline and an optional duration. If the
+ * execution is not able to be completed before the provided deadline or within the timeout
+ * duration (measured from when all sync fences in waitFor are signaled), whichever comes
+ * earlier, the execution may be aborted, and either
+ * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+ * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+ * sent the same way as other errors, described above.
+ *
+ * If any of the sync fences in waitFor changes to error status after the executeFenced call
+ * succeeds, or the execution is aborted because it cannot finish before the deadline has been
+ * reached or the duration has elapsed, the driver must immediately set the returned syncFence
+ * to error status.
+ *
+ * @param waitFor A vector of sync fence file descriptors. Execution must not start until all
+ * sync fences have been signaled.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
+ * @param durationNs The length of time in nanoseconds within which the execution is expected
+ * to complete after all sync fences in waitFor are signaled. If the
+ * execution cannot be finished within the duration, the execution may be
+ * aborted. Passing -1 means the duration is omitted. Other negative values
+ * are invalid.
+ * @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
+ * sync fence.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid, including fences in error
+ * states.
+ * - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+ * deadline
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ FencedExecutionResult executeFenced(
+ in ParcelFileDescriptor[] waitFor, in long deadlineNs, in long durationNs);
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index 956b626..f752750 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -18,9 +18,11 @@
import android.hardware.common.NativeHandle;
import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionConfig;
import android.hardware.neuralnetworks.ExecutionResult;
import android.hardware.neuralnetworks.FencedExecutionResult;
import android.hardware.neuralnetworks.IBurst;
+import android.hardware.neuralnetworks.IExecution;
import android.hardware.neuralnetworks.Request;
/**
@@ -67,6 +69,8 @@
* Any number of calls to the execute* functions, in any combination, may be made concurrently,
* even on the same IPreparedModel object.
*
+ * Also see {@link IPreparedModel::executeSynchronouslyWithConfig}.
+ *
* @param request The input and output information on which the prepared model is to be
* executed.
* @param measure Specifies whether or not to measure duration of the execution. The duration
@@ -105,11 +109,12 @@
* IDevice::allocate are valid. If there is an error, executeFenced must immediately return a
* service specific exception with the corresponding ErrorStatus. If the inputs to the function
* are valid and there is no error, executeFenced must dispatch an asynchronous task to perform
- * the execution in the background, assign a sync fence that will be signaled once the execution
- * is completed and immediately return a callback that can be used by the client to query the
- * duration and runtime error status. If the task has finished before the call returns,
- * syncFence file descriptor may be set to -1. The execution must wait for all the sync fences
- * (if any) in waitFor to be signaled before starting the actual execution.
+ * the execution in the background, and immediately return a {@link FencedExecutionResult}
+ * containing two fields: a callback (which can be used by the client to query the duration and
+ * runtime error status) and a sync fence (which will be signaled once the execution is
+ * completed). If the task has finished before the call returns, syncFence file descriptor may
+ * be set to -1. The execution must wait for all the sync fences (if any) in waitFor to be
+ * signaled before starting the actual execution.
*
* When the asynchronous task has finished its execution, it must immediately signal the
* syncFence returned from the executeFenced call. After the syncFence is signaled, the task
@@ -132,6 +137,8 @@
* Any number of calls to the execute* functions, in any combination, may be made concurrently,
* even on the same IPreparedModel object.
*
+ * Also see {@link IPreparedModel::executeFencedWithConfig}.
+ *
* @param request The input and output information on which the prepared model is to be
* executed. The outputs in the request must have fully specified dimensions.
* @param waitFor A vector of sync fence file descriptors. Execution must not start until all
@@ -186,4 +193,100 @@
* - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
*/
IBurst configureExecutionBurst();
+
+ /**
+ * Create a reusable execution object to launch multiple executions with the same request and
+ * properties.
+ *
+ * createReusableExecution must verify the inputs to the function are correct, and the usages of
+ * memory pools allocated by IDevice::allocate are valid. If there is an error,
+ * createReusableExecution must immediately return a service specific exception with the
+ * appropriate ErrorStatus value. If the inputs to the function are valid and there is no error,
+ * createReusableExecution must construct a reusable execution.
+ *
+ * This method will be called when a client requests a reusable execution with consistent
+ * request and execution config. For single-time execution,
+ * {@link IPreparedModel::executeSynchronouslyWithConfig} or
+ * {@link IPreparedModel::executeFencedWithConfig} is preferred, because the overhead of
+ * setting up a reusable execution can be avoided.
+ *
+ * @param request The input and output information on which the prepared model is to be
+ * executed.
+ * @param config Specifies the execution configuration parameters.
+ * @return execution An IExecution object representing a reusable execution that has been
+ * specialized for a fixed request.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ IExecution createReusableExecution(in Request request, in ExecutionConfig config);
+
+ /**
+ * For detailed specification, please refer to {@link IPreparedModel::executeSynchronously}. The
+ * difference between the two methods is that executeSynchronouslyWithConfig takes {@link
+ * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+ * more configuration parameters than are passed to executeSynchronously.
+ *
+ * This method is preferred when a client requests a single-time synchronous execution.
+ * For reusable execution with consistent request and execution config,
+ * {@link IPreparedModel::createReusableExecution} must be called.
+ *
+ * @param request The input and output information on which the prepared model is to be
+ * executed.
+ * @param config Specifies the execution configuration parameters.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative valueggs are invalid.
+ * @return ExecutionResult parcelable, containing the status of the execution, output shapes and
+ * timing information.
+ * - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+ * deadline
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ ExecutionResult executeSynchronouslyWithConfig(
+ in Request request, in ExecutionConfig config, in long deadlineNs);
+
+ /**
+ * For detailed specification, please refer to {@link IPreparedModel::executeFenced}. The
+ * difference between the two methods is that executeFencedWithConfig takes {@link
+ * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+ * more configuration parameters than are passed to executeFenced.
+ *
+ * This method is preferred when a client requests a single-time fenced execution.
+ * For reusable execution with consistent request and execution config,
+ * {@link IPreparedModel::createReusableExecution} must be called.
+ *
+ * @param request The input and output information on which the prepared model is to be
+ * executed. The outputs in the request must have fully specified dimensions.
+ * @param waitFor A vector of sync fence file descriptors. Execution must not start until all
+ * sync fences have been signaled.
+ * @param config Specifies the execution configuration parameters.
+ * @param deadlineNs The time by which the execution is expected to complete. The time is
+ * measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+ * &ts) or ::android::base::boot_clock). If the execution cannot be finished
+ * by the deadline, the execution may be aborted. Passing -1 means the
+ * deadline is omitted. Other negative values are invalid.
+ * @param durationNs The length of time in nanoseconds within which the execution is expected to
+ * complete after all sync fences in waitFor are signaled. If the execution
+ * cannot be finished within the duration, the execution may be aborted.
+ * Passing -1 means the duration is omitted. Other negative values are
+ * invalid.
+ * @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
+ * sync fence.
+ * @throws ServiceSpecificException with one of the following ErrorStatus values:
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if there is an unspecified error
+ * - INVALID_ARGUMENT if one of the input arguments is invalid, including fences in error
+ * states.
+ * - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+ * deadline
+ * - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+ */
+ FencedExecutionResult executeFencedWithConfig(in Request request,
+ in ParcelFileDescriptor[] waitFor, in ExecutionConfig config, in long deadlineNs,
+ in long durationNs);
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
index aebe8d9..5f7810b 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
@@ -5331,6 +5331,18 @@
/**
* Pads a tensor with mirrored values.
*
+ * This operator specifies one of two padding modes: REFLECT or SYMMETRIC.
+ * In the case of REFLECT mode, the mirroring excludes the border element
+ * on the padding side.
+ * In the case of SYMMETRIC mode, the mirroring includes the border element
+ * on the padding side.
+ *
+ * For example, if the input is the 1-D tensor `[1, 2, 3]` and the padding
+ * is `[0, 2]` (i.e., pad no elements before the first (and only) dimension,
+ * and two elements after the first (and only) dimension), then:
+ * - REFLECT mode produces the output `[1, 2, 3, 2, 1]`
+ * - SYMMETRIC mode produces the output `[1, 2, 3, 3, 2]`
+ *
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT16}
* * {@link OperandType::TENSOR_FLOAT32}
@@ -5349,6 +5361,11 @@
* front of dimension i.
* padding[i, 1] specifies the number of elements to be padded after the
* end of dimension i.
+ * Each padding value must be nonnegative.
+ * In the case of REFLECT mode, each padding value must be less than the
+ * corresponding dimension.
+ * In the case of SYMMETRIC mode, each padding value must be less than or
+ * equal to the corresponding dimension.
* * 2: An {@link OperandType::INT32} scalar, specifying the mode.
* Options are 0:REFLECT and 1:SYMMETRIC.
*
@@ -5385,7 +5402,7 @@
* must be in the range [0, n).
*
* Outputs:
- * * 0: The reversed tensor.
+ * * 0: The reversed tensor of the same shape as the input tensor.
* For {@link OperandType::TENSOR_QUANT8_ASYMM} and
* {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensors,
* the scales and zeroPoint must be the same as input0.
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl
new file mode 100644
index 0000000..55bd291
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExecutionPreference;
+import android.hardware.neuralnetworks.ExtensionNameAndPrefix;
+import android.hardware.neuralnetworks.Priority;
+import android.hardware.neuralnetworks.TokenValuePair;
+
+/**
+ * A type that is used to represent all configuration needed to
+ * prepare a model.
+ */
+@VintfStability
+parcelable PrepareModelConfig {
+ /**
+ * The byte size of the cache token.
+ */
+ const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+
+ /**
+ * Indicates the intended execution behavior of a prepared model.
+ */
+ ExecutionPreference preference;
+ /**
+ * The priority of the prepared model relative to other prepared
+ * models owned by the client.
+ */
+ Priority priority;
+ /**
+ * The time by which the model is expected to be prepared. The
+ * time is measured in nanoseconds since boot (as from
+ * clock_gettime(CLOCK_BOOTTIME, &ts) or
+ * ::android::base::boot_clock). If the model cannot be prepared
+ * by the deadline, the preparation may be aborted. Passing -1
+ * means the deadline is omitted. Other negative values are
+ * invalid.
+ */
+ long deadlineNs;
+ /**
+ * A vector of file descriptors for the security-sensitive cache.
+ * The length of the vector must either be 0 indicating that
+ * caching information is not provided, or match the
+ * numModelCache returned from IDevice::getNumberOfCacheFilesNeeded. The
+ * cache file descriptors will be provided in the same order when
+ * retrieving the preparedModel from cache files with
+ * IDevice::prepareModelFromCache.
+ */
+ ParcelFileDescriptor[] modelCache;
+ /**
+ * A vector of file descriptors for the constants' cache. The
+ * length of the vector must either be 0 indicating that caching
+ * information is not provided, or match the numDataCache
+ * returned from IDevice::getNumberOfCacheFilesNeeded. The cache file
+ * descriptors will be provided in the same order when retrieving
+ * the preparedModel from cache files with IDevice::prepareModelFromCache.
+ */
+ ParcelFileDescriptor[] dataCache;
+ /**
+ * A caching token of length BYTE_SIZE_OF_CACHE_TOKEN identifying
+ * the prepared model. The same token will be provided when
+ * retrieving the prepared model from the cache files with
+ * IDevice::prepareModelFromCache. Tokens should be chosen to have a low
+ * rate of collision for a particular application. The driver
+ * cannot detect a collision; a collision will result in a failed
+ * execution or in a successful execution that produces incorrect
+ * output values. If both modelCache and dataCache are empty
+ * indicating that caching information is not provided, this
+ * token must be ignored.
+ */
+ byte[BYTE_SIZE_OF_CACHE_TOKEN] cacheToken;
+ /**
+ * A vector of token / value pairs represent vendor specific
+ * compilation hints or metadata. The provided TokenValuePairs must not
+ * contain the same token twice. The driver must validate the
+ * data and ignore invalid hints. It is up to the driver to
+ * decide whether to respect the provided hints or not.
+ */
+ TokenValuePair[] compilationHints;
+ /**
+ * The mapping between extension names and prefixes of token values.
+ * The driver must ignore the corresponding compilation hint, if
+ * the extension is not supported.
+ */
+ ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl
new file mode 100644
index 0000000..ec665b4
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+
+/**
+ * A type that is used to represent a token / byte array data pair.
+ */
+@VintfStability
+parcelable TokenValuePair {
+ /**
+ * A 32bit integer token. The token is created by combining the
+ * extension prefix and enum defined within the extension.
+ * The low {@link IDevice::EXTENSION_TYPE_LOW_BITS_TYPE} bits of the value
+ * correspond to the hint within the extension and the high
+ * {@link IDevice::EXTENSION_TYPE_HIGH_BITS_PREFIX} bits encode the "prefix", which maps
+ * uniquely to the extension name. The sign bit is always 0.
+ *
+ * For example, if a token value is 0x7AAA000B and the corresponding
+ * {@link ExtensionNameAndPrefix} contains an entry with prefix=0x7AAA and
+ * name="vendor.test.test_extension", then the token should be interpreted as the hint
+ * 0x000B of the extension named vendor.test.test_extension.
+ */
+ int token;
+ /**
+ * A byte array containing the raw data.
+ */
+ byte[] value;
+}
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 37ad6d6..2b7b787 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -26,7 +26,14 @@
cc_defaults {
name: "neuralnetworks_utils_hal_aidl_defaults",
defaults: ["neuralnetworks_utils_defaults"],
- srcs: ["src/*"],
+ srcs: [
+ // AIDL utils that a driver may depend on.
+ "src/BufferTracker.cpp",
+ "src/Conversions.cpp",
+ "src/HalUtils.cpp",
+ "src/Utils.cpp",
+ "src/ValidateHal.cpp",
+ ],
local_include_dirs: ["include/nnapi/hal/aidl/"],
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
@@ -47,6 +54,7 @@
},
}
+// Deprecated. Remove once all modules depending on this are migrated away.
cc_library_static {
name: "neuralnetworks_utils_hal_aidl_v1",
defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
@@ -56,19 +64,25 @@
}
cc_library_static {
- name: "neuralnetworks_utils_hal_aidl_v2",
- defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
- shared_libs: [
- "android.hardware.neuralnetworks-V2-ndk",
- ],
-}
-
-cc_library_static {
name: "neuralnetworks_utils_hal_aidl",
defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
- shared_libs: [
- "android.hardware.neuralnetworks-V3-ndk",
+ srcs: [
+ // Additional AIDL utils for the runtime.
+ "src/Assertions.cpp",
+ "src/Buffer.cpp",
+ "src/Burst.cpp",
+ "src/Callbacks.cpp",
+ "src/Device.cpp",
+ "src/Execution.cpp",
+ "src/InvalidDevice.cpp",
+ "src/PreparedModel.cpp",
+ "src/ProtectCallback.cpp",
+ "src/Service.cpp",
],
+ shared_libs: [
+ "android.hardware.neuralnetworks-V4-ndk",
+ ],
+ cflags: ["-DNN_AIDL_V4_OR_ABOVE"],
}
// A cc_defaults that includes the latest non-experimental AIDL utilities and other AIDL libraries
@@ -79,9 +93,10 @@
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.graphics.common-V2-ndk",
- "android.hardware.neuralnetworks-V3-ndk",
+ "android.hardware.neuralnetworks-V4-ndk",
"neuralnetworks_utils_hal_aidl",
],
+ cflags: ["-DNN_AIDL_V4_OR_ABOVE"],
}
cc_test {
@@ -90,38 +105,28 @@
"neuralnetworks_use_latest_utils_hal_aidl",
"neuralnetworks_utils_defaults",
],
+ tidy_timeout_srcs: [
+ "test/DeviceTest.cpp",
+ "test/PreparedModelTest.cpp",
+ ],
srcs: [
"test/*.cpp",
],
static_libs: [
"libaidlcommonsupport",
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
],
shared_libs: [
- "android.hidl.allocator@1.0",
"libbase",
"libbinder_ndk",
"libcutils",
- "libhidlbase",
- "libhidlmemory",
- "liblog",
- "libutils",
],
target: {
android: {
shared_libs: ["libnativewindow"],
},
- host: {
- cflags: [
- "-D__INTRODUCED_IN(x)=",
- "-D__assert(a,b,c)=",
- // We want all the APIs to be available on the host.
- "-D__ANDROID_API__=10000",
- ],
- },
},
cflags: [
/* GMOCK defines functions for printing all MOCK_DEVICE arguments and
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
index 0cc78d4..f2e6e75 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
@@ -86,10 +86,12 @@
GUARDED_BY(mMutex);
};
+ // featureLevel is for testing purposes.
static nn::GeneralResult<std::shared_ptr<const Burst>> create(
- std::shared_ptr<aidl_hal::IBurst> burst);
+ std::shared_ptr<aidl_hal::IBurst> burst, nn::Version featureLevel);
- Burst(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IBurst> burst);
+ Burst(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IBurst> burst,
+ nn::Version featureLevel);
// See IBurst::cacheMemory for information.
OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
@@ -97,23 +99,29 @@
// See IBurst::execute for information.
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
// See IBurst::createReusableExecution for information.
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
const aidl_hal::Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
bool measure, int64_t deadline, int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
const hal::utils::RequestRelocation& relocation) const;
private:
mutable std::atomic_flag mExecutionInFlight = ATOMIC_FLAG_INIT;
const std::shared_ptr<aidl_hal::IBurst> kBurst;
const std::shared_ptr<MemoryCache> kMemoryCache;
+ const nn::Version kFeatureLevel;
};
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
index 168264b..960be2b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
@@ -36,6 +36,8 @@
public:
using Data = nn::GeneralResult<nn::SharedPreparedModel>;
+ PreparedModelCallback(nn::Version featureLevel) : kFeatureLevel(featureLevel) {}
+
ndk::ScopedAStatus notify(ErrorStatus status,
const std::shared_ptr<IPreparedModel>& preparedModel) override;
@@ -44,6 +46,7 @@
Data get();
private:
+ const nn::Version kFeatureLevel;
hal::utils::TransferValue<Data> mData;
};
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
index 78433a7..71a28ef 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
@@ -27,6 +27,7 @@
#include <aidl/android/hardware/neuralnetworks/Extension.h>
#include <aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.h>
#include <aidl/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
#include <aidl/android/hardware/neuralnetworks/Memory.h>
#include <aidl/android/hardware/neuralnetworks/Model.h>
#include <aidl/android/hardware/neuralnetworks/Operand.h>
@@ -46,6 +47,10 @@
#include <aidl/android/hardware/neuralnetworks/SymmPerChannelQuantParams.h>
#include <aidl/android/hardware/neuralnetworks/Timing.h>
+#ifdef NN_AIDL_V4_OR_ABOVE
+#include <aidl/android/hardware/neuralnetworks/TokenValuePair.h>
+#endif // NN_AIDL_V4_OR_ABOVE
+
#include <android/binder_auto_utils.h>
#include <nnapi/Result.h>
#include <nnapi/Types.h>
@@ -74,7 +79,7 @@
const aidl_hal::SymmPerChannelQuantParams& symmPerChannelQuantParams);
GeneralResult<Operation> unvalidatedConvert(const aidl_hal::Operation& operation);
GeneralResult<Model> unvalidatedConvert(const aidl_hal::Model& model);
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix);
GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues);
GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph);
@@ -97,6 +102,10 @@
const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation);
GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle);
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<TokenValuePair> unvalidatedConvert(const aidl_hal::TokenValuePair& tokenValuePair);
+#endif // NN_AIDL_V4_OR_ABOVE
+
GeneralResult<std::vector<Operation>> unvalidatedConvert(
const std::vector<aidl_hal::Operation>& operations);
@@ -112,11 +121,23 @@
GeneralResult<Request> convert(const aidl_hal::Request& request);
GeneralResult<Timing> convert(const aidl_hal::Timing& timing);
GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle);
+GeneralResult<BufferDesc> convert(const aidl_hal::BufferDesc& bufferDesc);
GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension);
GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories);
+GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+ const std::vector<aidl_hal::ExtensionNameAndPrefix>& extensionNameAndPrefix);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<std::vector<TokenValuePair>> convert(
+ const std::vector<aidl_hal::TokenValuePair>& metaData);
+#endif // NN_AIDL_V4_OR_ABOVE
+
GeneralResult<std::vector<OutputShape>> convert(
const std::vector<aidl_hal::OutputShape>& outputShapes);
+GeneralResult<std::vector<SharedHandle>> convert(
+ const std::vector<ndk::ScopedFileDescriptor>& handles);
+GeneralResult<std::vector<BufferRole>> convert(const std::vector<aidl_hal::BufferRole>& roles);
GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec);
@@ -129,6 +150,7 @@
nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken);
nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc);
nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole);
+nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType);
nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming);
nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory);
nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape);
@@ -147,21 +169,27 @@
nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(
const nn::Model::OperandValues& operandValues);
nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
- const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix);
+ const nn::ExtensionNameAndPrefix& extensionNameToPrefix);
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority);
nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request);
nn::GeneralResult<RequestArgument> unvalidatedConvert(const nn::Request::Argument& requestArgument);
nn::GeneralResult<RequestMemoryPool> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool);
nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing);
-nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration);
nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration);
nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalTimePoint& optionalTimePoint);
nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SyncFence& syncFence);
nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle);
+nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<TokenValuePair> unvalidatedConvert(const nn::TokenValuePair& tokenValuePair);
+#endif // NN_AIDL_V4_OR_ABOVE
nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken);
nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc);
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType);
nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming);
nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory);
nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
@@ -172,6 +200,8 @@
nn::GeneralResult<Timing> convert(const nn::Timing& timing);
nn::GeneralResult<int64_t> convert(const nn::OptionalDuration& optionalDuration);
nn::GeneralResult<int64_t> convert(const nn::OptionalTimePoint& optionalTimePoint);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Extension> convert(const nn::Extension& extension);
nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
nn::GeneralResult<std::vector<OutputShape>> convert(
@@ -180,8 +210,17 @@
const std::vector<nn::SharedHandle>& handles);
nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
const std::vector<nn::SyncFence>& syncFences);
+nn::GeneralResult<std::vector<Extension>> convert(const std::vector<nn::Extension>& extensions);
+nn::GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<std::vector<TokenValuePair>> convert(
+ const std::vector<nn::TokenValuePair>& metaData);
+#endif // NN_AIDL_V4_OR_ABOVE
nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec);
+std::vector<uint8_t> toVec(const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN>& token);
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index d558f66..615c6de 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -42,6 +42,7 @@
struct PrivateConstructorTag {};
public:
+ // featureLevel is for testing purposes.
static nn::GeneralResult<std::shared_ptr<const Device>> create(
std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel);
@@ -67,8 +68,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
index a77ea98..14802b9 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+
#include <nnapi/IExecution.h>
#include <nnapi/Result.h>
#include <nnapi/Types.h>
@@ -33,17 +35,22 @@
namespace aidl::android::hardware::neuralnetworks::utils {
-class Execution final : public nn::IExecution, public std::enable_shared_from_this<Execution> {
+// A reusable execution implementation with a cached Request, internally it is still passing the
+// request to the driver in every computation.
+class ExecutionWithCachedRequest final
+ : public nn::IExecution,
+ public std::enable_shared_from_this<ExecutionWithCachedRequest> {
struct PrivateConstructorTag {};
public:
- static nn::GeneralResult<std::shared_ptr<const Execution>> create(
+ static nn::GeneralResult<std::shared_ptr<const ExecutionWithCachedRequest>> create(
std::shared_ptr<const PreparedModel> preparedModel, Request request,
hal::utils::RequestRelocation relocation, bool measure, int64_t loopTimeoutDuration);
- Execution(PrivateConstructorTag tag, std::shared_ptr<const PreparedModel> preparedModel,
- Request request, hal::utils::RequestRelocation relocation, bool measure,
- int64_t loopTimeoutDuration);
+ ExecutionWithCachedRequest(PrivateConstructorTag tag,
+ std::shared_ptr<const PreparedModel> preparedModel, Request request,
+ hal::utils::RequestRelocation relocation, bool measure,
+ int64_t loopTimeoutDuration);
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
const nn::OptionalTimePoint& deadline) const override;
@@ -60,6 +67,30 @@
const int64_t kLoopTimeoutDuration;
};
+// A reusable execution implementation that is backed by an actual AIDL IExecution object.
+class Execution final : public nn::IExecution, public std::enable_shared_from_this<Execution> {
+ struct PrivateConstructorTag {};
+
+ public:
+ static nn::GeneralResult<std::shared_ptr<const Execution>> create(
+ std::shared_ptr<aidl_hal::IExecution> execution,
+ hal::utils::RequestRelocation relocation);
+
+ Execution(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IExecution> execution,
+ hal::utils::RequestRelocation relocation);
+
+ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
+ const nn::OptionalTimePoint& deadline) const override;
+
+ nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> computeFenced(
+ const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+
+ private:
+ const std::shared_ptr<aidl_hal::IExecution> kExecution;
+ const hal::utils::RequestRelocation kRelocation;
+};
+
} // namespace aidl::android::hardware::neuralnetworks::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
index 3fb443c..cacdc26 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
@@ -61,6 +61,13 @@
#include <aidl/android/hardware/neuralnetworks/SymmPerChannelQuantParams.h>
#include <aidl/android/hardware/neuralnetworks/Timing.h>
+#ifdef NN_AIDL_V4_OR_ABOVE
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionConfig.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/PrepareModelConfig.h>
+#endif // NN_AIDL_V4_OR_ABOVE
+
namespace android::nn {
namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
index e66507a..9375c1d 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
@@ -53,6 +53,9 @@
const std::vector<ndk::ScopedFileDescriptor>& dataCache,
const std::vector<uint8_t>& token,
const std::shared_ptr<IPreparedModelCallback>& callback) override;
+ ndk::ScopedAStatus prepareModelWithConfig(
+ const Model& model, const PrepareModelConfig& config,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
ndk::ScopedAStatus prepareModelFromCache(
int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
const std::vector<ndk::ScopedFileDescriptor>& dataCache,
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
index 4035764..cb6a85b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
@@ -40,26 +40,33 @@
struct PrivateConstructorTag {};
public:
+ // featureLevel is for testing purposes.
static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
- std::shared_ptr<aidl_hal::IPreparedModel> preparedModel);
+ std::shared_ptr<aidl_hal::IPreparedModel> preparedModel, nn::Version featureLevel);
PreparedModel(PrivateConstructorTag tag,
- std::shared_ptr<aidl_hal::IPreparedModel> preparedModel);
+ std::shared_ptr<aidl_hal::IPreparedModel> preparedModel,
+ nn::Version featureLevel);
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
@@ -67,6 +74,8 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
const Request& request, bool measure, int64_t deadline, int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
const hal::utils::RequestRelocation& relocation) const;
nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
@@ -74,10 +83,13 @@
const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measure,
int64_t deadline, int64_t loopTimeoutDuration,
int64_t timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
const hal::utils::RequestRelocation& relocation) const;
private:
const std::shared_ptr<aidl_hal::IPreparedModel> kPreparedModel;
+ const nn::Version kFeatureLevel;
};
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
index cb6ff4b..f229165 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
@@ -25,7 +25,8 @@
namespace aidl::android::hardware::neuralnetworks::utils {
-::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name);
+::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(
+ const std::string& name, ::android::nn::Version::Level maxFeatureLevelAllowed);
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
index a27487e..7ed5437 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
@@ -26,6 +26,8 @@
#include <nnapi/Types.h>
#include <nnapi/Validation.h>
+#include <type_traits>
+
namespace aidl::android::hardware::neuralnetworks::utils {
constexpr auto kDefaultPriority = Priority::MEDIUM;
@@ -38,6 +40,8 @@
return nn::kVersionFeatureLevel6;
case 3:
return nn::kVersionFeatureLevel7;
+ case 4:
+ return nn::kVersionFeatureLevel8;
default:
return std::nullopt;
}
@@ -78,6 +82,11 @@
return convert(NN_TRY(nn::convert(nonCanonicalObject)));
}
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+ return static_cast<std::underlying_type_t<Type>>(value);
+}
+
nn::GeneralResult<Memory> clone(const Memory& memory);
nn::GeneralResult<Request> clone(const Request& request);
nn::GeneralResult<RequestMemoryPool> clone(const RequestMemoryPool& requestPool);
diff --git a/neuralnetworks/aidl/utils/src/Burst.cpp b/neuralnetworks/aidl/utils/src/Burst.cpp
index fb00b26..6c7aa88 100644
--- a/neuralnetworks/aidl/utils/src/Burst.cpp
+++ b/neuralnetworks/aidl/utils/src/Burst.cpp
@@ -43,12 +43,16 @@
static nn::GeneralResult<std::shared_ptr<const BurstExecution>> create(
std::shared_ptr<const Burst> burst, Request request,
std::vector<int64_t> memoryIdentifierTokens, bool measure, int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
hal::utils::RequestRelocation relocation,
std::vector<Burst::OptionalCacheHold> cacheHolds);
BurstExecution(PrivateConstructorTag tag, std::shared_ptr<const Burst> burst, Request request,
std::vector<int64_t> memoryIdentifierTokens, bool measure,
- int64_t loopTimeoutDuration, hal::utils::RequestRelocation relocation,
+ int64_t loopTimeoutDuration, const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+ hal::utils::RequestRelocation relocation,
std::vector<Burst::OptionalCacheHold> cacheHolds);
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
@@ -64,6 +68,8 @@
const std::vector<int64_t> kMemoryIdentifierTokens;
const bool kMeasure;
const int64_t kLoopTimeoutDuration;
+ const std::vector<nn::TokenValuePair> kHints;
+ const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix;
const hal::utils::RequestRelocation kRelocation;
const std::vector<Burst::OptionalCacheHold> kCacheHolds;
};
@@ -149,17 +155,20 @@
}
nn::GeneralResult<std::shared_ptr<const Burst>> Burst::create(
- std::shared_ptr<aidl_hal::IBurst> burst) {
+ std::shared_ptr<aidl_hal::IBurst> burst, nn::Version featureLevel) {
if (burst == nullptr) {
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
<< "aidl_hal::utils::Burst::create must have non-null burst";
}
- return std::make_shared<const Burst>(PrivateConstructorTag{}, std::move(burst));
+ return std::make_shared<const Burst>(PrivateConstructorTag{}, std::move(burst), featureLevel);
}
-Burst::Burst(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IBurst> burst)
- : kBurst(std::move(burst)), kMemoryCache(std::make_shared<MemoryCache>(kBurst)) {
+Burst::Burst(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IBurst> burst,
+ nn::Version featureLevel)
+ : kBurst(std::move(burst)),
+ kMemoryCache(std::make_shared<MemoryCache>(kBurst)),
+ kFeatureLevel(featureLevel) {
CHECK(kBurst != nullptr);
}
@@ -170,8 +179,9 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -200,14 +210,14 @@
memoryIdentifierTokens.push_back(-1);
}
CHECK_EQ(requestInShared.pools.size(), memoryIdentifierTokens.size());
-
return executeInternal(aidlRequest, memoryIdentifierTokens, aidlMeasure, aidlDeadline,
- aidlLoopTimeoutDuration, relocation);
+ aidlLoopTimeoutDuration, hints, extensionNameToPrefix, relocation);
}
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::executeInternal(
const Request& request, const std::vector<int64_t>& memoryIdentifierTokens, bool measure,
- int64_t deadline, int64_t loopTimeoutDuration,
+ int64_t deadline, int64_t loopTimeoutDuration, const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
const hal::utils::RequestRelocation& relocation) const {
// Ensure that at most one execution is in flight at any given time.
const bool alreadyInFlight = mExecutionInFlight.test_and_set();
@@ -221,9 +231,21 @@
}
ExecutionResult executionResult;
- const auto ret = kBurst->executeSynchronously(request, memoryIdentifierTokens, measure,
- deadline, loopTimeoutDuration, &executionResult);
- HANDLE_ASTATUS(ret) << "execute failed";
+ if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+ auto aidlHints = NN_TRY(convert(hints));
+ auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+ const auto ret = kBurst->executeSynchronouslyWithConfig(
+ request, memoryIdentifierTokens,
+ {measure, loopTimeoutDuration, std::move(aidlHints),
+ std::move(aidlExtensionPrefix)},
+ deadline, &executionResult);
+ HANDLE_ASTATUS(ret) << "execute failed";
+ } else {
+ const auto ret =
+ kBurst->executeSynchronously(request, memoryIdentifierTokens, measure, deadline,
+ loopTimeoutDuration, &executionResult);
+ HANDLE_ASTATUS(ret) << "execute failed";
+ }
if (!executionResult.outputSufficientSize) {
auto canonicalOutputShapes =
nn::convert(executionResult.outputShapes).value_or(std::vector<nn::OutputShape>{});
@@ -241,7 +263,9 @@
nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -272,12 +296,15 @@
return BurstExecution::create(shared_from_this(), std::move(aidlRequest),
std::move(memoryIdentifierTokens), aidlMeasure,
- aidlLoopTimeoutDuration, std::move(relocation), std::move(holds));
+ aidlLoopTimeoutDuration, hints, extensionNameToPrefix,
+ std::move(relocation), std::move(holds));
}
nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create(
std::shared_ptr<const Burst> burst, Request request,
std::vector<int64_t> memoryIdentifierTokens, bool measure, int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
hal::utils::RequestRelocation relocation,
std::vector<Burst::OptionalCacheHold> cacheHolds) {
if (burst == nullptr) {
@@ -286,13 +313,15 @@
return std::make_shared<const BurstExecution>(
PrivateConstructorTag{}, std::move(burst), std::move(request),
- std::move(memoryIdentifierTokens), measure, loopTimeoutDuration, std::move(relocation),
- std::move(cacheHolds));
+ std::move(memoryIdentifierTokens), measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix, std::move(relocation), std::move(cacheHolds));
}
BurstExecution::BurstExecution(PrivateConstructorTag /*tag*/, std::shared_ptr<const Burst> burst,
Request request, std::vector<int64_t> memoryIdentifierTokens,
bool measure, int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
hal::utils::RequestRelocation relocation,
std::vector<Burst::OptionalCacheHold> cacheHolds)
: kBurst(std::move(burst)),
@@ -300,6 +329,8 @@
kMemoryIdentifierTokens(std::move(memoryIdentifierTokens)),
kMeasure(measure),
kLoopTimeoutDuration(loopTimeoutDuration),
+ kHints(hints),
+ kExtensionNameToPrefix(extensionNameToPrefix),
kRelocation(std::move(relocation)),
kCacheHolds(std::move(cacheHolds)) {}
@@ -307,7 +338,8 @@
const nn::OptionalTimePoint& deadline) const {
const auto aidlDeadline = NN_TRY(convert(deadline));
return kBurst->executeInternal(kRequest, kMemoryIdentifierTokens, kMeasure, aidlDeadline,
- kLoopTimeoutDuration, kRelocation);
+ kLoopTimeoutDuration, kHints, kExtensionNameToPrefix,
+ kRelocation);
}
nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
diff --git a/neuralnetworks/aidl/utils/src/Callbacks.cpp b/neuralnetworks/aidl/utils/src/Callbacks.cpp
index 8084970..554f3fa 100644
--- a/neuralnetworks/aidl/utils/src/Callbacks.cpp
+++ b/neuralnetworks/aidl/utils/src/Callbacks.cpp
@@ -38,16 +38,17 @@
// nn::kVersionFeatureLevel5. On failure, this function returns with the appropriate
// nn::GeneralError.
nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
- ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel) {
+ ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel,
+ nn::Version featureLevel) {
HANDLE_STATUS_AIDL(status) << "model preparation failed with " << toString(status);
- return NN_TRY(PreparedModel::create(preparedModel));
+ return NN_TRY(PreparedModel::create(preparedModel, featureLevel));
}
} // namespace
ndk::ScopedAStatus PreparedModelCallback::notify(
ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel) {
- mData.put(prepareModelCallback(status, preparedModel));
+ mData.put(prepareModelCallback(status, preparedModel, kFeatureLevel));
return ndk::ScopedAStatus::ok();
}
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index 45628c8..081e3d7 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -57,10 +57,6 @@
while (UNLIKELY(value > std::numeric_limits<int32_t>::max())) return NN_ERROR()
namespace {
-template <typename Type>
-constexpr std::underlying_type_t<Type> underlyingType(Type value) {
- return static_cast<std::underlying_type_t<Type>>(value);
-}
constexpr int64_t kNoTiming = -1;
@@ -70,6 +66,7 @@
namespace {
using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::neuralnetworks::utils::underlyingType;
template <typename Input>
using UnvalidatedConvertOutput =
@@ -302,9 +299,9 @@
};
}
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix) {
- return Model::ExtensionNameAndPrefix{
+ return ExtensionNameAndPrefix{
.name = extensionNameAndPrefix.name,
.prefix = extensionNameAndPrefix.prefix,
};
@@ -404,7 +401,7 @@
#endif // __ANDROID__
}
}
- return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
+ return NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag());
}
GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
@@ -506,6 +503,12 @@
return std::make_shared<const Handle>(std::move(duplicatedFd));
}
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<TokenValuePair> unvalidatedConvert(const aidl_hal::TokenValuePair& tokenValuePair) {
+ return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
+}
+#endif // NN_AIDL_V4_OR_ABOVE
+
GeneralResult<Capabilities> convert(const aidl_hal::Capabilities& capabilities) {
return validatedConvert(capabilities);
}
@@ -551,6 +554,10 @@
return validatedConvert(handle);
}
+GeneralResult<BufferDesc> convert(const aidl_hal::BufferDesc& bufferDesc) {
+ return validatedConvert(bufferDesc);
+}
+
GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension) {
return validatedConvert(extension);
}
@@ -558,12 +565,32 @@
GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories) {
return validatedConvert(memories);
}
+GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+ const std::vector<aidl_hal::ExtensionNameAndPrefix>& extensionNameAndPrefix) {
+ return unvalidatedConvert(extensionNameAndPrefix);
+}
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<std::vector<TokenValuePair>> convert(
+ const std::vector<aidl_hal::TokenValuePair>& metaData) {
+ return validatedConvert(metaData);
+}
+#endif // NN_AIDL_V4_OR_ABOVE
GeneralResult<std::vector<OutputShape>> convert(
const std::vector<aidl_hal::OutputShape>& outputShapes) {
return validatedConvert(outputShapes);
}
+GeneralResult<std::vector<SharedHandle>> convert(
+ const std::vector<ndk::ScopedFileDescriptor>& handles) {
+ return validatedConvert(handles);
+}
+
+GeneralResult<std::vector<BufferRole>> convert(const std::vector<aidl_hal::BufferRole>& roles) {
+ return validatedConvert(roles);
+}
+
GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec) {
if (!std::all_of(vec.begin(), vec.end(), [](int32_t v) { return v >= 0; })) {
return NN_ERROR() << "Negative value passed to conversion from signed to unsigned";
@@ -576,42 +603,7 @@
namespace aidl::android::hardware::neuralnetworks::utils {
namespace {
-template <typename Input>
-using UnvalidatedConvertOutput =
- std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
- const std::vector<Type>& arguments) {
- std::vector<UnvalidatedConvertOutput<Type>> halObject;
- halObject.reserve(arguments.size());
- for (const auto& argument : arguments) {
- halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
- }
- return halObject;
-}
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
- const std::vector<Type>& arguments) {
- return unvalidatedConvertVec(arguments);
-}
-
-template <typename Type>
-nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
- NN_TRY(compliantVersion(canonical));
- return utils::unvalidatedConvert(canonical);
-}
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
- const std::vector<Type>& arguments) {
- std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
- for (size_t i = 0; i < arguments.size(); ++i) {
- halObject[i] = NN_TRY(validatedConvert(arguments[i]));
- }
- return halObject;
-}
+using utils::unvalidatedConvert;
// Helper template for std::visit
template <class... Ts>
@@ -619,7 +611,7 @@
using Ts::operator()...;
};
template <class... Ts>
-overloaded(Ts...)->overloaded<Ts...>;
+overloaded(Ts...) -> overloaded<Ts...>;
#ifdef __ANDROID__
nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
@@ -721,6 +713,74 @@
operator nn::GeneralResult<Memory>();
}
+nn::GeneralResult<PerformanceInfo> unvalidatedConvert(
+ const nn::Capabilities::PerformanceInfo& info) {
+ return PerformanceInfo{.execTime = info.execTime, .powerUsage = info.powerUsage};
+}
+
+nn::GeneralResult<OperandPerformance> unvalidatedConvert(
+ const nn::Capabilities::OperandPerformance& operandPerformance) {
+ return OperandPerformance{.type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
+ .info = NN_TRY(unvalidatedConvert(operandPerformance.info))};
+}
+
+nn::GeneralResult<std::vector<OperandPerformance>> unvalidatedConvert(
+ const nn::Capabilities::OperandPerformanceTable& table) {
+ std::vector<OperandPerformance> operandPerformances;
+ operandPerformances.reserve(table.asVector().size());
+ for (const auto& operandPerformance : table.asVector()) {
+ operandPerformances.push_back(NN_TRY(unvalidatedConvert(operandPerformance)));
+ }
+ return operandPerformances;
+}
+
+nn::GeneralResult<ExtensionOperandTypeInformation> unvalidatedConvert(
+ const nn::Extension::OperandTypeInformation& info) {
+ return ExtensionOperandTypeInformation{.type = info.type,
+ .isTensor = info.isTensor,
+ .byteSize = static_cast<int32_t>(info.byteSize)};
+}
+
+nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
+ if (duration < nn::Duration::zero()) {
+ return NN_ERROR() << "Unable to convert invalid (negative) duration";
+ }
+ constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
+ const auto count = duration.count();
+ return static_cast<int64_t>(std::min(count, kIntMax));
+}
+
+template <typename Input>
+using UnvalidatedConvertOutput =
+ std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
+ const std::vector<Type>& arguments) {
+ std::vector<UnvalidatedConvertOutput<Type>> halObject;
+ halObject.reserve(arguments.size());
+ for (const auto& argument : arguments) {
+ halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
+ }
+ return halObject;
+}
+
+template <typename Type>
+nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
+ NN_TRY(compliantVersion(canonical));
+ return utils::unvalidatedConvert(canonical);
+}
+
+template <typename Type>
+nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
+ const std::vector<Type>& arguments) {
+ std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ halObject[i] = NN_TRY(validatedConvert(arguments[i]));
+ }
+ return halObject;
+}
+
} // namespace
nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken) {
@@ -743,6 +803,19 @@
};
}
+nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
+ switch (deviceType) {
+ case nn::DeviceType::UNKNOWN:
+ break;
+ case nn::DeviceType::OTHER:
+ case nn::DeviceType::CPU:
+ case nn::DeviceType::GPU:
+ case nn::DeviceType::ACCELERATOR:
+ return static_cast<DeviceType>(deviceType);
+ }
+ return NN_ERROR() << "Invalid DeviceType " << deviceType;
+}
+
nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
return measureTiming == nn::MeasureTiming::YES;
}
@@ -883,7 +956,7 @@
}
nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
- const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix) {
+ const nn::ExtensionNameAndPrefix& extensionNameToPrefix) {
return ExtensionNameAndPrefix{
.name = extensionNameToPrefix.name,
.prefix = extensionNameToPrefix.prefix,
@@ -891,6 +964,11 @@
}
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
+ if (!hal::utils::hasNoPointerData(model)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
+ }
+
return Model{
.main = NN_TRY(unvalidatedConvert(model.main)),
.referenced = NN_TRY(unvalidatedConvert(model.referenced)),
@@ -906,6 +984,11 @@
}
nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
+ if (!hal::utils::hasNoPointerData(request)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
+ }
+
return Request{
.inputs = NN_TRY(unvalidatedConvert(request.inputs)),
.outputs = NN_TRY(unvalidatedConvert(request.outputs)),
@@ -956,15 +1039,6 @@
};
}
-nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
- if (duration < nn::Duration::zero()) {
- return NN_ERROR() << "Unable to convert invalid (negative) duration";
- }
- constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
- const auto count = duration.count();
- return static_cast<int64_t>(std::min(count, kIntMax));
-}
-
nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration) {
if (!optionalDuration.has_value()) {
return kNoTiming;
@@ -989,6 +1063,28 @@
return ndk::ScopedFileDescriptor(duplicatedFd.release());
}
+nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
+ return Capabilities{
+ .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
+ unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+ .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
+ unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
+ .operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance)),
+ .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
+ .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
+ };
+}
+
+nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
+ return Extension{.name = extension.name,
+ .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes))};
+}
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<TokenValuePair> unvalidatedConvert(const nn::TokenValuePair& tokenValuePair) {
+ return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
+}
+#endif // NN_AIDL_V4_OR_ABOVE
+
nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken) {
return validatedConvert(cacheToken);
}
@@ -997,6 +1093,10 @@
return validatedConvert(bufferDesc);
}
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
+ return validatedConvert(deviceType);
+}
+
nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming) {
return validatedConvert(measureTiming);
}
@@ -1037,6 +1137,14 @@
return validatedConvert(outputShapes);
}
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+ return validatedConvert(capabilities);
+}
+
+nn::GeneralResult<Extension> convert(const nn::Extension& extension) {
+ return validatedConvert(extension);
+}
+
nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
return validatedConvert(bufferRoles);
}
@@ -1055,6 +1163,21 @@
const std::vector<nn::SyncFence>& syncFences) {
return validatedConvert(syncFences);
}
+nn::GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) {
+ return unvalidatedConvert(extensionNameToPrefix);
+}
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<std::vector<TokenValuePair>> convert(
+ const std::vector<nn::TokenValuePair>& metaData) {
+ return validatedConvert(metaData);
+}
+#endif // NN_AIDL_V4_OR_ABOVE
+
+nn::GeneralResult<std::vector<Extension>> convert(const std::vector<nn::Extension>& extensions) {
+ return validatedConvert(extensions);
+}
nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec) {
if (!std::all_of(vec.begin(), vec.end(),
@@ -1064,4 +1187,8 @@
return std::vector<int32_t>(vec.begin(), vec.end());
}
+std::vector<uint8_t> toVec(const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN>& token) {
+ return std::vector<uint8_t>(token.begin(), token.end());
+}
+
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index 5b7ec4e..b64a40d 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -215,7 +215,9 @@
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 {
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
// Ensure that model is ready for IPC.
std::optional<nn::Model> maybeModelInShared;
const nn::Model& modelInShared =
@@ -225,17 +227,28 @@
const auto aidlPreference = NN_TRY(convert(preference));
const auto aidlPriority = NN_TRY(convert(priority));
const auto aidlDeadline = NN_TRY(convert(deadline));
- const auto aidlModelCache = NN_TRY(convert(modelCache));
- const auto aidlDataCache = NN_TRY(convert(dataCache));
- const auto aidlToken = NN_TRY(convert(token));
+ auto aidlModelCache = NN_TRY(convert(modelCache));
+ auto aidlDataCache = NN_TRY(convert(dataCache));
- const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>();
+ const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>(kFeatureLevel);
const auto scoped = kDeathHandler.protectCallback(cb.get());
+ if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+ auto aidlHints = NN_TRY(convert(hints));
+ auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+ const auto ret = kDevice->prepareModelWithConfig(
+ aidlModel,
+ {aidlPreference, aidlPriority, aidlDeadline, std::move(aidlModelCache),
+ std::move(aidlDataCache), token, std::move(aidlHints),
+ std::move(aidlExtensionPrefix)},
+ cb);
+ HANDLE_ASTATUS(ret) << "prepareModel failed";
+ return cb->get();
+ }
+ const auto aidlToken = NN_TRY(convert(token));
const auto ret = kDevice->prepareModel(aidlModel, aidlPreference, aidlPriority, aidlDeadline,
aidlModelCache, aidlDataCache, aidlToken, cb);
HANDLE_ASTATUS(ret) << "prepareModel failed";
-
return cb->get();
}
@@ -247,7 +260,7 @@
const auto aidlDataCache = NN_TRY(convert(dataCache));
const auto aidlToken = NN_TRY(convert(token));
- const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>();
+ const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>(kFeatureLevel);
const auto scoped = kDeathHandler.protectCallback(cb.get());
const auto ret = kDevice->prepareModelFromCache(aidlDeadline, aidlModelCache, aidlDataCache,
diff --git a/neuralnetworks/aidl/utils/src/Execution.cpp b/neuralnetworks/aidl/utils/src/Execution.cpp
index 94edd90..2fd88af 100644
--- a/neuralnetworks/aidl/utils/src/Execution.cpp
+++ b/neuralnetworks/aidl/utils/src/Execution.cpp
@@ -35,44 +35,61 @@
namespace aidl::android::hardware::neuralnetworks::utils {
-nn::GeneralResult<std::shared_ptr<const Execution>> Execution::create(
- std::shared_ptr<const PreparedModel> preparedModel, Request request,
- hal::utils::RequestRelocation relocation, bool measure, int64_t loopTimeoutDuration) {
+nn::GeneralResult<std::shared_ptr<const ExecutionWithCachedRequest>>
+ExecutionWithCachedRequest::create(std::shared_ptr<const PreparedModel> preparedModel,
+ Request request, hal::utils::RequestRelocation relocation,
+ bool measure, int64_t loopTimeoutDuration) {
if (preparedModel == nullptr) {
- return NN_ERROR() << "aidl::utils::Execution::create must have non-null preparedModel";
+ return NN_ERROR() << "aidl::utils::ExecutionWithCachedRequest::create must have non-null "
+ "preparedModel";
}
- return std::make_shared<const Execution>(PrivateConstructorTag{}, std::move(preparedModel),
- std::move(request), std::move(relocation), measure,
- loopTimeoutDuration);
+ return std::make_shared<const ExecutionWithCachedRequest>(
+ PrivateConstructorTag{}, std::move(preparedModel), std::move(request),
+ std::move(relocation), measure, loopTimeoutDuration);
}
-Execution::Execution(PrivateConstructorTag /*tag*/,
- std::shared_ptr<const PreparedModel> preparedModel, Request request,
- hal::utils::RequestRelocation relocation, bool measure,
- int64_t loopTimeoutDuration)
+ExecutionWithCachedRequest::ExecutionWithCachedRequest(
+ PrivateConstructorTag /*tag*/, std::shared_ptr<const PreparedModel> preparedModel,
+ Request request, hal::utils::RequestRelocation relocation, bool measure,
+ int64_t loopTimeoutDuration)
: kPreparedModel(std::move(preparedModel)),
kRequest(std::move(request)),
kRelocation(std::move(relocation)),
kMeasure(measure),
kLoopTimeoutDuration(loopTimeoutDuration) {}
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
- const nn::OptionalTimePoint& deadline) const {
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+ExecutionWithCachedRequest::compute(const nn::OptionalTimePoint& deadline) const {
const auto aidlDeadline = NN_TRY(convert(deadline));
return kPreparedModel->executeInternal(kRequest, kMeasure, aidlDeadline, kLoopTimeoutDuration,
- kRelocation);
+ {}, {}, kRelocation);
}
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+ExecutionWithCachedRequest::computeFenced(
const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
const nn::OptionalDuration& timeoutDurationAfterFence) const {
const auto aidlWaitFor = NN_TRY(convert(waitFor));
const auto aidlDeadline = NN_TRY(convert(deadline));
const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
- return kPreparedModel->executeFencedInternal(kRequest, aidlWaitFor, kMeasure, aidlDeadline,
- kLoopTimeoutDuration,
- aidlTimeoutDurationAfterFence, kRelocation);
+ return kPreparedModel->executeFencedInternal(
+ kRequest, aidlWaitFor, kMeasure, aidlDeadline, kLoopTimeoutDuration,
+ aidlTimeoutDurationAfterFence, {}, {}, kRelocation);
}
+nn::GeneralResult<std::shared_ptr<const Execution>> Execution::create(
+ std::shared_ptr<aidl_hal::IExecution> execution, hal::utils::RequestRelocation relocation) {
+ if (execution == nullptr) {
+ return NN_ERROR() << "aidl::utils::Execution::create must have non-null execution";
+ }
+
+ return std::make_shared<const Execution>(PrivateConstructorTag{}, std::move(execution),
+ std::move(relocation));
+}
+
+Execution::Execution(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IExecution> execution,
+ hal::utils::RequestRelocation relocation)
+ : kExecution(std::move(execution)), kRelocation(std::move(relocation)) {}
+
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
index c9d9955..44f8ea9 100644
--- a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
+++ b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
@@ -167,6 +167,32 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus InvalidDevice::prepareModelWithConfig(
+ const Model& model, const PrepareModelConfig& config,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ if (!utils::valid(config.extensionNameToPrefix)) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT, "Invalid extensionNameToPrefix");
+ }
+ for (const auto& hint : config.compilationHints) {
+ auto result = std::find_if(config.extensionNameToPrefix.begin(),
+ config.extensionNameToPrefix.end(),
+ [&hint](const ExtensionNameAndPrefix& extension) {
+ uint16_t prefix = static_cast<uint32_t>(hint.token) >>
+ IDevice::EXTENSION_TYPE_LOW_BITS_TYPE;
+ return prefix == extension.prefix;
+ });
+ if (result == config.extensionNameToPrefix.end()) {
+ callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+ return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+ "Invalid token for compilation hints: " + std::to_string(hint.token));
+ }
+ }
+ return prepareModel(model, config.preference, config.priority, config.deadlineNs,
+ config.modelCache, config.dataCache, utils::toVec(config.cacheToken),
+ callback);
+}
+
ndk::ScopedAStatus InvalidDevice::prepareModelFromCache(
int64_t /*deadline*/, const std::vector<ndk::ScopedFileDescriptor>& /*modelCache*/,
const std::vector<ndk::ScopedFileDescriptor>& /*dataCache*/,
diff --git a/neuralnetworks/aidl/utils/src/PreparedModel.cpp b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
index f25c2c8..7e3a31c 100644
--- a/neuralnetworks/aidl/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
@@ -54,61 +54,16 @@
return std::make_pair(NN_TRY(nn::convert(timingLaunched)), NN_TRY(nn::convert(timingFenced)));
}
-} // namespace
-
-nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
- std::shared_ptr<aidl_hal::IPreparedModel> preparedModel) {
- if (preparedModel == nullptr) {
- return NN_ERROR()
- << "aidl_hal::utils::PreparedModel::create must have non-null preparedModel";
- }
-
- return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel));
-}
-
-PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/,
- std::shared_ptr<aidl_hal::IPreparedModel> preparedModel)
- : kPreparedModel(std::move(preparedModel)) {}
-
-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::OptionalDuration& loopTimeoutDuration) const {
- // Ensure that request is ready for IPC.
- std::optional<nn::Request> maybeRequestInShared;
- hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
- &maybeRequestInShared, &relocation));
-
- const auto aidlRequest = NN_TRY(convert(requestInShared));
- const auto aidlMeasure = NN_TRY(convert(measure));
- const auto aidlDeadline = NN_TRY(convert(deadline));
- const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
- return executeInternal(aidlRequest, aidlMeasure, aidlDeadline, aidlLoopTimeoutDuration,
- relocation);
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-PreparedModel::executeInternal(const Request& request, bool measure, int64_t deadline,
- int64_t loopTimeoutDuration,
- const hal::utils::RequestRelocation& relocation) const {
- if (relocation.input) {
- relocation.input->flush();
- }
-
- ExecutionResult executionResult;
- const auto ret = kPreparedModel->executeSynchronously(request, measure, deadline,
- loopTimeoutDuration, &executionResult);
- HANDLE_ASTATUS(ret) << "executeSynchronously failed";
- if (!executionResult.outputSufficientSize) {
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> handleExecutionResult(
+ const ExecutionResult& result, const hal::utils::RequestRelocation& relocation) {
+ if (!result.outputSufficientSize) {
auto canonicalOutputShapes =
- nn::convert(executionResult.outputShapes).value_or(std::vector<nn::OutputShape>{});
+ nn::convert(result.outputShapes).value_or(std::vector<nn::OutputShape>{});
return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
<< "execution failed with " << nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
}
auto [outputShapes, timing] =
- NN_TRY(convertExecutionResults(executionResult.outputShapes, executionResult.timing));
+ NN_TRY(convertExecutionResults(result.outputShapes, result.timing));
if (relocation.output) {
relocation.output->flush();
@@ -117,44 +72,8 @@
}
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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const {
- // Ensure that request is ready for IPC.
- std::optional<nn::Request> maybeRequestInShared;
- hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
- &maybeRequestInShared, &relocation));
-
- const auto aidlRequest = NN_TRY(convert(requestInShared));
- const auto aidlWaitFor = NN_TRY(convert(waitFor));
- const auto aidlMeasure = NN_TRY(convert(measure));
- const auto aidlDeadline = NN_TRY(convert(deadline));
- const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
- const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
- return executeFencedInternal(aidlRequest, aidlWaitFor, aidlMeasure, aidlDeadline,
- aidlLoopTimeoutDuration, aidlTimeoutDurationAfterFence,
- relocation);
-}
-
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFencedInternal(const Request& request,
- const std::vector<ndk::ScopedFileDescriptor>& waitFor,
- bool measure, int64_t deadline, int64_t loopTimeoutDuration,
- int64_t timeoutDurationAfterFence,
- const hal::utils::RequestRelocation& relocation) const {
- if (relocation.input) {
- relocation.input->flush();
- }
-
- FencedExecutionResult result;
- const auto ret =
- kPreparedModel->executeFenced(request, waitFor, measure, deadline, loopTimeoutDuration,
- timeoutDurationAfterFence, &result);
- HANDLE_ASTATUS(ret) << "executeFenced failed";
-
+handleFencedExecutionResult(const FencedExecutionResult& result,
+ const hal::utils::RequestRelocation& relocation) {
auto resultSyncFence = nn::SyncFence::createAsSignaled();
if (result.syncFence.get() != -1) {
resultSyncFence = nn::SyncFence::create(NN_TRY(nn::convert(result.syncFence))).value();
@@ -165,7 +84,7 @@
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "callback is null";
}
- // If executeFenced required the request memory to be moved into shared memory, block here until
+ // If computeFenced required the request memory to be moved into shared memory, block here until
// the fenced execution has completed and flush the memory back.
if (relocation.output) {
const auto state = resultSyncFence.syncWait({});
@@ -189,9 +108,133 @@
return std::make_pair(std::move(resultSyncFence), std::move(resultCallback));
}
+} // namespace
+
+nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
+ std::shared_ptr<aidl_hal::IPreparedModel> preparedModel, nn::Version featureLevel) {
+ if (preparedModel == nullptr) {
+ return NN_ERROR()
+ << "aidl_hal::utils::PreparedModel::create must have non-null preparedModel";
+ }
+
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
+ featureLevel);
+}
+
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/,
+ std::shared_ptr<aidl_hal::IPreparedModel> preparedModel,
+ nn::Version featureLevel)
+ : kPreparedModel(std::move(preparedModel)), kFeatureLevel(featureLevel) {}
+
+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::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ hal::utils::RequestRelocation relocation;
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+ &maybeRequestInShared, &relocation));
+
+ const auto aidlRequest = NN_TRY(convert(requestInShared));
+ const auto aidlMeasure = NN_TRY(convert(measure));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+ const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
+ return executeInternal(aidlRequest, aidlMeasure, aidlDeadline, aidlLoopTimeoutDuration, hints,
+ extensionNameToPrefix, relocation);
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeInternal(const Request& request, bool measure, int64_t deadline,
+ int64_t loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+ const hal::utils::RequestRelocation& relocation) const {
+ if (relocation.input) {
+ relocation.input->flush();
+ }
+
+ ExecutionResult executionResult;
+ if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+ auto aidlHints = NN_TRY(convert(hints));
+ auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+ const auto ret = kPreparedModel->executeSynchronouslyWithConfig(
+ request,
+ {measure, loopTimeoutDuration, std::move(aidlHints),
+ std::move(aidlExtensionPrefix)},
+ deadline, &executionResult);
+ HANDLE_ASTATUS(ret) << "executeSynchronouslyWithConfig failed";
+ } else {
+ const auto ret = kPreparedModel->executeSynchronously(
+ request, measure, deadline, loopTimeoutDuration, &executionResult);
+ HANDLE_ASTATUS(ret) << "executeSynchronously failed";
+ }
+ return handleExecutionResult(executionResult, relocation);
+}
+
+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::OptionalDuration& loopTimeoutDuration,
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ // Ensure that request is ready for IPC.
+ std::optional<nn::Request> maybeRequestInShared;
+ hal::utils::RequestRelocation relocation;
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+ &maybeRequestInShared, &relocation));
+
+ const auto aidlRequest = NN_TRY(convert(requestInShared));
+ const auto aidlWaitFor = NN_TRY(convert(waitFor));
+ const auto aidlMeasure = NN_TRY(convert(measure));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+ const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
+ const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
+ return executeFencedInternal(aidlRequest, aidlWaitFor, aidlMeasure, aidlDeadline,
+ aidlLoopTimeoutDuration, aidlTimeoutDurationAfterFence, hints,
+ extensionNameToPrefix, relocation);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFencedInternal(
+ const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measure,
+ int64_t deadline, int64_t loopTimeoutDuration, int64_t timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+ const hal::utils::RequestRelocation& relocation) const {
+ if (relocation.input) {
+ relocation.input->flush();
+ }
+
+ FencedExecutionResult result;
+ if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+ auto aidlHints = NN_TRY(convert(hints));
+ auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+ const auto ret = kPreparedModel->executeFencedWithConfig(
+ request, waitFor,
+ {measure, loopTimeoutDuration, std::move(aidlHints),
+ std::move(aidlExtensionPrefix)},
+ deadline, timeoutDurationAfterFence, &result);
+ HANDLE_ASTATUS(ret) << "executeFencedWithConfig failed";
+ } else {
+ const auto ret = kPreparedModel->executeFenced(request, waitFor, measure, deadline,
+ loopTimeoutDuration,
+ timeoutDurationAfterFence, &result);
+ HANDLE_ASTATUS(ret) << "executeFenced failed";
+ }
+ return handleFencedExecutionResult(result, relocation);
+}
+
nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
@@ -202,15 +245,31 @@
auto aidlRequest = NN_TRY(convert(requestInShared));
auto aidlMeasure = NN_TRY(convert(measure));
auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
- return Execution::create(shared_from_this(), std::move(aidlRequest), std::move(relocation),
- aidlMeasure, aidlLoopTimeoutDuration);
+
+ if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+ std::shared_ptr<IExecution> execution;
+ auto aidlHints = NN_TRY(convert(hints));
+ auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+
+ const auto ret = kPreparedModel->createReusableExecution(
+ aidlRequest,
+ {aidlMeasure, aidlLoopTimeoutDuration, std::move(aidlHints),
+ std::move(aidlExtensionPrefix)},
+ &execution);
+ HANDLE_ASTATUS(ret) << "createReusableExecution failed";
+ return Execution::create(std::move(execution), std::move(relocation));
+ }
+
+ return ExecutionWithCachedRequest::create(shared_from_this(), std::move(aidlRequest),
+ std::move(relocation), aidlMeasure,
+ aidlLoopTimeoutDuration);
}
nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
std::shared_ptr<IBurst> burst;
const auto ret = kPreparedModel->configureExecutionBurst(&burst);
HANDLE_ASTATUS(ret) << "configureExecutionBurst failed";
- return Burst::create(std::move(burst));
+ return Burst::create(std::move(burst), kFeatureLevel);
}
std::any PreparedModel::getUnderlyingResource() const {
@@ -218,4 +277,36 @@
return resource;
}
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
+ const nn::OptionalTimePoint& deadline) const {
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+
+ if (kRelocation.input) {
+ kRelocation.input->flush();
+ }
+
+ ExecutionResult executionResult;
+ auto ret = kExecution->executeSynchronously(aidlDeadline, &executionResult);
+ HANDLE_ASTATUS(ret) << "executeSynchronously failed";
+ return handleExecutionResult(executionResult, kRelocation);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
+ const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalDuration& timeoutDurationAfterFence) const {
+ const auto aidlWaitFor = NN_TRY(convert(waitFor));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+ const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
+
+ if (kRelocation.input) {
+ kRelocation.input->flush();
+ }
+
+ FencedExecutionResult result;
+ const auto ret = kExecution->executeFenced(aidlWaitFor, aidlDeadline,
+ aidlTimeoutDurationAfterFence, &result);
+ HANDLE_ASTATUS(ret) << "executeFenced failed";
+ return handleFencedExecutionResult(result, kRelocation);
+}
+
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index e48593c..24fbb53 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -55,11 +55,12 @@
} // namespace
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
+nn::GeneralResult<nn::SharedDevice> getDevice(
+ const std::string& instanceName, ::android::nn::Version::Level maxFeatureLevelAllowed) {
auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
hal::utils::ResilientDevice::Factory makeDevice =
- [instanceName,
- name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ [instanceName, name = std::move(fullName),
+ maxFeatureLevelAllowed](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
std::add_pointer_t<AIBinder*(const char*)> getService;
if (blocking) {
if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
@@ -79,7 +80,8 @@
<< " returned nullptr";
}
ABinderProcess_startThreadPool();
- const auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+ auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+ featureLevel.level = std::min(featureLevel.level, maxFeatureLevelAllowed);
return Device::create(instanceName, std::move(service), featureLevel);
};
diff --git a/neuralnetworks/aidl/utils/src/Utils.cpp b/neuralnetworks/aidl/utils/src/Utils.cpp
index 03407be..76a0b07 100644
--- a/neuralnetworks/aidl/utils/src/Utils.cpp
+++ b/neuralnetworks/aidl/utils/src/Utils.cpp
@@ -88,7 +88,7 @@
return Memory::make<Memory::Tag::hardwareBuffer>(std::move(handle));
}
}
- return (NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag())
+ return (NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag()))
.
operator nn::GeneralResult<Memory>();
}
@@ -103,7 +103,7 @@
}
// Using explicit type conversion because std::variant inside the RequestMemoryPool confuses the
// compiler.
- return (NN_ERROR() << "Unrecognized request pool tag: " << requestPool.getTag())
+ return (NN_ERROR() << "Unrecognized request pool tag: " << underlyingType(requestPool.getTag()))
.
operator nn::GeneralResult<RequestMemoryPool>();
}
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index 0366e7d..73727b3 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -17,6 +17,7 @@
#include "MockBuffer.h"
#include "MockDevice.h"
#include "MockPreparedModel.h"
+#include "TestUtils.h"
#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
#include <android/binder_auto_utils.h>
@@ -60,7 +61,6 @@
.powerUsage = std::numeric_limits<float>::max()};
constexpr NumberOfCacheFiles kNumberOfCacheFiles = {.numModelCache = nn::kMaxNumberOfCacheFiles - 1,
.numDataCache = nn::kMaxNumberOfCacheFiles};
-
constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
std::shared_ptr<MockDevice> createMockDevice() {
@@ -123,6 +123,18 @@
};
}
+const std::vector<nn::TokenValuePair> kHints = {nn::TokenValuePair{.token = 0, .value = {1}}};
+const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix = {
+ nn::ExtensionNameAndPrefix{.name = "com.android.nn_test", .prefix = 1}};
+auto makePreparedModelWithConfigReturn(ErrorStatus launchStatus, ErrorStatus returnStatus,
+ const std::shared_ptr<MockPreparedModel>& preparedModel) {
+ return [launchStatus, returnStatus, preparedModel](
+ const Model& /*model*/, const PrepareModelConfig& /*config*/,
+ const std::shared_ptr<IPreparedModelCallback>& cb) -> ndk::ScopedAStatus {
+ return makePreparedModelReturnImpl(launchStatus, returnStatus, preparedModel, cb);
+ };
+}
+
auto makePreparedModelFromCacheReturn(ErrorStatus launchStatus, ErrorStatus returnStatus,
const std::shared_ptr<MockPreparedModel>& preparedModel) {
return [launchStatus, returnStatus, preparedModel](
@@ -146,26 +158,7 @@
return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
};
-class DeviceTest : public ::testing::TestWithParam<nn::Version> {
- protected:
- const nn::Version kVersion = GetParam();
-};
-
-std::string printDeviceTest(const testing::TestParamInfo<nn::Version>& info) {
- const nn::Version version = info.param;
- CHECK(!version.runtimeOnlyFeatures);
- switch (version.level) {
- case nn::Version::Level::FEATURE_LEVEL_5:
- return "v1";
- case nn::Version::Level::FEATURE_LEVEL_6:
- return "v2";
- case nn::Version::Level::FEATURE_LEVEL_7:
- return "v3";
- default:
- LOG(FATAL) << "Invalid AIDL version: " << version;
- return "invalid";
- }
-}
+class DeviceTest : public VersionedAidlUtilsTestBase {};
} // namespace
@@ -578,6 +571,8 @@
}
TEST_P(DeviceTest, prepareModel) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -589,7 +584,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -598,6 +593,8 @@
}
TEST_P(DeviceTest, prepareModelLaunchError) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -608,7 +605,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -616,6 +613,8 @@
}
TEST_P(DeviceTest, prepareModelReturnError) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -626,7 +625,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -634,6 +633,8 @@
}
TEST_P(DeviceTest, prepareModelNullptrError) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -644,7 +645,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -652,6 +653,8 @@
}
TEST_P(DeviceTest, prepareModelTransportFailure) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -661,7 +664,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -669,6 +672,8 @@
}
TEST_P(DeviceTest, prepareModelDeadObject) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup call
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -678,7 +683,7 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -686,6 +691,8 @@
}
TEST_P(DeviceTest, prepareModelAsyncCrash) {
+ if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
// setup test
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
@@ -699,7 +706,157 @@
// run test
const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfig) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto mockPreparedModel = MockPreparedModel::create();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makePreparedModelWithConfigReturn(ErrorStatus::NONE, ErrorStatus::NONE,
+ mockPreparedModel)));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ EXPECT_NE(result.value(), nullptr);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigLaunchError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makePreparedModelWithConfigReturn(
+ ErrorStatus::GENERAL_FAILURE, ErrorStatus::GENERAL_FAILURE, nullptr)));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigReturnError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makePreparedModelWithConfigReturn(
+ ErrorStatus::NONE, ErrorStatus::GENERAL_FAILURE, nullptr)));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigNullptrError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makePreparedModelWithConfigReturn(ErrorStatus::NONE, ErrorStatus::NONE,
+ nullptr)));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigTransportFailure) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigDeadObject) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigAsyncCrash) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockDevice = createMockDevice();
+ const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto ret = [&device]() {
+ DeathMonitor::serviceDied(device->getDeathMonitor());
+ return ndk::ScopedAStatus::ok();
+ };
+ EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(ret));
+
+ // run test
+ const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+ kExtensionNameToPrefix);
// verify result
ASSERT_FALSE(result.has_value());
@@ -894,9 +1051,6 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-INSTANTIATE_TEST_SUITE_P(TestDevice, DeviceTest,
- ::testing::Values(nn::kVersionFeatureLevel5, nn::kVersionFeatureLevel6,
- nn::kVersionFeatureLevel7),
- printDeviceTest);
+INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(DeviceTest, kAllAidlVersions);
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/ExecutionTest.cpp b/neuralnetworks/aidl/utils/test/ExecutionTest.cpp
new file mode 100644
index 0000000..8519290
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/ExecutionTest.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MockExecution.h"
+#include "MockFencedExecutionCallback.h"
+
+#include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Execution.h>
+
+#include <functional>
+#include <memory>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+namespace {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Invoke;
+using ::testing::InvokeWithoutArgs;
+using ::testing::SetArgPointee;
+
+const std::shared_ptr<IExecution> kInvalidExecution;
+constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
+
+constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
+
+constexpr auto makeGeneralFailure = [] {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+};
+constexpr auto makeGeneralTransportFailure = [] {
+ return ndk::ScopedAStatus::fromStatus(STATUS_NO_MEMORY);
+};
+constexpr auto makeDeadObjectFailure = [] {
+ return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
+};
+
+auto makeFencedExecutionResult(const std::shared_ptr<MockFencedExecutionCallback>& callback) {
+ return [callback](const std::vector<ndk::ScopedFileDescriptor>& /*waitFor*/,
+ int64_t /*deadline*/, int64_t /*duration*/,
+ FencedExecutionResult* fencedExecutionResult) {
+ *fencedExecutionResult = FencedExecutionResult{.callback = callback,
+ .syncFence = ndk::ScopedFileDescriptor(-1)};
+ return ndk::ScopedAStatus::ok();
+ };
+}
+
+} // namespace
+
+TEST(ExecutionTest, invalidExecution) {
+ // run test
+ const auto result = Execution::create(kInvalidExecution, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSync) {
+ // setup call
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ const auto mockExecutionResult = ExecutionResult{
+ .outputSufficientSize = true,
+ .outputShapes = {},
+ .timing = kNoTiming,
+ };
+ EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<1>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
+
+ // run test
+ const auto result = execution->compute({});
+
+ // verify result
+ EXPECT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+}
+
+TEST(ExecutionTest, executeSyncError) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+ .Times(1)
+ .WillOnce(Invoke(makeGeneralFailure));
+
+ // run test
+ const auto result = execution->compute({});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSyncTransportFailure) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto result = execution->compute({});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSyncDeadObject) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto result = execution->compute({});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST(ExecutionTest, executeFenced) {
+ // setup call
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+ SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
+ EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
+
+ // run test
+ const auto result = execution->computeFenced({}, {}, {});
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ const auto& [syncFence, callback] = result.value();
+ EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
+ ASSERT_NE(callback, nullptr);
+
+ // get results from callback
+ const auto callbackResult = callback();
+ ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
+ << callbackResult.error().message;
+}
+
+TEST(ExecutionTest, executeFencedCallbackError) {
+ // setup call
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+ SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
+ Invoke(makeStatusOk))));
+ EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
+
+ // run test
+ const auto result = execution->computeFenced({}, {}, {});
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ const auto& [syncFence, callback] = result.value();
+ EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
+ ASSERT_NE(callback, nullptr);
+
+ // verify callback failure
+ const auto callbackResult = callback();
+ ASSERT_FALSE(callbackResult.has_value());
+ EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedError) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+
+ // run test
+ const auto result = execution->computeFenced({}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedTransportFailure) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto result = execution->computeFenced({}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedDeadObject) {
+ // setup test
+ const auto mockExecution = MockExecution::create();
+ const auto execution = Execution::create(mockExecution, {}).value();
+ EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto result = execution->computeFenced({}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/MockBuffer.h b/neuralnetworks/aidl/utils/test/MockBuffer.h
index f77fa86..7a05a0f 100644
--- a/neuralnetworks/aidl/utils/test/MockBuffer.h
+++ b/neuralnetworks/aidl/utils/test/MockBuffer.h
@@ -21,7 +21,6 @@
#include <android/binder_interface_utils.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/Status.h>
namespace aidl::android::hardware::neuralnetworks::utils {
diff --git a/neuralnetworks/aidl/utils/test/MockBurst.h b/neuralnetworks/aidl/utils/test/MockBurst.h
index 5083bbd..609bd30 100644
--- a/neuralnetworks/aidl/utils/test/MockBurst.h
+++ b/neuralnetworks/aidl/utils/test/MockBurst.h
@@ -21,7 +21,6 @@
#include <android/binder_interface_utils.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/Status.h>
namespace aidl::android::hardware::neuralnetworks::utils {
@@ -32,6 +31,10 @@
bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
ExecutionResult* executionResult),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, executeSynchronouslyWithConfig,
+ (const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+ const ExecutionConfig& config, int64_t deadline, ExecutionResult* executionResult),
+ (override));
MOCK_METHOD(ndk::ScopedAStatus, releaseMemoryResource, (int64_t memoryIdentifierToken),
(override));
};
diff --git a/neuralnetworks/aidl/utils/test/MockDevice.h b/neuralnetworks/aidl/utils/test/MockDevice.h
index 3a28d55..47b8346 100644
--- a/neuralnetworks/aidl/utils/test/MockDevice.h
+++ b/neuralnetworks/aidl/utils/test/MockDevice.h
@@ -50,6 +50,10 @@
const std::vector<uint8_t>& token,
const std::shared_ptr<IPreparedModelCallback>& callback),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, prepareModelWithConfig,
+ (const Model& model, const PrepareModelConfig& config,
+ const std::shared_ptr<IPreparedModelCallback>& callback),
+ (override));
MOCK_METHOD(ndk::ScopedAStatus, prepareModelFromCache,
(int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
const std::vector<ndk::ScopedFileDescriptor>& dataCache,
diff --git a/neuralnetworks/aidl/utils/test/MockExecution.h b/neuralnetworks/aidl/utils/test/MockExecution.h
new file mode 100644
index 0000000..782e54f
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/MockExecution.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_AIDL_UTILS_TEST_MOCK_EXECUTION_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_EXECUTION_H
+
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <android/binder_interface_utils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+class MockExecution final : public BnExecution {
+ public:
+ static std::shared_ptr<MockExecution> create();
+
+ MOCK_METHOD(ndk::ScopedAStatus, executeSynchronously,
+ (int64_t deadline, ExecutionResult* executionResult), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, executeFenced,
+ (const std::vector<ndk::ScopedFileDescriptor>& waitFor, int64_t deadline,
+ int64_t duration, FencedExecutionResult* fencedExecutionResult),
+ (override));
+};
+
+inline std::shared_ptr<MockExecution> MockExecution::create() {
+ return ndk::SharedRefBase::make<MockExecution>();
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_EXECUTION_H
diff --git a/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h b/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
index 06f9ea2..29449bb 100644
--- a/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
+++ b/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
@@ -22,7 +22,6 @@
#include <android/binder_interface_utils.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/Status.h>
namespace aidl::android::hardware::neuralnetworks::utils {
diff --git a/neuralnetworks/aidl/utils/test/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
index a4ae2b7..a5b3b66 100644
--- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h
+++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
@@ -17,12 +17,11 @@
#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_PREPARED_MODEL_H
#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_PREPARED_MODEL_H
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
#include <android/binder_interface_utils.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/Status.h>
namespace aidl::android::hardware::neuralnetworks::utils {
@@ -39,8 +38,21 @@
bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
int64_t duration, FencedExecutionResult* fencedExecutionResult),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, executeSynchronouslyWithConfig,
+ (const Request& request, const ExecutionConfig& config, int64_t deadline,
+ ExecutionResult* executionResult),
+ (override));
+ MOCK_METHOD(ndk::ScopedAStatus, executeFencedWithConfig,
+ (const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ const ExecutionConfig& config, int64_t deadline, int64_t duration,
+ FencedExecutionResult* fencedExecutionResult),
+ (override));
MOCK_METHOD(ndk::ScopedAStatus, configureExecutionBurst, (std::shared_ptr<IBurst> * burst),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, createReusableExecution,
+ (const Request& request, const ExecutionConfig& config,
+ std::shared_ptr<IExecution>* execution),
+ (override));
};
inline std::shared_ptr<MockPreparedModel> MockPreparedModel::create() {
diff --git a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
index 8bb5c90..bf6136d 100644
--- a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
@@ -15,8 +15,10 @@
*/
#include "MockBurst.h"
+#include "MockExecution.h"
#include "MockFencedExecutionCallback.h"
#include "MockPreparedModel.h"
+#include "TestUtils.h"
#include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
#include <gmock/gmock.h>
@@ -66,21 +68,40 @@
};
}
+class PreparedModelTest : public VersionedAidlUtilsTestBase {};
+
+const std::vector<nn::TokenValuePair> kHints = {nn::TokenValuePair{.token = 0, .value = {1}}};
+const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix = {
+ nn::ExtensionNameAndPrefix{.name = "com.android.nn_test", .prefix = 1}};
+auto makeFencedExecutionWithConfigResult(
+ const std::shared_ptr<MockFencedExecutionCallback>& callback) {
+ return [callback](const Request& /*request*/,
+ const std::vector<ndk::ScopedFileDescriptor>& /*waitFor*/,
+ const ExecutionConfig& /*config*/, int64_t /*deadline*/, int64_t /*duration*/,
+ FencedExecutionResult* fencedExecutionResult) {
+ *fencedExecutionResult = FencedExecutionResult{.callback = callback,
+ .syncFence = ndk::ScopedFileDescriptor(-1)};
+ return ndk::ScopedAStatus::ok();
+ };
+}
+
} // namespace
-TEST(PreparedModelTest, invalidPreparedModel) {
+TEST_P(PreparedModelTest, invalidPreparedModel) {
// run test
- const auto result = PreparedModel::create(kInvalidPreparedModel);
+ const auto result = PreparedModel::create(kInvalidPreparedModel, kVersion);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeSync) {
+TEST_P(PreparedModelTest, executeSync) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockExecutionResult = ExecutionResult{
.outputSufficientSize = true,
.outputShapes = {},
@@ -92,65 +113,73 @@
DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
EXPECT_TRUE(result.has_value())
<< "Failed with " << result.error().code << ": " << result.error().message;
}
-TEST(PreparedModelTest, executeSyncError) {
+TEST_P(PreparedModelTest, executeSyncError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makeGeneralFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeSyncTransportFailure) {
+TEST_P(PreparedModelTest, executeSyncTransportFailure) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeSyncDeadObject) {
+TEST_P(PreparedModelTest, executeSyncDeadObject) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST(PreparedModelTest, executeFenced) {
+TEST_P(PreparedModelTest, executeFenced) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockCallback = MockFencedExecutionCallback::create();
EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
.Times(1)
@@ -161,7 +190,7 @@
.WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -176,10 +205,12 @@
<< callbackResult.error().message;
}
-TEST(PreparedModelTest, executeFencedCallbackError) {
+TEST_P(PreparedModelTest, executeFencedCallbackError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockCallback = MockFencedExecutionCallback::create();
EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
.Times(1)
@@ -191,7 +222,7 @@
.WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -206,59 +237,67 @@
EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeFencedError) {
+TEST_P(PreparedModelTest, executeFencedError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeFencedTransportFailure) {
+TEST_P(PreparedModelTest, executeFencedTransportFailure) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, executeFencedDeadObject) {
+TEST_P(PreparedModelTest, executeFencedDeadObject) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST(PreparedModelTest, reusableExecuteSync) {
+TEST_P(PreparedModelTest, reusableExecuteSync) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const uint32_t kNumberOfComputations = 2;
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockExecutionResult = ExecutionResult{
.outputSufficientSize = true,
.outputShapes = {},
@@ -270,7 +309,7 @@
DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -283,16 +322,18 @@
}
}
-TEST(PreparedModelTest, reusableExecuteSyncError) {
+TEST_P(PreparedModelTest, reusableExecuteSyncError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makeGeneralFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -303,16 +344,18 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
+TEST_P(PreparedModelTest, reusableExecuteSyncTransportFailure) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -323,16 +366,18 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
+TEST_P(PreparedModelTest, reusableExecuteSyncDeadObject) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -343,11 +388,13 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST(PreparedModelTest, reusableExecuteFenced) {
+TEST_P(PreparedModelTest, reusableExecuteFenced) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const uint32_t kNumberOfComputations = 2;
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockCallback = MockFencedExecutionCallback::create();
EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
.Times(kNumberOfComputations)
@@ -358,7 +405,7 @@
.WillRepeatedly(Invoke(makeFencedExecutionResult(mockCallback)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -379,10 +426,12 @@
}
}
-TEST(PreparedModelTest, reusableExecuteFencedCallbackError) {
+TEST_P(PreparedModelTest, reusableExecuteFencedCallbackError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup call
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
const auto mockCallback = MockFencedExecutionCallback::create();
EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
.Times(1)
@@ -394,7 +443,7 @@
.WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -413,16 +462,18 @@
EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, reusableExecuteFencedError) {
+TEST_P(PreparedModelTest, reusableExecuteFencedError) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -433,16 +484,18 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, reusableExecuteFencedTransportFailure) {
+TEST_P(PreparedModelTest, reusableExecuteFencedTransportFailure) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -453,16 +506,18 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, reusableExecuteFencedDeadObject) {
+TEST_P(PreparedModelTest, reusableExecuteFencedDeadObject) {
+ if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// create execution
- const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
ASSERT_TRUE(createResult.has_value())
<< "Failed with " << createResult.error().code << ": " << createResult.error().message;
ASSERT_NE(createResult.value(), nullptr);
@@ -473,14 +528,214 @@
EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST(PreparedModelTest, configureExecutionBurst) {
+TEST_P(PreparedModelTest, executeSyncWithConfig) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ const auto mockExecutionResult = ExecutionResult{
+ .outputSufficientSize = true,
+ .outputShapes = {},
+ .timing = kNoTiming,
+ };
+ EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<3>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
+
+ // run test
+ const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ EXPECT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeGeneralFailure));
+
+ // run test
+ const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigTransportFailure) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigDeadObject) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfig) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+ SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
+ EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeFencedExecutionWithConfigResult(mockCallback)));
+
+ // run test
+ const auto result =
+ preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ const auto& [syncFence, callback] = result.value();
+ EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
+ ASSERT_NE(callback, nullptr);
+
+ // get results from callback
+ const auto callbackResult = callback();
+ ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
+ << callbackResult.error().message;
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigCallbackError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup call
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+ .Times(1)
+ .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+ SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
+ Invoke(makeStatusOk))));
+ EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeFencedExecutionWithConfigResult(mockCallback)));
+
+ // run test
+ const auto result =
+ preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ const auto& [syncFence, callback] = result.value();
+ EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
+ ASSERT_NE(callback, nullptr);
+
+ // verify callback failure
+ const auto callbackResult = callback();
+ ASSERT_FALSE(callbackResult.has_value());
+ EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+
+ // run test
+ const auto result =
+ preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigTransportFailure) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto result =
+ preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigDeadObject) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+ EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto result =
+ preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, configureExecutionBurst) {
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
const auto mockBurst = ndk::SharedRefBase::make<MockBurst>();
EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
.Times(1)
.WillOnce(DoAll(SetArgPointee<0>(mockBurst), Invoke(makeStatusOk)));
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
// run test
const auto result = preparedModel->configureExecutionBurst();
@@ -491,13 +746,13 @@
EXPECT_NE(result.value(), nullptr);
}
-TEST(PreparedModelTest, configureExecutionBurstError) {
+TEST_P(PreparedModelTest, configureExecutionBurstError) {
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
// run test
const auto result = preparedModel->configureExecutionBurst();
@@ -507,13 +762,13 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, configureExecutionBurstTransportFailure) {
+TEST_P(PreparedModelTest, configureExecutionBurstTransportFailure) {
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
// run test
const auto result = preparedModel->configureExecutionBurst();
@@ -523,13 +778,13 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST(PreparedModelTest, configureExecutionBurstDeadObject) {
+TEST_P(PreparedModelTest, configureExecutionBurstDeadObject) {
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
// run test
const auto result = preparedModel->configureExecutionBurst();
@@ -539,10 +794,84 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST(PreparedModelTest, getUnderlyingResource) {
+TEST_P(PreparedModelTest, createReusableExecution) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
// setup test
const auto mockPreparedModel = MockPreparedModel::create();
- const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+ const auto mockExecution = ndk::SharedRefBase::make<MockExecution>();
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<2>(mockExecution), Invoke(makeStatusOk)));
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+ // run test
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+ // verify result
+ ASSERT_TRUE(result.has_value())
+ << "Failed with " << result.error().code << ": " << result.error().message;
+ EXPECT_NE(result.value(), nullptr);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionError) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+ // run test
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionTransportFailure) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+ // run test
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionDeadObject) {
+ if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+ // run test
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, getUnderlyingResource) {
+ // setup test
+ const auto mockPreparedModel = MockPreparedModel::create();
+ const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
// run test
const auto resource = preparedModel->getUnderlyingResource();
@@ -554,4 +883,6 @@
EXPECT_EQ(maybeMock->get(), mockPreparedModel.get());
}
+INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(PreparedModelTest, kAllAidlVersions);
+
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/TestUtils.cpp b/neuralnetworks/aidl/utils/test/TestUtils.cpp
new file mode 100644
index 0000000..9abec88
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/TestUtils.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TestUtils.h"
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <string>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+std::string printTestVersion(const testing::TestParamInfo<nn::Version>& info) {
+ switch (info.param.level) {
+ case nn::Version::Level::FEATURE_LEVEL_5:
+ return "v1";
+ case nn::Version::Level::FEATURE_LEVEL_6:
+ return "v2";
+ case nn::Version::Level::FEATURE_LEVEL_7:
+ return "v3";
+ case nn::Version::Level::FEATURE_LEVEL_8:
+ return "v4";
+ default:
+ LOG(FATAL) << "Invalid AIDL version: " << info.param;
+ return "invalid";
+ }
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/TestUtils.h b/neuralnetworks/aidl/utils/test/TestUtils.h
new file mode 100644
index 0000000..23f734a
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/TestUtils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_AIDL_UTILS_TEST_TEST_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_TEST_UTILS_H
+
+#include <gtest/gtest.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <string>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+class VersionedAidlUtilsTestBase : public ::testing::TestWithParam<nn::Version> {
+ protected:
+ const nn::Version kVersion = GetParam();
+};
+
+std::string printTestVersion(const testing::TestParamInfo<nn::Version>& info);
+
+inline const auto kAllAidlVersions =
+ ::testing::Values(nn::kVersionFeatureLevel5, nn::kVersionFeatureLevel6,
+ nn::kVersionFeatureLevel7, nn::kVersionFeatureLevel8);
+
+#define INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(TestSuite, versions) \
+ INSTANTIATE_TEST_SUITE_P(Versioned, TestSuite, versions, printTestVersion)
+
+} // namespace aidl::android::hardware::neuralnetworks::utils
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_TEST_UTILS_H
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 1ed15b8..04b4a45 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -30,6 +30,11 @@
"neuralnetworks_vts_functional_defaults",
"use_libaidlvintf_gtest_helper_static",
],
+ host_supported: true,
+ tidy_timeout_srcs: [
+ "CompilationCachingTests.cpp",
+ "MemoryDomainTests.cpp",
+ ],
srcs: [
"BasicTests.cpp",
"Callbacks.cpp",
@@ -46,18 +51,11 @@
],
shared_libs: [
"libbinder_ndk",
- "libnativewindow",
- "libvndksupport",
],
static_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libaidlcommonsupport",
- "libgmock",
- "libhidlmemory",
"libneuralnetworks_common",
"libneuralnetworks_generated_test_harness",
- "libsync",
],
whole_static_libs: [
"neuralnetworks_generated_AIDL_V3_example",
@@ -73,6 +71,34 @@
],
test_suites: [
"general-tests",
- "vts",
],
+ target: {
+ android: {
+ shared_libs: [
+ "libnativewindow",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "libsync",
+ ],
+ test_suites: [
+ "vts",
+ ],
+ test_config: "AndroidTestDevice.xml",
+ },
+ host: {
+ shared_libs: [
+ "libtextclassifier_hash",
+ ],
+ static_libs: [
+ "neuralnetworks_canonical_sample_driver",
+ "neuralnetworks_utils_hal_adapter_aidl",
+ ],
+ exclude_static_libs: [
+ "VtsHalHidlTestUtils",
+ "libaidlvintf_gtest_helper",
+ ],
+ test_config: "AndroidTestHost.xml",
+ },
+ },
}
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTest.xml b/neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
similarity index 100%
rename from neuralnetworks/aidl/vts/functional/AndroidTest.xml
rename to neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
new file mode 100644
index 0000000..7372a31
--- /dev/null
+++ b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalNeuralnetworksTargetTest.">
+ <test class="com.android.tradefed.testtype.HostGTest" >
+ <option name="module-name" value="VtsHalNeuralnetworksTargetTest" />
+ <option name="native-test-timeout" value="15m" />
+ </test>
+</configuration>
+
diff --git a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index 77208aa..7451f7e 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -23,7 +23,6 @@
#include <fcntl.h>
#include <ftw.h>
#include <gtest/gtest.h>
-#include <hidlmemory/mapping.h>
#include <unistd.h>
#include <cstdio>
@@ -34,7 +33,6 @@
#include "Callbacks.h"
#include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
#include "TestHarness.h"
#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
@@ -229,7 +227,11 @@
// Create cache directory. The cache directory and a temporary cache file is always created
// to test the behavior of prepareModelFromCache, even when caching is not supported.
+#ifdef __ANDROID__
char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
+#else // __ANDROID__
+ char cacheDirTemp[] = "/tmp/TestCompilationCachingXXXXXX";
+#endif // __ANDROID__
char* cacheDir = mkdtemp(cacheDirTemp);
ASSERT_NE(cacheDir, nullptr);
mCacheDir = cacheDir;
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index f67fd34..40f6cd1 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -20,7 +20,6 @@
#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
-#include <android/sync.h>
#include <gtest/gtest.h>
#include <algorithm>
@@ -30,7 +29,6 @@
#include <numeric>
#include <vector>
-#include <MemoryUtils.h>
#include <android/binder_status.h>
#include <nnapi/Result.h>
#include <nnapi/SharedMemory.h>
@@ -43,6 +41,10 @@
#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
+#ifdef __ANDROID__
+#include <android/sync.h>
+#endif // __ANDROID__
+
namespace aidl::android::hardware::neuralnetworks::vts::functional {
namespace nn = ::android::nn;
@@ -58,25 +60,66 @@
bool measureTiming;
OutputType outputType;
MemoryType memoryType;
+ bool reusable;
// `reportSkipping` indicates if a test should print an info message in case
// it is skipped. The field is set to true by default and is set to false in
// quantization coupling tests to suppress skipping a test
bool reportSkipping;
- TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType)
- : executor(executor),
- measureTiming(measureTiming),
- outputType(outputType),
- memoryType(memoryType),
- reportSkipping(true) {}
+ // `useConfig` indicates if a test should use execute*WithConfig functions for the execution.
+ bool useConfig;
TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
- bool reportSkipping)
+ bool reusable)
: executor(executor),
measureTiming(measureTiming),
outputType(outputType),
memoryType(memoryType),
- reportSkipping(reportSkipping) {}
+ reusable(reusable),
+ reportSkipping(true),
+ useConfig(false) {}
+ TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
+ bool reusable, bool reportSkipping)
+ : executor(executor),
+ measureTiming(measureTiming),
+ outputType(outputType),
+ memoryType(memoryType),
+ reusable(reusable),
+ reportSkipping(reportSkipping),
+ useConfig(false) {}
+ TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
+ bool reusable, bool reportSkipping, bool useConfig)
+ : executor(executor),
+ measureTiming(measureTiming),
+ outputType(outputType),
+ memoryType(memoryType),
+ reusable(reusable),
+ reportSkipping(reportSkipping),
+ useConfig(useConfig) {}
};
+std::string toString(OutputType type) {
+ switch (type) {
+ case OutputType::FULLY_SPECIFIED:
+ return "FULLY_SPECIFIED";
+ case OutputType::UNSPECIFIED:
+ return "UNSPECIFIED";
+ case OutputType::INSUFFICIENT:
+ return "INSUFFICIENT";
+ case OutputType::MISSED_DEADLINE:
+ return "MISSED_DEADLINE";
+ }
+}
+
+std::string toString(const TestConfig& config) {
+ std::stringstream ss;
+ ss << "TestConfig{.executor=" << toString(config.executor)
+ << ", .measureTiming=" << (config.measureTiming ? "true" : "false")
+ << ", .outputType=" << toString(config.outputType)
+ << ", .memoryType=" << toString(config.memoryType)
+ << ", .reusable=" << (config.reusable ? "true" : "false")
+ << ", .useConfig=" << (config.useConfig ? "true" : "false") << "}";
+ return ss.str();
+}
+
enum class IOType { INPUT, OUTPUT };
class DeviceMemoryAllocator {
@@ -240,10 +283,14 @@
} // namespace
void waitForSyncFence(int syncFd) {
- constexpr int kInfiniteTimeout = -1;
ASSERT_GT(syncFd, 0);
+#ifdef __ANDROID__
+ constexpr int kInfiniteTimeout = -1;
int r = sync_wait(syncFd, kInfiniteTimeout);
ASSERT_GE(r, 0);
+#else // __ANDROID__
+ LOG(FATAL) << "waitForSyncFence not supported on host";
+#endif // __ANDROID__
}
Model createModel(const TestModel& testModel) {
@@ -558,209 +605,266 @@
loopTimeoutDurationNs = 1 * kMillisecond;
}
- ErrorStatus executionStatus;
- std::vector<OutputShape> outputShapes;
- Timing timing = kNoTiming;
- switch (testConfig.executor) {
- case Executor::SYNC: {
- SCOPED_TRACE("synchronous");
+ std::shared_ptr<IExecution> execution;
+ if (testConfig.reusable) {
+ const auto ret = preparedModel->createReusableExecution(
+ request, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}}, &execution);
+ ASSERT_TRUE(ret.isOk()) << static_cast<nn::ErrorStatus>(ret.getServiceSpecificError());
+ ASSERT_NE(nullptr, execution.get());
+ }
- ExecutionResult executionResult;
- // execute
- const auto ret = preparedModel->executeSynchronously(request, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDurationNs,
- &executionResult);
- ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
- << ret.getDescription();
- if (ret.isOk()) {
- executionStatus = executionResult.outputSufficientSize
- ? ErrorStatus::NONE
- : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
- outputShapes = std::move(executionResult.outputShapes);
- timing = executionResult.timing;
- } else {
- executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
- }
- break;
- }
- case Executor::BURST: {
- SCOPED_TRACE("burst");
+ const auto executeAndCheckResults = [&preparedModel, &execution, &testConfig, &testModel,
+ &context, &request, loopTimeoutDurationNs, skipped]() {
+ ErrorStatus executionStatus;
+ std::vector<OutputShape> outputShapes;
+ Timing timing = kNoTiming;
+ switch (testConfig.executor) {
+ case Executor::SYNC: {
+ SCOPED_TRACE("synchronous");
- // create burst
- std::shared_ptr<IBurst> burst;
- auto ret = preparedModel->configureExecutionBurst(&burst);
- ASSERT_TRUE(ret.isOk()) << ret.getDescription();
- ASSERT_NE(nullptr, burst.get());
-
- // associate a unique slot with each memory pool
- int64_t currentSlot = 0;
- std::vector<int64_t> slots;
- slots.reserve(request.pools.size());
- for (const auto& pool : request.pools) {
- if (pool.getTag() == RequestMemoryPool::Tag::pool) {
- slots.push_back(currentSlot++);
+ ExecutionResult executionResult;
+ // execute
+ ::ndk::ScopedAStatus ret;
+ if (testConfig.reusable) {
+ ret = execution->executeSynchronously(kNoDeadline, &executionResult);
+ } else if (testConfig.useConfig) {
+ ret = preparedModel->executeSynchronouslyWithConfig(
+ request, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+ kNoDeadline, &executionResult);
} else {
- EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
- slots.push_back(-1);
+ ret = preparedModel->executeSynchronously(request, testConfig.measureTiming,
+ kNoDeadline, loopTimeoutDurationNs,
+ &executionResult);
}
+ ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << ret.getDescription();
+ if (ret.isOk()) {
+ executionStatus = executionResult.outputSufficientSize
+ ? ErrorStatus::NONE
+ : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+ outputShapes = std::move(executionResult.outputShapes);
+ timing = executionResult.timing;
+ } else {
+ executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+ }
+ break;
}
+ case Executor::BURST: {
+ SCOPED_TRACE("burst");
- ExecutionResult executionResult;
- // execute
- ret = burst->executeSynchronously(request, slots, testConfig.measureTiming, kNoDeadline,
- loopTimeoutDurationNs, &executionResult);
- ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
- << ret.getDescription();
- if (ret.isOk()) {
- executionStatus = executionResult.outputSufficientSize
- ? ErrorStatus::NONE
- : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
- outputShapes = std::move(executionResult.outputShapes);
- timing = executionResult.timing;
- } else {
- executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
- }
-
- // Mark each slot as unused after the execution. This is unnecessary because the burst
- // is freed after this scope ends, but this is here to test the functionality.
- for (int64_t slot : slots) {
- ret = burst->releaseMemoryResource(slot);
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
ASSERT_TRUE(ret.isOk()) << ret.getDescription();
- }
+ ASSERT_NE(nullptr, burst.get());
- break;
- }
- case Executor::FENCED: {
- SCOPED_TRACE("fenced");
- ErrorStatus result = ErrorStatus::NONE;
- FencedExecutionResult executionResult;
- auto ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDurationNs, kNoDuration,
- &executionResult);
- ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
- << ret.getDescription();
- if (!ret.isOk()) {
- result = static_cast<ErrorStatus>(ret.getServiceSpecificError());
- executionStatus = result;
- } else if (executionResult.syncFence.get() != -1) {
- std::vector<ndk::ScopedFileDescriptor> waitFor;
- auto dupFd = dup(executionResult.syncFence.get());
- ASSERT_NE(dupFd, -1);
- waitFor.emplace_back(dupFd);
- // If a sync fence is returned, try start another run waiting for the sync fence.
- ret = preparedModel->executeFenced(request, waitFor, testConfig.measureTiming,
- kNoDeadline, loopTimeoutDurationNs, kNoDuration,
- &executionResult);
- ASSERT_TRUE(ret.isOk());
- waitForSyncFence(executionResult.syncFence.get());
- }
- if (result == ErrorStatus::NONE) {
- ASSERT_NE(executionResult.callback, nullptr);
- Timing timingFenced;
- auto ret = executionResult.callback->getExecutionInfo(&timing, &timingFenced,
- &executionStatus);
- ASSERT_TRUE(ret.isOk());
- }
- break;
- }
- default: {
- FAIL() << "Unsupported execution mode for AIDL interface.";
- }
- }
-
- if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
- executionStatus == ErrorStatus::GENERAL_FAILURE) {
- if (skipped != nullptr) {
- *skipped = true;
- }
- if (!testConfig.reportSkipping) {
- return;
- }
- LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
- "execute model that it does not support.";
- std::cout << "[ ] Early termination of test because vendor service cannot "
- "execute model that it does not support."
- << std::endl;
- GTEST_SKIP();
- }
- if (!testConfig.measureTiming) {
- EXPECT_EQ(timing, kNoTiming);
- } else {
- if (timing.timeOnDeviceNs != -1 && timing.timeInDriverNs != -1) {
- EXPECT_LE(timing.timeOnDeviceNs, timing.timeInDriverNs);
- }
- }
-
- switch (testConfig.outputType) {
- case OutputType::FULLY_SPECIFIED:
- if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
- // Executor::FENCED does not support zero-sized output.
- ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
- return;
- }
- // If the model output operands are fully specified, outputShapes must be either
- // either empty, or have the same number of elements as the number of outputs.
- ASSERT_EQ(ErrorStatus::NONE, executionStatus);
- ASSERT_TRUE(outputShapes.size() == 0 ||
- outputShapes.size() == testModel.main.outputIndexes.size());
- break;
- case OutputType::UNSPECIFIED:
- if (testConfig.executor == Executor::FENCED) {
- // For Executor::FENCED, the output shape must be fully specified.
- ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
- return;
- }
- // If the model output operands are not fully specified, outputShapes must have
- // the same number of elements as the number of outputs.
- ASSERT_EQ(ErrorStatus::NONE, executionStatus);
- ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
- break;
- case OutputType::INSUFFICIENT:
- if (testConfig.executor == Executor::FENCED) {
- // For Executor::FENCED, the output shape must be fully specified.
- ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
- return;
- }
- ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
- ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
- // Check that all returned output dimensions are at least as fully specified as the
- // union of the information about the corresponding operand in the model and in the
- // request. In this test, all model outputs have known rank with all dimensions
- // unspecified, and no dimensional information is provided in the request.
- for (uint32_t i = 0; i < outputShapes.size(); i++) {
- ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
- const auto& actual = outputShapes[i].dimensions;
- const auto& golden =
- testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
- ASSERT_EQ(actual.size(), golden.size());
- for (uint32_t j = 0; j < actual.size(); j++) {
- if (actual[j] == 0) continue;
- EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+ // associate a unique slot with each memory pool
+ int64_t currentSlot = 0;
+ std::vector<int64_t> slots;
+ slots.reserve(request.pools.size());
+ for (const auto& pool : request.pools) {
+ if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+ slots.push_back(currentSlot++);
+ } else {
+ EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
+ slots.push_back(-1);
+ }
}
+
+ ExecutionResult executionResult;
+ // execute
+ if (testConfig.useConfig) {
+ ret = burst->executeSynchronouslyWithConfig(
+ request, slots,
+ {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}}, kNoDeadline,
+ &executionResult);
+ } else {
+ ret = burst->executeSynchronously(request, slots, testConfig.measureTiming,
+ kNoDeadline, loopTimeoutDurationNs,
+ &executionResult);
+ }
+ ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << ret.getDescription();
+ if (ret.isOk()) {
+ executionStatus = executionResult.outputSufficientSize
+ ? ErrorStatus::NONE
+ : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+ outputShapes = std::move(executionResult.outputShapes);
+ timing = executionResult.timing;
+ } else {
+ executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+ }
+
+ // Mark each slot as unused after the execution. This is unnecessary because the
+ // burst is freed after this scope ends, but this is here to test the functionality.
+ for (int64_t slot : slots) {
+ ret = burst->releaseMemoryResource(slot);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ }
+
+ break;
}
- return;
- case OutputType::MISSED_DEADLINE:
- ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
- executionStatus == ErrorStatus::MISSED_DEADLINE_PERSISTENT)
- << "executionStatus = " << executionStatus;
- return;
+ case Executor::FENCED: {
+ SCOPED_TRACE("fenced");
+ ErrorStatus result = ErrorStatus::NONE;
+ FencedExecutionResult executionResult;
+ ::ndk::ScopedAStatus ret;
+ if (testConfig.reusable) {
+ ret = execution->executeFenced({}, kNoDeadline, kNoDuration, &executionResult);
+ } else if (testConfig.useConfig) {
+ ret = preparedModel->executeFencedWithConfig(
+ request, {}, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+ kNoDeadline, kNoDuration, &executionResult);
+ } else {
+ ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
+ kNoDeadline, loopTimeoutDurationNs,
+ kNoDuration, &executionResult);
+ }
+ ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << ret.getDescription();
+ if (!ret.isOk()) {
+ result = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+ executionStatus = result;
+ } else if (executionResult.syncFence.get() != -1) {
+ std::vector<ndk::ScopedFileDescriptor> waitFor;
+ auto dupFd = dup(executionResult.syncFence.get());
+ ASSERT_NE(dupFd, -1);
+ waitFor.emplace_back(dupFd);
+ // If a sync fence is returned, try start another run waiting for the sync
+ // fence.
+ if (testConfig.reusable) {
+ ret = execution->executeFenced(waitFor, kNoDeadline, kNoDuration,
+ &executionResult);
+ } else if (testConfig.useConfig) {
+ ret = preparedModel->executeFencedWithConfig(
+ request, waitFor,
+ {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+ kNoDeadline, kNoDuration, &executionResult);
+ } else {
+ ret = preparedModel->executeFenced(
+ request, waitFor, testConfig.measureTiming, kNoDeadline,
+ loopTimeoutDurationNs, kNoDuration, &executionResult);
+ }
+ ASSERT_TRUE(ret.isOk());
+ waitForSyncFence(executionResult.syncFence.get());
+ }
+ if (result == ErrorStatus::NONE) {
+ ASSERT_NE(executionResult.callback, nullptr);
+ Timing timingFenced;
+ auto ret = executionResult.callback->getExecutionInfo(&timing, &timingFenced,
+ &executionStatus);
+ ASSERT_TRUE(ret.isOk());
+ }
+ break;
+ }
+ default: {
+ FAIL() << "Unsupported execution mode for AIDL interface.";
+ }
+ }
+
+ if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
+ executionStatus == ErrorStatus::GENERAL_FAILURE) {
+ if (skipped != nullptr) {
+ *skipped = true;
+ }
+ if (!testConfig.reportSkipping) {
+ return;
+ }
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "execute model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "execute model that it does not support."
+ << std::endl;
+ GTEST_SKIP();
+ }
+ if (!testConfig.measureTiming) {
+ EXPECT_EQ(timing, kNoTiming);
+ } else {
+ if (timing.timeOnDeviceNs != -1 && timing.timeInDriverNs != -1) {
+ EXPECT_LE(timing.timeOnDeviceNs, timing.timeInDriverNs);
+ }
+ }
+
+ switch (testConfig.outputType) {
+ case OutputType::FULLY_SPECIFIED:
+ if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
+ // Executor::FENCED does not support zero-sized output.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
+ // If the model output operands are fully specified, outputShapes must be either
+ // either empty, or have the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_TRUE(outputShapes.size() == 0 ||
+ outputShapes.size() == testModel.main.outputIndexes.size());
+ break;
+ case OutputType::UNSPECIFIED:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
+ // If the model output operands are not fully specified, outputShapes must have
+ // the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
+ break;
+ case OutputType::INSUFFICIENT:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
+ ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
+ // Check that all returned output dimensions are at least as fully specified as the
+ // union of the information about the corresponding operand in the model and in the
+ // request. In this test, all model outputs have known rank with all dimensions
+ // unspecified, and no dimensional information is provided in the request.
+ for (uint32_t i = 0; i < outputShapes.size(); i++) {
+ ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
+ const auto& actual = outputShapes[i].dimensions;
+ const auto& golden =
+ testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+ ASSERT_EQ(actual.size(), golden.size());
+ for (uint32_t j = 0; j < actual.size(); j++) {
+ if (actual[j] == 0) continue;
+ EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+ }
+ }
+ return;
+ case OutputType::MISSED_DEADLINE:
+ ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
+ executionStatus == ErrorStatus::MISSED_DEADLINE_PERSISTENT)
+ << "executionStatus = " << executionStatus;
+ return;
+ }
+
+ // Go through all outputs, check returned output shapes.
+ for (uint32_t i = 0; i < outputShapes.size(); i++) {
+ EXPECT_TRUE(outputShapes[i].isSufficient);
+ const auto& expect =
+ testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+ const auto unsignedActual = nn::toUnsigned(outputShapes[i].dimensions);
+ ASSERT_TRUE(unsignedActual.has_value());
+ const std::vector<uint32_t>& actual = unsignedActual.value();
+ EXPECT_EQ(expect, actual);
+ }
+
+ // Retrieve execution results.
+ const std::vector<TestBuffer> outputs = context.getOutputBuffers(testModel, request);
+
+ // We want "close-enough" results.
+ checkResults(testModel, outputs);
+ };
+
+ executeAndCheckResults();
+
+ // For reusable execution tests, run the execution twice.
+ if (testConfig.reusable) {
+ SCOPED_TRACE("Second execution");
+ executeAndCheckResults();
}
-
- // Go through all outputs, check returned output shapes.
- for (uint32_t i = 0; i < outputShapes.size(); i++) {
- EXPECT_TRUE(outputShapes[i].isSufficient);
- const auto& expect = testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
- const auto unsignedActual = nn::toUnsigned(outputShapes[i].dimensions);
- ASSERT_TRUE(unsignedActual.has_value());
- const std::vector<uint32_t>& actual = unsignedActual.value();
- EXPECT_EQ(expect, actual);
- }
-
- // Retrieve execution results.
- const std::vector<TestBuffer> outputs = context.getOutputBuffers(testModel, request);
-
- // We want "close-enough" results.
- checkResults(testModel, outputs);
}
void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device,
@@ -770,6 +874,15 @@
std::vector<bool> measureTimingList;
std::vector<Executor> executorList;
std::vector<MemoryType> memoryTypeList;
+ std::vector<bool> reusableList = {false};
+ std::vector<bool> useConfigList = {false};
+
+ int deviceVersion;
+ ASSERT_TRUE(device->getInterfaceVersion(&deviceVersion).isOk());
+ if (deviceVersion >= kMinAidlLevelForFL8) {
+ reusableList.push_back(true);
+ useConfigList.push_back(true);
+ }
switch (testKind) {
case TestKind::GENERAL: {
@@ -788,7 +901,11 @@
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {false};
executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
+#ifdef __ANDROID__
memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
+#else // __ANDROID__
+ memoryTypeList = {MemoryType::DEVICE}; // BLOB_AHWB is not supported on the host.
+#endif // __ANDROID__
} break;
case TestKind::FENCED_COMPUTE: {
outputTypesList = {OutputType::FULLY_SPECIFIED};
@@ -812,8 +929,16 @@
for (const bool measureTiming : measureTimingList) {
for (const Executor executor : executorList) {
for (const MemoryType memoryType : memoryTypeList) {
- const TestConfig testConfig(executor, measureTiming, outputType, memoryType);
- EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+ for (const bool reusable : reusableList) {
+ for (const bool useConfig : useConfigList) {
+ if ((useConfig || executor == Executor::BURST) && reusable) continue;
+ const TestConfig testConfig(executor, measureTiming, outputType,
+ memoryType, reusable,
+ /*reportSkipping=*/true, useConfig);
+ SCOPED_TRACE(toString(testConfig));
+ EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+ }
+ }
}
}
}
@@ -833,7 +958,7 @@
for (const bool measureTiming : measureTimingList) {
for (const Executor executor : executorList) {
const TestConfig testConfig(executor, measureTiming, outputType, MemoryType::ASHMEM,
- /*reportSkipping=*/false);
+ /*reusable=*/false, /*reportSkipping=*/false);
bool baseSkipped = false;
EvaluatePreparedModel(device, preparedModel, testModel, testConfig, &baseSkipped);
bool coupledSkipped = false;
@@ -871,6 +996,13 @@
createPreparedModel(device, model, &preparedModel);
if (preparedModel == nullptr) return;
EvaluatePreparedModel(device, preparedModel, testModel, testKind);
+ int32_t deviceVersion;
+ ASSERT_TRUE(device->getInterfaceVersion(&deviceVersion).isOk());
+ if (deviceVersion >= kMinAidlLevelForFL8) {
+ createPreparedModel(device, model, &preparedModel, /*reportSkipping*/ true,
+ /*useConfig*/ true);
+ EvaluatePreparedModel(device, preparedModel, testModel, testKind);
+ }
} break;
case TestKind::QUANTIZATION_COUPLING: {
ASSERT_TRUE(testModel.hasQuant8CoupledOperands());
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index cd5475c..f8341b1 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "neuralnetworks_aidl_hal_test"
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModel.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
#include <android/binder_interface_utils.h>
@@ -33,7 +34,6 @@
#include "Callbacks.h"
#include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
@@ -191,7 +191,7 @@
}
// A placeholder invalid IPreparedModel class for MemoryDomainAllocateTest.InvalidPreparedModel
-class InvalidPreparedModel : public BnPreparedModel {
+class InvalidPreparedModel final : public IPreparedModel {
public:
ndk::ScopedAStatus executeSynchronously(const Request&, bool, int64_t, int64_t,
ExecutionResult*) override {
@@ -204,10 +204,37 @@
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
}
+ ndk::ScopedAStatus executeSynchronouslyWithConfig(const Request&, const ExecutionConfig&,
+ int64_t, ExecutionResult*) override {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
+ ndk::ScopedAStatus executeFencedWithConfig(const Request&,
+ const std::vector<ndk::ScopedFileDescriptor>&,
+ const ExecutionConfig&, int64_t, int64_t,
+ FencedExecutionResult*) override {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>*) override {
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
}
+ ndk::ScopedAStatus createReusableExecution(const aidl_hal::Request&, const ExecutionConfig&,
+ std::shared_ptr<aidl_hal::IExecution>*) override {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
+ ndk::ScopedAStatus getInterfaceVersion(int32_t* /*interfaceVersion*/) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
+ ndk::ScopedAStatus getInterfaceHash(std::string* /*interfaceHash*/) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+ }
+ ndk::SpAIBinder asBinder() override { return ::ndk::SpAIBinder{}; }
+ bool isRemote() override { return true; }
};
template <typename... Args>
diff --git a/neuralnetworks/aidl/vts/functional/Utils.cpp b/neuralnetworks/aidl/vts/functional/Utils.cpp
index 325a436..1bc76f2 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.cpp
+++ b/neuralnetworks/aidl/vts/functional/Utils.cpp
@@ -21,18 +21,20 @@
#include <aidl/android/hardware/neuralnetworks/OperandType.h>
#include <android-base/logging.h>
#include <android/binder_status.h>
-#include <android/hardware_buffer.h>
#include <sys/mman.h>
#include <iostream>
#include <limits>
#include <numeric>
-#include <MemoryUtils.h>
#include <nnapi/SharedMemory.h>
#include <nnapi/hal/aidl/Conversions.h>
#include <nnapi/hal/aidl/Utils.h>
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#endif // __ANDROID__
+
namespace aidl::android::hardware::neuralnetworks {
using test_helper::TestBuffer;
@@ -140,7 +142,8 @@
return ahwb->mIsValid ? std::move(ahwb) : nullptr;
}
-void TestBlobAHWB::initialize(uint32_t size) {
+void TestBlobAHWB::initialize([[maybe_unused]] uint32_t size) {
+#ifdef __ANDROID__
mIsValid = false;
ASSERT_GT(size, 0);
const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
@@ -164,6 +167,9 @@
mAidlMemory = utils::convert(mMemory).value();
mIsValid = true;
+#else // __ANDROID__
+ LOG(FATAL) << "TestBlobAHWB::initialize not supported on host";
+#endif // __ANDROID__
}
std::string gtestCompliantName(std::string name) {
@@ -177,6 +183,17 @@
return os << toString(errorStatus);
}
+std::string toString(MemoryType type) {
+ switch (type) {
+ case MemoryType::ASHMEM:
+ return "ASHMEM";
+ case MemoryType::BLOB_AHWB:
+ return "BLOB_AHWB";
+ case MemoryType::DEVICE:
+ return "DEVICE";
+ }
+}
+
Request ExecutionContext::createRequest(const TestModel& testModel, MemoryType memoryType) {
CHECK(memoryType == MemoryType::ASHMEM || memoryType == MemoryType::BLOB_AHWB);
diff --git a/neuralnetworks/aidl/vts/functional/Utils.h b/neuralnetworks/aidl/vts/functional/Utils.h
index ca81418..ccb0778 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -18,10 +18,10 @@
#define ANDROID_HARDWARE_NEURALNETWORKS_AIDL_UTILS_H
#include <android-base/logging.h>
-#include <android/hardware_buffer.h>
#include <gtest/gtest.h>
#include <algorithm>
+#include <array>
#include <iosfwd>
#include <string>
#include <utility>
@@ -48,6 +48,7 @@
inline constexpr int64_t kOmittedTimeoutDuration = -1;
inline constexpr int64_t kNoDuration = -1;
inline const std::vector<uint8_t> kEmptyCacheToken(IDevice::BYTE_SIZE_OF_CACHE_TOKEN);
+inline const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN> kEmptyCacheTokenArray{};
// Returns the amount of space needed to store a value of the specified type.
//
@@ -111,6 +112,8 @@
enum class MemoryType { ASHMEM, BLOB_AHWB, DEVICE };
+std::string toString(MemoryType type);
+
// Manages the lifetime of memory resources used in an execution.
class ExecutionContext {
DISALLOW_COPY_AND_ASSIGN(ExecutionContext);
diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
index fdc7eff..060434e 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
@@ -77,6 +77,28 @@
ASSERT_EQ(nullptr, preparedModel.get());
}
+static void validatePrepareModelWithConfig(const std::shared_ptr<IDevice>& device,
+ const std::string& message, const Model& model,
+ ExecutionPreference preference, Priority priority) {
+ SCOPED_TRACE(message + " [prepareModelWithConfig]");
+
+ std::shared_ptr<PreparedModelCallback> preparedModelCallback =
+ ndk::SharedRefBase::make<PreparedModelCallback>();
+ const auto prepareLaunchStatus = device->prepareModelWithConfig(
+ model, {preference, priority, kNoDeadline, {}, {}, kEmptyCacheTokenArray, {}, {}},
+ preparedModelCallback);
+ ASSERT_FALSE(prepareLaunchStatus.isOk());
+ ASSERT_EQ(prepareLaunchStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(prepareLaunchStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+
+ preparedModelCallback->wait();
+ ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+ std::shared_ptr<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+ ASSERT_EQ(nullptr, preparedModel.get());
+}
+
static bool validExecutionPreference(ExecutionPreference preference) {
return preference == ExecutionPreference::LOW_POWER ||
preference == ExecutionPreference::FAST_SINGLE_ANSWER ||
@@ -103,6 +125,13 @@
}
validatePrepareModel(device, message, model, preference, priority);
+
+ int32_t aidlVersion;
+ ASSERT_TRUE(device->getInterfaceVersion(&aidlVersion).isOk());
+ if (aidlVersion >= kMinAidlLevelForFL8) {
+ // prepareModelWithConfig must satisfy all requirements enforced by prepareModel.
+ validatePrepareModelWithConfig(device, message, model, preference, priority);
+ }
}
static uint32_t addOperand(Model* model) {
diff --git a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
index 29e2471..d749841 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
@@ -36,6 +36,51 @@
///////////////////////// UTILITY FUNCTIONS /////////////////////////
+// Test request validation with reusable execution.
+static void validateReusableExecution(const std::shared_ptr<IPreparedModel>& preparedModel,
+ const std::string& message, const Request& request,
+ bool measure) {
+ // createReusableExecution
+ std::shared_ptr<IExecution> execution;
+ {
+ SCOPED_TRACE(message + " [createReusableExecution]");
+ const auto createStatus = preparedModel->createReusableExecution(
+ request, {measure, kOmittedTimeoutDuration, {}, {}}, &execution);
+ if (!createStatus.isOk()) {
+ ASSERT_EQ(createStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(createStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ ASSERT_EQ(nullptr, execution);
+ return;
+ } else {
+ ASSERT_NE(nullptr, execution);
+ }
+ }
+
+ // synchronous
+ {
+ SCOPED_TRACE(message + " [executeSynchronously]");
+ ExecutionResult executionResult;
+ const auto executeStatus = execution->executeSynchronously(kNoDeadline, &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
+
+ // fenced
+ {
+ SCOPED_TRACE(message + " [executeFenced]");
+ FencedExecutionResult executionResult;
+ const auto executeStatus =
+ execution->executeFenced({}, kNoDeadline, kNoDuration, &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
+}
+
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
// that use the request.
@@ -101,6 +146,63 @@
ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
ErrorStatus::INVALID_ARGUMENT);
}
+
+ int32_t aidlVersion;
+ ASSERT_TRUE(preparedModel->getInterfaceVersion(&aidlVersion).isOk());
+ if (aidlVersion < kMinAidlLevelForFL8) {
+ return;
+ }
+
+ // validate reusable execution
+ validateReusableExecution(preparedModel, message, request, measure);
+
+ // synchronous with empty hints
+ {
+ SCOPED_TRACE(message + " [executeSynchronouslyWithConfig]");
+ ExecutionResult executionResult;
+ const auto executeStatus = preparedModel->executeSynchronouslyWithConfig(
+ request, {measure, kOmittedTimeoutDuration, {}, {}}, kNoDeadline, &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
+
+ // fenced with empty hints
+ {
+ SCOPED_TRACE(message + " [executeFencedWithConfig]");
+ FencedExecutionResult executionResult;
+ const auto executeStatus = preparedModel->executeFencedWithConfig(
+ request, {}, {false, kOmittedTimeoutDuration, {}, {}}, kNoDeadline, kNoDuration,
+ &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
+
+ // burst with empty hints
+ {
+ SCOPED_TRACE(message + " [burst executeSynchronouslyWithConfig]");
+
+ // create burst
+ std::shared_ptr<IBurst> burst;
+ auto ret = preparedModel->configureExecutionBurst(&burst);
+ ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+ ASSERT_NE(nullptr, burst.get());
+
+ // use -1 for all memory identifier tokens
+ const std::vector<int64_t> slots(request.pools.size(), -1);
+
+ ExecutionResult executionResult;
+ const auto executeStatus = burst->executeSynchronouslyWithConfig(
+ request, slots, {measure, kOmittedTimeoutDuration, {}, {}}, kNoDeadline,
+ &executionResult);
+ ASSERT_FALSE(executeStatus.isOk());
+ ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+ ErrorStatus::INVALID_ARGUMENT);
+ }
}
std::shared_ptr<IBurst> createBurst(const std::shared_ptr<IPreparedModel>& preparedModel) {
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index c417356..bf87f15 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "neuralnetworks_aidl_hal_test"
+
#include "VtsHalNeuralnetworks.h"
#include <android-base/logging.h>
@@ -28,20 +29,27 @@
#include <utility>
#include <TestHarness.h>
-#include <aidl/Vintf.h>
#include <nnapi/hal/aidl/Conversions.h>
#include "Callbacks.h"
#include "GeneratedTestHarness.h"
#include "Utils.h"
+#ifdef __ANDROID__
+#include <aidl/Vintf.h>
+#else // __ANDROID__
+#include <CanonicalDevice.h>
+#include <nnapi/hal/aidl/Adapter.h>
+#endif // __ANDROID__
+
namespace aidl::android::hardware::neuralnetworks::vts::functional {
using implementation::PreparedModelCallback;
// internal helper function
void createPreparedModel(const std::shared_ptr<IDevice>& device, const Model& model,
- std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping) {
+ std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping,
+ bool useConfig) {
ASSERT_NE(nullptr, preparedModel);
*preparedModel = nullptr;
@@ -56,11 +64,25 @@
// launch prepare model
const std::shared_ptr<PreparedModelCallback> preparedModelCallback =
ndk::SharedRefBase::make<PreparedModelCallback>();
- const auto prepareLaunchStatus =
- device->prepareModel(model, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority,
- kNoDeadline, {}, {}, kEmptyCacheToken, preparedModelCallback);
- ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
-
+ if (useConfig) {
+ const auto prepareLaunchStatus =
+ device->prepareModelWithConfig(model,
+ {ExecutionPreference::FAST_SINGLE_ANSWER,
+ kDefaultPriority,
+ kNoDeadline,
+ {},
+ {},
+ kEmptyCacheTokenArray,
+ {},
+ {}},
+ preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
+ } else {
+ const auto prepareLaunchStatus = device->prepareModel(
+ model, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority, kNoDeadline, {},
+ {}, kEmptyCacheToken, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
+ }
// retrieve prepared model
preparedModelCallback->wait();
const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
@@ -96,6 +118,7 @@
ASSERT_TRUE(deviceIsResponsive);
}
+#ifdef __ANDROID__
static NamedDevice makeNamedDevice(const std::string& name) {
ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
return {name, IDevice::fromBinder(binder)};
@@ -112,6 +135,14 @@
std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
return namedDevices;
}
+#else // __ANDROID__
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+ const std::string name = "nnapi-sample";
+ auto device = std::make_shared<const ::android::nn::sample::Device>(name);
+ auto aidlDevice = adapter::adapt(device);
+ return {{name, aidlDevice}};
+}
+#endif // __ANDROID__
const std::vector<NamedDevice>& getNamedDevices() {
const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
index 4312d3a..00d705c 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
@@ -30,6 +30,8 @@
using NamedDevice = Named<std::shared_ptr<IDevice>>;
using NeuralNetworksAidlTestParam = NamedDevice;
+constexpr int kMinAidlLevelForFL8 = 4;
+
class NeuralNetworksAidlTest : public testing::TestWithParam<NeuralNetworksAidlTestParam> {
protected:
void SetUp() override;
@@ -49,8 +51,8 @@
// Create an IPreparedModel object. If the model cannot be prepared,
// "preparedModel" will be nullptr instead.
void createPreparedModel(const std::shared_ptr<IDevice>& device, const Model& model,
- std::shared_ptr<IPreparedModel>* preparedModel,
- bool reportSkipping = true);
+ std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping = true,
+ bool useConfig = false);
enum class Executor { SYNC, BURST, FENCED };
diff --git a/neuralnetworks/utils/adapter/Android.bp b/neuralnetworks/utils/adapter/Android.bp
deleted file mode 100644
index d073106..0000000
--- a/neuralnetworks/utils/adapter/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_library_static {
- name: "neuralnetworks_utils_hal_adapter",
- 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",
- ],
- shared_libs: [
- "android.hardware.neuralnetworks@1.0",
- "android.hardware.neuralnetworks@1.1",
- "android.hardware.neuralnetworks@1.2",
- "android.hardware.neuralnetworks@1.3",
- "libfmq",
- ],
-}
diff --git a/neuralnetworks/utils/adapter/aidl/Android.bp b/neuralnetworks/utils/adapter/aidl/Android.bp
new file mode 100644
index 0000000..8269a3d
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_adapter_aidl",
+ defaults: [
+ "neuralnetworks_use_latest_utils_hal_aidl",
+ "neuralnetworks_utils_defaults",
+ ],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal/aidl/"],
+ export_include_dirs: ["include"],
+ static_libs: [
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_common",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+}
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
new file mode 100644
index 0000000..80ed41d
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ADAPTER_AIDL_ADAPTER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_ADAPTER_H
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+/**
+ * A self-contained unit of work to be executed.
+ */
+using Task = std::function<void()>;
+
+/**
+ * A type-erased executor which executes a task asynchronously.
+ *
+ * This executor is also provided an optional deadline for when the caller expects is the upper
+ * bound for the amount of time to complete the task. If needed, the Executor can retrieve the
+ * Application ID (Android User ID) by calling AIBinder_getCallingUid in android/binder_ibinder.h.
+ */
+using Executor = std::function<void(Task, ::android::nn::OptionalTimePoint)>;
+
+/**
+ * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @param executor Type-erased executor to handle executing tasks asynchronously.
+ * @return AIDL NN HAL IDevice interface object.
+ */
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device, Executor executor);
+
+/**
+ * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
+ *
+ * This function uses a default executor, which will execute tasks from a detached thread.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @return AIDL NN HAL IDevice interface object.
+ */
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device);
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h
new file mode 100644
index 0000000..701e43e
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ADAPTER_AIDL_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BUFFER_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBuffer.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IBuffer to BnBuffer.
+class Buffer : public BnBuffer {
+ public:
+ explicit Buffer(::android::nn::SharedBuffer buffer);
+
+ ndk::ScopedAStatus copyFrom(const Memory& src, const std::vector<int32_t>& dimensions) override;
+ ndk::ScopedAStatus copyTo(const Memory& dst) override;
+
+ private:
+ const ::android::nn::SharedBuffer kBuffer;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BUFFER_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
new file mode 100644
index 0000000..8d42e2f
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ADAPTER_AIDL_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BURST_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBurst.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::Burst to BnBurst.
+class Burst : public BnBurst {
+ public:
+ // Precondition: burst != nullptr
+ explicit Burst(::android::nn::SharedBurst burst);
+
+ ndk::ScopedAStatus executeSynchronously(const Request& request,
+ const std::vector<int64_t>& memoryIdentifierTokens,
+ bool measureTiming, int64_t deadlineNs,
+ int64_t loopTimeoutDurationNs,
+ ExecutionResult* executionResult) override;
+ ndk::ScopedAStatus executeSynchronouslyWithConfig(
+ const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+ const ExecutionConfig& config, int64_t deadlineNs,
+ ExecutionResult* executionResult) override;
+
+ ndk::ScopedAStatus releaseMemoryResource(int64_t memoryIdentifierToken) override;
+
+ class ThreadSafeMemoryCache {
+ public:
+ using Value =
+ std::pair<::android::nn::SharedMemory, ::android::nn::IBurst::OptionalCacheHold>;
+
+ Value add(int64_t token, const ::android::nn::SharedMemory& memory,
+ const ::android::nn::IBurst& burst) const;
+ void remove(int64_t token) const;
+
+ private:
+ mutable std::mutex mMutex;
+ mutable std::unordered_map<int64_t, Value> mCache GUARDED_BY(mMutex);
+ };
+
+ private:
+ const ::android::nn::SharedBurst kBurst;
+ const ThreadSafeMemoryCache kMemoryCache;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BURST_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
new file mode 100644
index 0000000..c94f270
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ADAPTER_AIDL_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_DEVICE_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/Capabilities.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/PrepareModelConfig.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IDevice.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IDevice to BnDevice.
+class Device : public BnDevice {
+ public:
+ Device(::android::nn::SharedDevice device, Executor executor);
+
+ ndk::ScopedAStatus allocate(const BufferDesc& desc,
+ const std::vector<IPreparedModelParcel>& preparedModels,
+ const std::vector<BufferRole>& inputRoles,
+ const std::vector<BufferRole>& outputRoles,
+ DeviceBuffer* buffer) override;
+ ndk::ScopedAStatus getCapabilities(Capabilities* capabilities) override;
+ ndk::ScopedAStatus getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) override;
+ ndk::ScopedAStatus getSupportedExtensions(std::vector<Extension>* extensions) override;
+ ndk::ScopedAStatus getSupportedOperations(const Model& model,
+ std::vector<bool>* supported) override;
+ ndk::ScopedAStatus getType(DeviceType* deviceType) override;
+ ndk::ScopedAStatus getVersionString(std::string* version) override;
+ ndk::ScopedAStatus prepareModel(
+ const Model& model, ExecutionPreference preference, Priority priority,
+ int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
+ ndk::ScopedAStatus prepareModelFromCache(
+ int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
+ ndk::ScopedAStatus prepareModelWithConfig(
+ const Model& model, const PrepareModelConfig& config,
+ const std::shared_ptr<IPreparedModelCallback>& callback) override;
+
+ protected:
+ const ::android::nn::SharedDevice kDevice;
+ const Executor kExecutor;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_DEVICE_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.h
new file mode 100644
index 0000000..6a9ac57
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IExecution to BnExecution.
+class Execution : public BnExecution {
+ public:
+ explicit Execution(::android::nn::SharedExecution execution);
+
+ ndk::ScopedAStatus executeSynchronously(int64_t deadlineNs,
+ ExecutionResult* executionResult) override;
+ ndk::ScopedAStatus executeFenced(const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ int64_t deadlineNs, int64_t durationNs,
+ FencedExecutionResult* fencedExecutionResult) override;
+
+ protected:
+ const ::android::nn::SharedExecution kExecution;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
new file mode 100644
index 0000000..d1359d6
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ADAPTER_AIDL_PREPARED_MDOEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_PREPARED_MDOEL_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IBurst.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IPreparedModel to BnPreparedModel.
+class PreparedModel : public BnPreparedModel {
+ public:
+ explicit PreparedModel(::android::nn::SharedPreparedModel preparedModel);
+
+ ndk::ScopedAStatus executeSynchronously(const Request& request, bool measureTiming,
+ int64_t deadlineNs, int64_t loopTimeoutDurationNs,
+ ExecutionResult* executionResult) override;
+ ndk::ScopedAStatus executeFenced(const Request& request,
+ const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ bool measureTiming, int64_t deadlineNs,
+ int64_t loopTimeoutDurationNs, int64_t durationNs,
+ FencedExecutionResult* executionResult) override;
+ ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>* burst) override;
+ ndk::ScopedAStatus createReusableExecution(const Request& request,
+ const ExecutionConfig& config,
+ std::shared_ptr<IExecution>* execution) override;
+ ndk::ScopedAStatus executeSynchronouslyWithConfig(const Request& request,
+ const ExecutionConfig& config,
+ int64_t deadlineNs,
+ ExecutionResult* executionResult) override;
+ ndk::ScopedAStatus executeFencedWithConfig(
+ const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ const ExecutionConfig& config, int64_t deadlineNs, int64_t durationNs,
+ FencedExecutionResult* executionResult) override;
+
+ ::android::nn::SharedPreparedModel getUnderlyingPreparedModel() const;
+
+ protected:
+ const ::android::nn::SharedPreparedModel kPreparedModel;
+};
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_PREPARED_MDOEL_H
diff --git a/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp b/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp
new file mode 100644
index 0000000..d0b56e8
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Adapter.h"
+
+#include "Device.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <android/binder_interface_utils.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device, Executor executor) {
+ return ndk::SharedRefBase::make<Device>(std::move(device), std::move(executor));
+}
+
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device) {
+ Executor defaultExecutor = [](Task task, ::android::nn::OptionalTimePoint /*deadline*/) {
+ std::thread(std::move(task)).detach();
+ };
+ return adapt(std::move(device), std::move(defaultExecutor));
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp b/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp
new file mode 100644
index 0000000..c15ab65
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+nn::GeneralResult<std::vector<uint32_t>> inputToUnsigned(const std::vector<int32_t>& dims) {
+ auto result = nn::toUnsigned(dims);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+nn::GeneralResult<void> copyTo(const nn::IBuffer& buffer, const Memory& dst) {
+ const auto nnDst = NN_TRY(convertInput(dst));
+ return buffer.copyTo(nnDst);
+}
+
+nn::GeneralResult<void> copyFrom(const nn::IBuffer& buffer, const Memory& src,
+ const std::vector<int32_t>& dimensions) {
+ const auto nnSrc = NN_TRY(convertInput(src));
+ const auto nnDims = NN_TRY(inputToUnsigned(dimensions));
+ return buffer.copyFrom(nnSrc, nnDims);
+}
+
+} // namespace
+
+Buffer::Buffer(nn::SharedBuffer buffer) : kBuffer(std::move(buffer)) {
+ CHECK(kBuffer != nullptr);
+}
+
+ndk::ScopedAStatus Buffer::copyTo(const Memory& dst) {
+ const auto result = adapter::copyTo(*kBuffer, dst);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Buffer::copyFrom(const Memory& src, const std::vector<int32_t>& dimensions) {
+ const auto result = adapter::copyFrom(*kBuffer, src, dimensions);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Burst.cpp b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
new file mode 100644
index 0000000..a4a80fa
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Burst.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/Utils.h>
+
+#include <algorithm>
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <utility>
+#include <variant>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+using Value = Burst::ThreadSafeMemoryCache::Value;
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+ return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalDuration> makeOptionalDuration(int64_t durationNs) {
+ if (durationNs < -1) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid duration " << durationNs;
+ }
+ return durationNs < 0 ? nn::OptionalDuration{} : makeDuration(durationNs);
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+ if (durationNs < -1) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+ }
+ return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+std::vector<nn::IBurst::OptionalCacheHold> ensureAllMemoriesAreCached(
+ nn::Request* request, const std::vector<int64_t>& memoryIdentifierTokens,
+ const nn::IBurst& burst, const Burst::ThreadSafeMemoryCache& cache) {
+ std::vector<nn::IBurst::OptionalCacheHold> holds;
+ holds.reserve(memoryIdentifierTokens.size());
+
+ for (size_t i = 0; i < memoryIdentifierTokens.size(); ++i) {
+ const auto& pool = request->pools[i];
+ const auto token = memoryIdentifierTokens[i];
+ constexpr int64_t kNoToken = -1;
+ if (token == kNoToken || !std::holds_alternative<nn::SharedMemory>(pool)) {
+ continue;
+ }
+
+ const auto& memory = std::get<nn::SharedMemory>(pool);
+ auto [storedMemory, hold] = cache.add(token, memory, burst);
+
+ request->pools[i] = std::move(storedMemory);
+ holds.push_back(std::move(hold));
+ }
+
+ return holds;
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(
+ const nn::IBurst& burst, const Burst::ThreadSafeMemoryCache& cache, const Request& request,
+ const std::vector<int64_t>& memoryIdentifierTokens, bool measureTiming, int64_t deadlineNs,
+ int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+ const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+ if (request.pools.size() != memoryIdentifierTokens.size()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+ << "request.pools.size() != memoryIdentifierTokens.size()";
+ }
+ if (!std::all_of(memoryIdentifierTokens.begin(), memoryIdentifierTokens.end(),
+ [](int64_t token) { return token >= -1; })) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid memoryIdentifierTokens";
+ }
+
+ auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+ auto nnHints = NN_TRY(convertInput(hints));
+ auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+ const auto hold = ensureAllMemoriesAreCached(&nnRequest, memoryIdentifierTokens, burst, cache);
+
+ const auto result = burst.execute(nnRequest, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration,
+ nnHints, nnExtensionNameToPrefix);
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ const auto& [message, code, outputShapes] = result.error();
+ return ExecutionResult{.outputSufficientSize = false,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+ }
+
+ const auto& [outputShapes, timing] = NN_TRY(result);
+ return ExecutionResult{.outputSufficientSize = true,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = utils::convert(timing).value()};
+}
+
+} // namespace
+
+Value Burst::ThreadSafeMemoryCache::add(int64_t token, const nn::SharedMemory& memory,
+ const nn::IBurst& burst) const {
+ std::lock_guard guard(mMutex);
+ if (const auto it = mCache.find(token); it != mCache.end()) {
+ return it->second;
+ }
+ auto hold = burst.cacheMemory(memory);
+ auto [it, _] = mCache.emplace(token, std::make_pair(memory, std::move(hold)));
+ return it->second;
+}
+
+void Burst::ThreadSafeMemoryCache::remove(int64_t token) const {
+ std::lock_guard guard(mMutex);
+ mCache.erase(token);
+}
+
+Burst::Burst(nn::SharedBurst burst) : kBurst(std::move(burst)) {
+ CHECK(kBurst != nullptr);
+}
+
+ndk::ScopedAStatus Burst::executeSynchronously(const Request& request,
+ const std::vector<int64_t>& memoryIdentifierTokens,
+ bool measureTiming, int64_t deadlineNs,
+ int64_t loopTimeoutDurationNs,
+ ExecutionResult* executionResult) {
+ auto result =
+ adapter::executeSynchronously(*kBurst, kMemoryCache, request, memoryIdentifierTokens,
+ measureTiming, deadlineNs, loopTimeoutDurationNs, {}, {});
+ if (!result.has_value()) {
+ auto [message, code, _] = std::move(result).error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Burst::executeSynchronouslyWithConfig(
+ const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+ const ExecutionConfig& config, int64_t deadlineNs, ExecutionResult* executionResult) {
+ auto result = adapter::executeSynchronously(
+ *kBurst, kMemoryCache, request, memoryIdentifierTokens, config.measureTiming,
+ deadlineNs, config.loopTimeoutDurationNs, config.executionHints,
+ config.extensionNameToPrefix);
+ if (!result.has_value()) {
+ auto [message, code, _] = std::move(result).error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Burst::releaseMemoryResource(int64_t memoryIdentifierToken) {
+ if (memoryIdentifierToken < -1) {
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(ErrorStatus::INVALID_ARGUMENT),
+ "Invalid memoryIdentifierToken");
+ }
+ kMemoryCache.remove(memoryIdentifierToken);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Device.cpp b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
new file mode 100644
index 0000000..1b90a1a
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Adapter.h"
+#include "Buffer.h"
+#include "PreparedModel.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <chrono>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+ return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+ if (durationNs < -1) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+ }
+ return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+nn::GeneralResult<nn::CacheToken> convertCacheToken(const std::vector<uint8_t>& token) {
+ nn::CacheToken nnToken;
+ if (token.size() != nnToken.size()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid token";
+ }
+ std::copy(token.begin(), token.end(), nnToken.begin());
+ return nnToken;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> downcast(const IPreparedModelParcel& preparedModel) {
+ if (preparedModel.preparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
+ }
+ if (preparedModel.preparedModel->isRemote()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
+ }
+
+ // This static_cast is safe because adapter::PreparedModel is the only class that implements
+ // the IPreparedModel interface in the adapter service code.
+ const auto* casted = static_cast<const PreparedModel*>(preparedModel.preparedModel.get());
+ return casted->getUnderlyingPreparedModel();
+}
+
+nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
+ const std::vector<IPreparedModelParcel>& preparedModels) {
+ std::vector<nn::SharedPreparedModel> canonical;
+ canonical.reserve(preparedModels.size());
+ for (const auto& preparedModel : preparedModels) {
+ canonical.push_back(NN_TRY(downcast(preparedModel)));
+ }
+ return canonical;
+}
+
+nn::GeneralResult<DeviceBuffer> allocate(const nn::IDevice& device, const BufferDesc& desc,
+ const std::vector<IPreparedModelParcel>& preparedModels,
+ const std::vector<BufferRole>& inputRoles,
+ const std::vector<BufferRole>& outputRoles) {
+ auto nnDesc = NN_TRY(convertInput(desc));
+ auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
+ auto nnInputRoles = NN_TRY(convertInput(inputRoles));
+ auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
+
+ auto buffer = NN_TRY(device.allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
+ CHECK(buffer != nullptr);
+
+ const nn::Request::MemoryDomainToken token = buffer->getToken();
+ auto aidlBuffer = ndk::SharedRefBase::make<Buffer>(std::move(buffer));
+ return DeviceBuffer{.buffer = std::move(aidlBuffer), .token = static_cast<int32_t>(token)};
+}
+
+nn::GeneralResult<std::vector<bool>> getSupportedOperations(const nn::IDevice& device,
+ const Model& model) {
+ const auto nnModel = NN_TRY(convertInput(model));
+ return device.getSupportedOperations(nnModel);
+}
+
+using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
+
+std::shared_ptr<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel) {
+ if (preparedModel == nullptr) {
+ return nullptr;
+ }
+ return ndk::SharedRefBase::make<PreparedModel>(std::move(preparedModel));
+}
+
+void notify(IPreparedModelCallback* callback, PrepareModelResult result) {
+ if (!result.has_value()) {
+ const auto& [message, status] = result.error();
+ LOG(ERROR) << message;
+ const auto aidlCode = utils::convert(status).value_or(ErrorStatus::GENERAL_FAILURE);
+ callback->notify(aidlCode, nullptr);
+ } else {
+ auto preparedModel = std::move(result).value();
+ auto aidlPreparedModel = adaptPreparedModel(std::move(preparedModel));
+ callback->notify(ErrorStatus::NONE, std::move(aidlPreparedModel));
+ }
+}
+
+nn::GeneralResult<void> prepareModel(
+ const nn::SharedDevice& device, const Executor& executor, const Model& model,
+ ExecutionPreference preference, Priority priority, int64_t deadlineNs,
+ const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModel = NN_TRY(convertInput(model));
+ const auto nnPreference = NN_TRY(convertInput(preference));
+ const auto nnPriority = NN_TRY(convertInput(priority));
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = NN_TRY(convertCacheToken(token));
+ auto nnHints = NN_TRY(convertInput(hints));
+ auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+ Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
+ nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+ nnToken, nnHints = std::move(nnHints),
+ nnExtensionNameToPrefix = std::move(nnExtensionNameToPrefix), callback] {
+ auto result =
+ device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline, nnModelCache,
+ nnDataCache, nnToken, nnHints, nnExtensionNameToPrefix);
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), nnDeadline);
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache(
+ const nn::SharedDevice& device, const Executor& executor, int64_t deadlineNs,
+ const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = NN_TRY(convertCacheToken(token));
+
+ auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
+ nnDataCache = std::move(nnDataCache), nnToken, callback] {
+ auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), nnDeadline);
+
+ return {};
+}
+
+} // namespace
+
+Device::Device(::android::nn::SharedDevice device, Executor executor)
+ : kDevice(std::move(device)), kExecutor(std::move(executor)) {
+ CHECK(kDevice != nullptr);
+ CHECK(kExecutor != nullptr);
+}
+
+ndk::ScopedAStatus Device::allocate(const BufferDesc& desc,
+ const std::vector<IPreparedModelParcel>& preparedModels,
+ const std::vector<BufferRole>& inputRoles,
+ const std::vector<BufferRole>& outputRoles,
+ DeviceBuffer* buffer) {
+ auto result = adapter::allocate(*kDevice, desc, preparedModels, inputRoles, outputRoles);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *buffer = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getCapabilities(Capabilities* capabilities) {
+ *capabilities = utils::convert(kDevice->getCapabilities()).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) {
+ const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
+ *numberOfCacheFiles = NumberOfCacheFiles{.numModelCache = static_cast<int32_t>(numModelCache),
+ .numDataCache = static_cast<int32_t>(numDataCache)};
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getSupportedExtensions(std::vector<Extension>* extensions) {
+ *extensions = utils::convert(kDevice->getSupportedExtensions()).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getSupportedOperations(const Model& model,
+ std::vector<bool>* supported) {
+ auto result = adapter::getSupportedOperations(*kDevice, model);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *supported = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getType(DeviceType* deviceType) {
+ *deviceType = utils::convert(kDevice->getType()).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getVersionString(std::string* version) {
+ *version = kDevice->getVersionString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModel(const Model& model, ExecutionPreference preference,
+ Priority priority, int64_t deadlineNs,
+ const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ const auto result =
+ adapter::prepareModel(kDevice, kExecutor, model, preference, priority, deadlineNs,
+ modelCache, dataCache, token, {}, {}, callback);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ callback->notify(aidlCode, nullptr);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModelFromCache(
+ int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ const auto result = adapter::prepareModelFromCache(kDevice, kExecutor, deadlineNs, modelCache,
+ dataCache, token, callback);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ callback->notify(aidlCode, nullptr);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModelWithConfig(
+ const Model& model, const PrepareModelConfig& config,
+ const std::shared_ptr<IPreparedModelCallback>& callback) {
+ const auto result = adapter::prepareModel(
+ kDevice, kExecutor, model, config.preference, config.priority, config.deadlineNs,
+ config.modelCache, config.dataCache, utils::toVec(config.cacheToken),
+ config.compilationHints, config.extensionNameToPrefix, callback);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ callback->notify(aidlCode, nullptr);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
new file mode 100644
index 0000000..790558f
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Burst.h"
+#include "Execution.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IBurst.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/Utils.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+class FencedExecutionCallback : public BnFencedExecutionCallback {
+ public:
+ FencedExecutionCallback(nn::ExecuteFencedInfoCallback callback)
+ : kCallback(std::move(callback)) {}
+
+ ndk::ScopedAStatus getExecutionInfo(Timing* timingLaunched, Timing* timingFenced,
+ ErrorStatus* errorStatus) override {
+ const auto result = kCallback();
+ if (result.ok()) {
+ const auto& [nnTimingLaunched, nnTimingFenced] = result.value();
+ *timingLaunched = utils::convert(nnTimingLaunched).value();
+ *timingFenced = utils::convert(nnTimingFenced).value();
+ *errorStatus = ErrorStatus::NONE;
+ } else {
+ constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
+ const auto& [message, code] = result.error();
+ LOG(ERROR) << "getExecutionInfo failed with " << code << ": " << message;
+ const auto aidlStatus = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ *timingLaunched = kNoTiming;
+ *timingFenced = kNoTiming;
+ *errorStatus = aidlStatus;
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+
+ private:
+ const nn::ExecuteFencedInfoCallback kCallback;
+};
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
+ const std::vector<ndk::ScopedFileDescriptor>& waitFor) {
+ auto handles = NN_TRY(convertInput(waitFor));
+
+ constexpr auto valid = [](const nn::SharedHandle& handle) {
+ return handle != nullptr && handle->ok();
+ };
+ if (!std::all_of(handles.begin(), handles.end(), valid)) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid sync fence";
+ }
+
+ std::vector<nn::SyncFence> syncFences;
+ syncFences.reserve(waitFor.size());
+ for (auto& handle : handles) {
+ syncFences.push_back(nn::SyncFence::create(std::move(handle)).value());
+ }
+ return syncFences;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+ return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalDuration> makeOptionalDuration(int64_t durationNs) {
+ if (durationNs < -1) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid duration " << durationNs;
+ }
+ return durationNs < 0 ? nn::OptionalDuration{} : makeDuration(durationNs);
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+ if (durationNs < -1) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+ }
+ return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(
+ const nn::IPreparedModel& preparedModel, const Request& request, bool measureTiming,
+ int64_t deadlineNs, int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+ const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+ auto nnHints = NN_TRY(convertInput(hints));
+ auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+ const auto result =
+ preparedModel.execute(nnRequest, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration,
+ nnHints, nnExtensionNameToPrefix);
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ const auto& [message, code, outputShapes] = result.error();
+ LOG(ERROR) << "executeSynchronously failed with " << code << ": " << message;
+ return ExecutionResult{.outputSufficientSize = false,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+ }
+
+ const auto& [outputShapes, timing] = NN_TRY(result);
+ return ExecutionResult{.outputSufficientSize = true,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = utils::convert(timing).value()};
+}
+
+nn::GeneralResult<FencedExecutionResult> executeFenced(
+ const nn::IPreparedModel& preparedModel, const Request& request,
+ const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measureTiming,
+ int64_t deadlineNs, int64_t loopTimeoutDurationNs, int64_t durationNs,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+ const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+ const auto nnDuration = NN_TRY(makeOptionalDuration(durationNs));
+ auto nnHints = NN_TRY(convertInput(hints));
+ auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+ auto [syncFence, executeFencedInfoCallback] = NN_TRY(preparedModel.executeFenced(
+ nnRequest, nnWaitFor, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration, nnDuration,
+ nnHints, nnExtensionNameToPrefix));
+
+ ndk::ScopedFileDescriptor fileDescriptor;
+ if (syncFence.hasFd()) {
+ auto uniqueFd = NN_TRY(nn::dupFd(syncFence.getFd()));
+ fileDescriptor = ndk::ScopedFileDescriptor(uniqueFd.release());
+ }
+
+ return FencedExecutionResult{.callback = ndk::SharedRefBase::make<FencedExecutionCallback>(
+ std::move(executeFencedInfoCallback)),
+ .syncFence = std::move(fileDescriptor)};
+}
+
+nn::GeneralResult<nn::SharedExecution> createReusableExecution(
+ const nn::IPreparedModel& preparedModel, const Request& request, bool measureTiming,
+ int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+ const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+ const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+ auto nnHints = NN_TRY(convertInput(hints));
+ auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+ return preparedModel.createReusableExecution(nnRequest, nnMeasureTiming, nnLoopTimeoutDuration,
+ nnHints, nnExtensionNameToPrefix);
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(const nn::IExecution& execution,
+ int64_t deadlineNs) {
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+
+ const auto result = execution.compute(nnDeadline);
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ const auto& [message, code, outputShapes] = result.error();
+ LOG(ERROR) << "executeSynchronously failed with " << code << ": " << message;
+ return ExecutionResult{.outputSufficientSize = false,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+ }
+
+ const auto& [outputShapes, timing] = NN_TRY(result);
+ return ExecutionResult{.outputSufficientSize = true,
+ .outputShapes = utils::convert(outputShapes).value(),
+ .timing = utils::convert(timing).value()};
+}
+
+nn::GeneralResult<FencedExecutionResult> executeFenced(
+ const nn::IExecution& execution, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ int64_t deadlineNs, int64_t durationNs) {
+ const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+ const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+ const auto nnDuration = NN_TRY(makeOptionalDuration(durationNs));
+
+ auto [syncFence, executeFencedInfoCallback] =
+ NN_TRY(execution.computeFenced(nnWaitFor, nnDeadline, nnDuration));
+
+ ndk::ScopedFileDescriptor fileDescriptor;
+ if (syncFence.hasFd()) {
+ auto uniqueFd = NN_TRY(nn::dupFd(syncFence.getFd()));
+ fileDescriptor = ndk::ScopedFileDescriptor(uniqueFd.release());
+ }
+
+ return FencedExecutionResult{.callback = ndk::SharedRefBase::make<FencedExecutionCallback>(
+ std::move(executeFencedInfoCallback)),
+ .syncFence = std::move(fileDescriptor)};
+}
+
+} // namespace
+
+PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel)
+ : kPreparedModel(std::move(preparedModel)) {
+ CHECK(kPreparedModel != nullptr);
+}
+
+ndk::ScopedAStatus PreparedModel::executeSynchronously(const Request& request, bool measureTiming,
+ int64_t deadlineNs,
+ int64_t loopTimeoutDurationNs,
+ ExecutionResult* executionResult) {
+ auto result = adapter::executeSynchronously(*kPreparedModel, request, measureTiming, deadlineNs,
+ loopTimeoutDurationNs, {}, {});
+ if (!result.has_value()) {
+ const auto& [message, code, _] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeFenced(
+ const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ bool measureTiming, int64_t deadlineNs, int64_t loopTimeoutDurationNs, int64_t durationNs,
+ FencedExecutionResult* executionResult) {
+ auto result = adapter::executeFenced(*kPreparedModel, request, waitFor, measureTiming,
+ deadlineNs, loopTimeoutDurationNs, durationNs, {}, {});
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeSynchronouslyWithConfig(const Request& request,
+ const ExecutionConfig& config,
+ int64_t deadlineNs,
+ ExecutionResult* executionResult) {
+ auto result = adapter::executeSynchronously(
+ *kPreparedModel, request, config.measureTiming, deadlineNs,
+ config.loopTimeoutDurationNs, config.executionHints, config.extensionNameToPrefix);
+ if (!result.has_value()) {
+ const auto& [message, code, _] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeFencedWithConfig(
+ const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ const ExecutionConfig& config, int64_t deadlineNs, int64_t durationNs,
+ FencedExecutionResult* executionResult) {
+ auto result = adapter::executeFenced(*kPreparedModel, request, waitFor, config.measureTiming,
+ deadlineNs, config.loopTimeoutDurationNs, durationNs,
+ config.executionHints, config.extensionNameToPrefix);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::configureExecutionBurst(std::shared_ptr<IBurst>* burst) {
+ auto result = kPreparedModel->configureExecutionBurst();
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *burst = ndk::SharedRefBase::make<Burst>(std::move(result).value());
+ return ndk::ScopedAStatus::ok();
+}
+
+nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
+ return kPreparedModel;
+}
+
+ndk::ScopedAStatus PreparedModel::createReusableExecution(const Request& request,
+ const ExecutionConfig& config,
+ std::shared_ptr<IExecution>* execution) {
+ auto result = adapter::createReusableExecution(
+ *kPreparedModel, request, config.measureTiming, config.loopTimeoutDurationNs,
+ config.executionHints, config.extensionNameToPrefix);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *execution = ndk::SharedRefBase::make<Execution>(std::move(result).value());
+ return ndk::ScopedAStatus::ok();
+}
+
+Execution::Execution(nn::SharedExecution execution) : kExecution(std::move(execution)) {
+ CHECK(kExecution != nullptr);
+}
+
+ndk::ScopedAStatus Execution::executeSynchronously(int64_t deadlineNs,
+ ExecutionResult* executionResult) {
+ auto result = adapter::executeSynchronously(*kExecution, deadlineNs);
+ if (!result.has_value()) {
+ const auto& [message, code, _] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Execution::executeFenced(const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+ int64_t deadlineNs, int64_t durationNs,
+ FencedExecutionResult* executionResult) {
+ auto result = adapter::executeFenced(*kExecution, waitFor, deadlineNs, durationNs);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(aidlCode), message.c_str());
+ }
+ *executionResult = std::move(result).value();
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/Android.bp b/neuralnetworks/utils/adapter/hidl/Android.bp
new file mode 100644
index 0000000..6875daa
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/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.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "neuralnetworks_utils_hal_adapter",
+ defaults: ["neuralnetworks_utils_defaults"],
+ srcs: ["src/*"],
+ local_include_dirs: ["include/nnapi/hal"],
+ export_include_dirs: ["include"],
+ static_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ "libfmq",
+ "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",
+ ],
+}
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
new file mode 100644
index 0000000..3bd93e0
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.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_UTILS_ADAPTER_ADAPTER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
+
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+#include <functional>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+/**
+ * A self-contained unit of work to be executed.
+ */
+using Task = std::function<void()>;
+
+/**
+ * A type-erased executor which executes a task asynchronously.
+ *
+ * This executor is also provided an optional deadline for when the caller expects is the upper
+ * bound for the amount of time to complete the task. If needed, the Executor can retrieve the
+ * Application ID (Android User ID) by calling IPCThreadState::self()->getCallingUid() in
+ * hwbinder/IPCThreadState.h.
+ */
+using Executor = std::function<void(Task, nn::OptionalTimePoint)>;
+
+/**
+ * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @param executor Type-erased executor to handle executing tasks asynchronously.
+ * @return HIDL NN HAL IDevice interface object.
+ */
+sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor);
+
+/**
+ * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
+ *
+ * This function uses a default executor, which will execute tasks from a detached thread.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @return HIDL NN HAL IDevice interface object.
+ */
+sp<V1_3::IDevice> adapt(nn::SharedDevice device);
+
+} // namespace android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Buffer.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Buffer.h
similarity index 100%
rename from neuralnetworks/utils/adapter/include/nnapi/hal/Buffer.h
rename to neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Buffer.h
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Burst.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Burst.h
similarity index 100%
rename from neuralnetworks/utils/adapter/include/nnapi/hal/Burst.h
rename to neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Burst.h
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Device.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Device.h
similarity index 100%
rename from neuralnetworks/utils/adapter/include/nnapi/hal/Device.h
rename to neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Device.h
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
new file mode 100644
index 0000000..01cd4bc
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.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_UTILS_ADAPTER_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
+
+#include "nnapi/hal/Adapter.h"
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Types.h>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IPreparedModel to V1_3::IPreparedModel.
+class PreparedModel final : public V1_3::IPreparedModel {
+ public:
+ explicit PreparedModel(nn::SharedPreparedModel preparedModel);
+
+ Return<V1_0::ErrorStatus> execute(const V1_0::Request& request,
+ const sp<V1_0::IExecutionCallback>& callback) override;
+ Return<V1_0::ErrorStatus> execute_1_2(const V1_0::Request& request, V1_2::MeasureTiming measure,
+ const sp<V1_2::IExecutionCallback>& callback) override;
+ Return<V1_3::ErrorStatus> execute_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const sp<V1_3::IExecutionCallback>& callback) override;
+ Return<void> executeSynchronously(const V1_0::Request& request, V1_2::MeasureTiming measure,
+ executeSynchronously_cb cb) override;
+ Return<void> executeSynchronously_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ executeSynchronously_1_3_cb cb) override;
+ Return<void> configureExecutionBurst(
+ const sp<V1_2::IBurstCallback>& callback,
+ const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+ const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+ configureExecutionBurst_cb cb) override;
+ Return<void> executeFenced(const V1_3::Request& request, const hidl_vec<hidl_handle>& waitFor,
+ V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const V1_3::OptionalTimeoutDuration& duration,
+ executeFenced_cb callback) override;
+
+ nn::SharedPreparedModel getUnderlyingPreparedModel() const;
+
+ private:
+ const nn::SharedPreparedModel kPreparedModel;
+};
+
+} // namespace android::hardware::neuralnetworks::adapter
+
+#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp b/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp
new file mode 100644
index 0000000..782e815
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp
@@ -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.
+ */
+
+#include "Adapter.h"
+
+#include "Device.h"
+
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor) {
+ return sp<Device>::make(std::move(device), std::move(executor));
+}
+
+sp<V1_3::IDevice> adapt(nn::SharedDevice device) {
+ Executor defaultExecutor = [](Task task, nn::OptionalTimePoint /*deadline*/) {
+ std::thread(std::move(task)).detach();
+ };
+ return adapt(std::move(device), std::move(defaultExecutor));
+}
+
+} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/Buffer.cpp b/neuralnetworks/utils/adapter/hidl/src/Buffer.cpp
similarity index 100%
rename from neuralnetworks/utils/adapter/src/Buffer.cpp
rename to neuralnetworks/utils/adapter/hidl/src/Buffer.cpp
diff --git a/neuralnetworks/utils/adapter/hidl/src/Burst.cpp b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
new file mode 100644
index 0000000..e3b165b
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
@@ -0,0 +1,259 @@
+/*
+ * 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 "Burst.h"
+
+#include <android-base/logging.h>
+#include <nnapi/IBurst.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.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/1.2/BurstUtils.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <map>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "Tracing.h"
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+constexpr V1_2::Timing kTiming = {std::numeric_limits<uint64_t>::max(),
+ std::numeric_limits<uint64_t>::max()};
+
+nn::GeneralResult<std::vector<nn::SharedMemory>> getMemoriesCallback(
+ V1_0::ErrorStatus status, const hidl_vec<hidl_memory>& memories) {
+ HANDLE_STATUS_HIDL(status) << "getting burst memories failed with " << toString(status);
+ std::vector<nn::SharedMemory> canonicalMemories;
+ canonicalMemories.reserve(memories.size());
+ for (const auto& memory : memories) {
+ canonicalMemories.push_back(NN_TRY(nn::convert(memory)));
+ }
+ return canonicalMemories;
+}
+
+} // anonymous namespace
+
+Burst::MemoryCache::MemoryCache(nn::SharedBurst burstExecutor,
+ sp<V1_2::IBurstCallback> burstCallback)
+ : kBurstExecutor(std::move(burstExecutor)), kBurstCallback(std::move(burstCallback)) {
+ CHECK(kBurstExecutor != nullptr);
+ CHECK(kBurstCallback != nullptr);
+}
+
+nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
+Burst::MemoryCache::getCacheEntries(const std::vector<int32_t>& slots) {
+ std::lock_guard guard(mMutex);
+ NN_TRY(ensureCacheEntriesArePresentLocked(slots));
+
+ std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> results;
+ results.reserve(slots.size());
+ for (int32_t slot : slots) {
+ results.push_back(NN_TRY(getCacheEntryLocked(slot)));
+ }
+
+ return results;
+}
+
+nn::GeneralResult<void> Burst::MemoryCache::ensureCacheEntriesArePresentLocked(
+ const std::vector<int32_t>& slots) {
+ const auto slotIsKnown = [this](int32_t slot)
+ REQUIRES(mMutex) { return mCache.count(slot) > 0; };
+
+ // find unique unknown slots
+ std::vector<int32_t> unknownSlots = slots;
+ std::sort(unknownSlots.begin(), unknownSlots.end());
+ auto unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlots.end());
+ unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown);
+ unknownSlots.erase(unknownSlotsEnd, unknownSlots.end());
+
+ // quick-exit if all slots are known
+ if (unknownSlots.empty()) {
+ return {};
+ }
+
+ auto cb = neuralnetworks::utils::CallbackValue(getMemoriesCallback);
+
+ const auto ret = kBurstCallback->getMemories(unknownSlots, cb);
+ HANDLE_TRANSPORT_FAILURE(ret);
+
+ auto returnedMemories = NN_TRY(cb.take());
+
+ if (returnedMemories.size() != unknownSlots.size()) {
+ return NN_ERROR() << "Burst::MemoryCache::ensureCacheEntriesArePresentLocked: Error "
+ "retrieving memories -- count mismatch between requested memories ("
+ << unknownSlots.size() << ") and returned memories ("
+ << returnedMemories.size() << ")";
+ }
+
+ // add memories to unknown slots
+ for (size_t i = 0; i < unknownSlots.size(); ++i) {
+ addCacheEntryLocked(unknownSlots[i], std::move(returnedMemories[i]));
+ }
+
+ return {};
+}
+
+nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
+Burst::MemoryCache::getCacheEntryLocked(int32_t slot) {
+ if (const auto iter = mCache.find(slot); iter != mCache.end()) {
+ return iter->second;
+ }
+ return NN_ERROR() << "Burst::MemoryCache::getCacheEntryLocked failed because slot " << slot
+ << " is not present in the cache";
+}
+
+void Burst::MemoryCache::addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) {
+ auto hold = kBurstExecutor->cacheMemory(memory);
+ mCache.emplace(slot, std::make_pair(std::move(memory), std::move(hold)));
+}
+
+void Burst::MemoryCache::removeCacheEntry(int32_t slot) {
+ std::lock_guard guard(mMutex);
+ mCache.erase(slot);
+}
+
+// Burst methods
+
+nn::GeneralResult<sp<Burst>> Burst::create(
+ const sp<V1_2::IBurstCallback>& callback,
+ const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+ const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor,
+ std::chrono::microseconds pollingTimeWindow) {
+ // check inputs
+ if (callback == nullptr || burstExecutor == nullptr) {
+ return NN_ERROR() << "Burst::create passed a nullptr";
+ }
+
+ // create FMQ objects
+ auto requestChannelReceiver =
+ NN_TRY(V1_2::utils::RequestChannelReceiver::create(requestChannel, pollingTimeWindow));
+ auto resultChannelSender = NN_TRY(V1_2::utils::ResultChannelSender::create(resultChannel));
+
+ // check FMQ objects
+ CHECK(requestChannelReceiver != nullptr);
+ CHECK(resultChannelSender != nullptr);
+
+ // make and return context
+ return sp<Burst>::make(PrivateConstructorTag{}, callback, std::move(requestChannelReceiver),
+ std::move(resultChannelSender), std::move(burstExecutor));
+}
+
+Burst::Burst(PrivateConstructorTag /*tag*/, const sp<V1_2::IBurstCallback>& callback,
+ std::unique_ptr<V1_2::utils::RequestChannelReceiver> requestChannel,
+ std::unique_ptr<V1_2::utils::ResultChannelSender> resultChannel,
+ nn::SharedBurst burstExecutor)
+ : mCallback(callback),
+ mRequestChannelReceiver(std::move(requestChannel)),
+ mResultChannelSender(std::move(resultChannel)),
+ mBurstExecutor(std::move(burstExecutor)),
+ mMemoryCache(mBurstExecutor, mCallback) {
+ // TODO: highly document the threading behavior of this class
+ mWorker = std::thread([this] { task(); });
+}
+
+Burst::~Burst() {
+ // set teardown flag
+ mTeardown = true;
+ mRequestChannelReceiver->invalidate();
+
+ // wait for task thread to end
+ mWorker.join();
+}
+
+Return<void> Burst::freeMemory(int32_t slot) {
+ mMemoryCache.removeCacheEntry(slot);
+ return Void();
+}
+
+void Burst::task() {
+ // loop until the burst object is being destroyed
+ while (!mTeardown) {
+ // receive request
+ auto arguments = mRequestChannelReceiver->getBlocking();
+
+ // if the request packet was not properly received, return a generic error and skip the
+ // execution
+ //
+ // if the burst is being torn down, skip the execution so the "task" function can end
+ if (!arguments.has_value()) {
+ if (!mTeardown) {
+ mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kTiming);
+ }
+ continue;
+ }
+
+ // unpack the arguments; types are Request, std::vector<int32_t>, and V1_2::MeasureTiming,
+ // respectively
+ const auto [requestWithoutPools, slotsOfPools, measure] = std::move(arguments).value();
+
+ auto result = execute(requestWithoutPools, slotsOfPools, measure);
+
+ // return result
+ if (result.has_value()) {
+ const auto& [outputShapes, timing] = result.value();
+ mResultChannelSender->send(V1_0::ErrorStatus::NONE, outputShapes, timing);
+ } else {
+ const auto& [message, code, outputShapes] = result.error();
+ LOG(ERROR) << "IBurst::execute failed with " << code << ": " << message;
+ mResultChannelSender->send(V1_2::utils::convert(code).value(),
+ V1_2::utils::convert(outputShapes).value(), kTiming);
+ }
+ }
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> Burst::execute(
+ const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
+ V1_2::MeasureTiming measure) {
+ NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
+ "Burst getting memory, executing, and returning results");
+
+ // ensure executor with cache has required memory
+ const auto cacheEntries = NN_TRY(mMemoryCache.getCacheEntries(slotsOfPools));
+
+ // convert request, populating its pools
+ // This code performs an unvalidated convert because the request object without its pools is
+ // invalid because it is incomplete. Instead, the validation is performed after the memory pools
+ // have been added to the request.
+ auto canonicalRequest = NN_TRY(nn::unvalidatedConvert(requestWithoutPools));
+ CHECK(canonicalRequest.pools.empty());
+ std::transform(cacheEntries.begin(), cacheEntries.end(),
+ std::back_inserter(canonicalRequest.pools),
+ [](const auto& cacheEntry) { return cacheEntry.first; });
+ NN_TRY(validate(canonicalRequest));
+
+ nn::MeasureTiming canonicalMeasure = NN_TRY(nn::convert(measure));
+
+ const auto [outputShapes, timing] =
+ NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}, {}, {}));
+
+ return std::make_pair(NN_TRY(V1_2::utils::convert(outputShapes)),
+ NN_TRY(V1_2::utils::convert(timing)));
+}
+
+} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/src/Device.cpp b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
new file mode 100644
index 0000000..305a1b4
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
@@ -0,0 +1,546 @@
+/*
+ * 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 "PreparedModel.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.3/types.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 <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/Utils.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/1.1/Utils.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/1.2/Utils.h>
+#include <nnapi/hal/1.3/Conversions.h>
+#include <nnapi/hal/1.3/Utils.h>
+
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
+
+sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel) {
+ if (preparedModel == nullptr) {
+ return nullptr;
+ }
+ return sp<PreparedModel>::make(std::move(preparedModel));
+}
+
+void notify(V1_0::IPreparedModelCallback* callback, nn::ErrorStatus status,
+ const sp<PreparedModel>& hidlPreparedModel) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_0::utils::convert(status).value();
+ const auto ret = callback->notify(hidlStatus, hidlPreparedModel);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_0::IPreparedModelCallback::notify failed with " << ret.description();
+ }
+ }
+}
+
+void notify(V1_2::IPreparedModelCallback* callback, nn::ErrorStatus status,
+ const sp<PreparedModel>& hidlPreparedModel) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_2::utils::convert(status).value();
+ const auto ret = callback->notify_1_2(hidlStatus, hidlPreparedModel);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_2::IPreparedModelCallback::notify_1_2 failed with "
+ << ret.description();
+ }
+ }
+}
+
+void notify(V1_3::IPreparedModelCallback* callback, nn::ErrorStatus status,
+ const sp<PreparedModel>& hidlPreparedModel) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_3::utils::convert(status).value();
+ const auto ret = callback->notify_1_3(hidlStatus, hidlPreparedModel);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_3::IPreparedModelCallback::notify_1_3 failed with "
+ << ret.description();
+ }
+ }
+}
+
+template <typename CallbackType>
+void notify(CallbackType* callback, PrepareModelResult result) {
+ if (!result.has_value()) {
+ const auto [message, status] = std::move(result).error();
+ LOG(ERROR) << message;
+ notify(callback, status, nullptr);
+ } else {
+ auto preparedModel = std::move(result).value();
+ auto hidlPreparedModel = adaptPreparedModel(std::move(preparedModel));
+ notify(callback, nn::ErrorStatus::NONE, std::move(hidlPreparedModel));
+ }
+}
+
+template <typename ModelType>
+nn::GeneralResult<hidl_vec<bool>> getSupportedOperations(const nn::SharedDevice& device,
+ const ModelType& model) {
+ const auto nnModel = NN_TRY(convertInput(model));
+ return NN_TRY(device->getSupportedOperations(nnModel));
+}
+
+nn::GeneralResult<void> prepareModel(const nn::SharedDevice& device, const Executor& executor,
+ const V1_0::Model& model,
+ const sp<V1_0::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModel = NN_TRY(convertInput(model));
+
+ Task task = [device, nnModel = std::move(nnModel), callback] {
+ auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
+ nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), {});
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_1(const nn::SharedDevice& device, const Executor& executor,
+ const V1_1::Model& model,
+ V1_1::ExecutionPreference preference,
+ const sp<V1_0::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModel = NN_TRY(convertInput(model));
+ const auto nnPreference = NN_TRY(convertInput(preference));
+
+ Task task = [device, nnModel = std::move(nnModel), nnPreference, callback] {
+ auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {},
+ {}, {}, {});
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), {});
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_2(const nn::SharedDevice& device, const Executor& executor,
+ const V1_2::Model& model,
+ V1_1::ExecutionPreference preference,
+ const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token,
+ const sp<V1_2::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModel = NN_TRY(convertInput(model));
+ const auto nnPreference = NN_TRY(convertInput(preference));
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = nn::CacheToken(token);
+
+ Task task = [device, nnModel = std::move(nnModel), nnPreference,
+ nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+ nnToken, callback] {
+ auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
+ nnModelCache, nnDataCache, nnToken, {}, {});
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), {});
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_3(
+ const nn::SharedDevice& device, const Executor& executor, const V1_3::Model& model,
+ V1_1::ExecutionPreference preference, V1_3::Priority priority,
+ const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModel = NN_TRY(convertInput(model));
+ const auto nnPreference = NN_TRY(convertInput(preference));
+ const auto nnPriority = NN_TRY(convertInput(priority));
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = nn::CacheToken(token);
+
+ Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
+ nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+ nnToken, callback] {
+ auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
+ nnModelCache, nnDataCache, nnToken, {}, {});
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), nnDeadline);
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache(const nn::SharedDevice& device,
+ const Executor& executor,
+ const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token,
+ const sp<V1_2::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = nn::CacheToken(token);
+
+ Task task = [device, nnModelCache = std::move(nnModelCache),
+ nnDataCache = std::move(nnDataCache), nnToken, callback] {
+ auto result = device->prepareModelFromCache({}, nnModelCache, nnDataCache, nnToken);
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), {});
+
+ return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache_1_3(
+ const nn::SharedDevice& device, const Executor& executor,
+ const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ auto nnModelCache = NN_TRY(convertInput(modelCache));
+ auto nnDataCache = NN_TRY(convertInput(dataCache));
+ const auto nnToken = nn::CacheToken(token);
+
+ auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
+ nnDataCache = std::move(nnDataCache), nnToken, callback] {
+ auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
+ notify(callback.get(), std::move(result));
+ };
+ executor(std::move(task), nnDeadline);
+
+ return {};
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> downcast(const sp<V1_3::IPreparedModel>& preparedModel) {
+ if (preparedModel == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
+ }
+ if (preparedModel->isRemote()) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
+ }
+
+ // This static_cast is safe because adapter::PreparedModel is the only class that implements
+ // the IPreparedModel interface in the adapter service code.
+ const auto* casted = static_cast<const PreparedModel*>(preparedModel.get());
+ return casted->getUnderlyingPreparedModel();
+}
+
+nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
+ const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels) {
+ std::vector<nn::SharedPreparedModel> canonical;
+ canonical.reserve(preparedModels.size());
+ for (const auto& preparedModel : preparedModels) {
+ canonical.push_back(NN_TRY(downcast(preparedModel)));
+ }
+ return canonical;
+}
+
+nn::GeneralResult<std::pair<sp<V1_3::IBuffer>, uint32_t>> allocate(
+ const nn::SharedDevice& device, const V1_3::BufferDesc& desc,
+ const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
+ const hidl_vec<V1_3::BufferRole>& inputRoles,
+ const hidl_vec<V1_3::BufferRole>& outputRoles) {
+ auto nnDesc = NN_TRY(convertInput(desc));
+ auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
+ auto nnInputRoles = NN_TRY(convertInput(inputRoles));
+ auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
+
+ auto buffer = NN_TRY(device->allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
+
+ const nn::Request::MemoryDomainToken token = buffer->getToken();
+ auto hidlBuffer = sp<Buffer>::make(std::move(buffer));
+ return std::make_pair(std::move(hidlBuffer), static_cast<uint32_t>(token));
+}
+
+} // namespace
+
+Device::Device(nn::SharedDevice device, Executor executor)
+ : kDevice(std::move(device)), kExecutor(std::move(executor)) {
+ CHECK(kDevice != nullptr);
+ CHECK(kExecutor != nullptr);
+}
+
+Return<void> Device::getCapabilities(getCapabilities_cb cb) {
+ const auto capabilities = V1_0::utils::convert(kDevice->getCapabilities()).value();
+ cb(V1_0::ErrorStatus::NONE, capabilities);
+ return Void();
+}
+
+Return<void> Device::getCapabilities_1_1(getCapabilities_1_1_cb cb) {
+ const auto capabilities = V1_1::utils::convert(kDevice->getCapabilities()).value();
+ cb(V1_0::ErrorStatus::NONE, capabilities);
+ return Void();
+}
+
+Return<void> Device::getCapabilities_1_2(getCapabilities_1_2_cb cb) {
+ const auto capabilities = V1_2::utils::convert(kDevice->getCapabilities()).value();
+ cb(V1_0::ErrorStatus::NONE, capabilities);
+ return Void();
+}
+
+Return<void> Device::getCapabilities_1_3(getCapabilities_1_3_cb cb) {
+ const auto capabilities = V1_3::utils::convert(kDevice->getCapabilities()).value();
+ cb(V1_3::ErrorStatus::NONE, capabilities);
+ return Void();
+}
+
+Return<void> Device::getVersionString(getVersionString_cb cb) {
+ cb(V1_0::ErrorStatus::NONE, kDevice->getVersionString());
+ return Void();
+}
+
+Return<void> Device::getType(getType_cb cb) {
+ const auto maybeDeviceType = V1_2::utils::convert(kDevice->getType());
+ if (!maybeDeviceType.has_value()) {
+ const auto& [message, code] = maybeDeviceType.error();
+ LOG(ERROR) << "adapter::Device::getType failed with " << code << ": " << message;
+ cb(V1_2::utils::convert(code).value(), {});
+ } else {
+ cb(V1_0::ErrorStatus::NONE, maybeDeviceType.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getSupportedExtensions(getSupportedExtensions_cb cb) {
+ const auto maybeSupportedExtensions = V1_2::utils::convert(kDevice->getSupportedExtensions());
+ if (!maybeSupportedExtensions.has_value()) {
+ const auto& [message, code] = maybeSupportedExtensions.error();
+ LOG(ERROR) << "adapter::Device::getSupportedExtensions failed with " << code << ": "
+ << message;
+ cb(V1_2::utils::convert(code).value(), {});
+ } else {
+ cb(V1_0::ErrorStatus::NONE, maybeSupportedExtensions.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getSupportedOperations(const V1_0::Model& model,
+ getSupportedOperations_cb cb) {
+ const auto result = adapter::getSupportedOperations(kDevice, model);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ LOG(ERROR) << "adapter::Device::getSupportedOperations_1_0 failed with " << code << ": "
+ << message;
+ cb(V1_0::utils::convert(code).value(), {});
+ } else {
+ cb(V1_0::ErrorStatus::NONE, result.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_1(const V1_1::Model& model,
+ getSupportedOperations_1_1_cb cb) {
+ const auto result = adapter::getSupportedOperations(kDevice, model);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ LOG(ERROR) << "adapter::Device::getSupportedOperations_1_1 failed with " << code << ": "
+ << message;
+ cb(V1_1::utils::convert(code).value(), {});
+ } else {
+ cb(V1_0::ErrorStatus::NONE, result.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_2(const V1_2::Model& model,
+ getSupportedOperations_1_2_cb cb) {
+ const auto result = adapter::getSupportedOperations(kDevice, model);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ LOG(ERROR) << "adapter::Device::getSupportedOperations_1_2 failed with " << code << ": "
+ << message;
+ cb(V1_2::utils::convert(code).value(), {});
+ } else {
+ cb(V1_0::ErrorStatus::NONE, result.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_3(const V1_3::Model& model,
+ getSupportedOperations_1_3_cb cb) {
+ const auto result = adapter::getSupportedOperations(kDevice, model);
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ LOG(ERROR) << "adapter::Device::getSupportedOperations_1_3 failed with " << code << ": "
+ << message;
+ cb(V1_3::utils::convert(code).value(), {});
+ } else {
+ cb(V1_3::ErrorStatus::NONE, result.value());
+ }
+ return Void();
+}
+
+Return<void> Device::getNumberOfCacheFilesNeeded(getNumberOfCacheFilesNeeded_cb cb) {
+ const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
+ cb(V1_0::ErrorStatus::NONE, numModelCache, numDataCache);
+ return Void();
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel(const V1_0::Model& model,
+ const sp<V1_0::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModel(kDevice, kExecutor, model, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModel failed with " << code << ": " << message;
+ notify(callback.get(), code, nullptr);
+ return V1_0::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel_1_1(
+ const V1_1::Model& model, V1_1::ExecutionPreference preference,
+ const sp<V1_0::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModel_1_1(kDevice, kExecutor, model, preference, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModel_1_1 failed with " << code << ": " << message;
+ notify(callback.get(), code, nullptr);
+ return V1_1::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel_1_2(
+ const V1_2::Model& model, V1_1::ExecutionPreference preference,
+ const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModel_1_2(kDevice, kExecutor, model, preference, modelCache,
+ dataCache, token, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModel_1_2 failed with " << code << ": " << message;
+ notify(callback.get(), code, nullptr);
+ return V1_2::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> Device::prepareModel_1_3(
+ const V1_3::Model& model, V1_1::ExecutionPreference preference, V1_3::Priority priority,
+ const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModel_1_3(kDevice, kExecutor, model, preference, priority,
+ deadline, modelCache, dataCache, token, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModel_1_3 failed with " << code << ": " << message;
+ notify(callback.get(), code, nullptr);
+ return V1_3::utils::convert(code).value();
+ }
+ return V1_3::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModelFromCache(
+ const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModelFromCache(kDevice, kExecutor, modelCache, dataCache, token,
+ callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModelFromCache failed with " << code << ": "
+ << message;
+ notify(callback.get(), code, nullptr);
+ return V1_2::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> Device::prepareModelFromCache_1_3(
+ const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback) {
+ auto result = adapter::prepareModelFromCache_1_3(kDevice, kExecutor, deadline, modelCache,
+ dataCache, token, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::prepareModelFromCache_1_3 failed with " << code << ": "
+ << message;
+ notify(callback.get(), code, nullptr);
+ return V1_3::utils::convert(code).value();
+ }
+ return V1_3::ErrorStatus::NONE;
+}
+
+Return<V1_0::DeviceStatus> Device::getStatus() {
+ return V1_0::DeviceStatus::AVAILABLE;
+}
+
+Return<void> Device::allocate(const V1_3::BufferDesc& desc,
+ const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
+ const hidl_vec<V1_3::BufferRole>& inputRoles,
+ const hidl_vec<V1_3::BufferRole>& outputRoles, allocate_cb cb) {
+ auto result = adapter::allocate(kDevice, desc, preparedModels, inputRoles, outputRoles);
+ if (!result.has_value()) {
+ const auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::Device::allocate failed with " << code << ": " << message;
+ cb(V1_3::utils::convert(code).value(), nullptr, /*token=*/0);
+ return Void();
+ }
+ auto [buffer, token] = std::move(result).value();
+ cb(V1_3::ErrorStatus::NONE, buffer, token);
+ return Void();
+}
+
+} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
new file mode 100644
index 0000000..3570a74
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
@@ -0,0 +1,409 @@
+/*
+ * 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 "Burst.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Utils.h>
+#include <nnapi/hal/1.2/Utils.h>
+#include <nnapi/hal/1.3/Conversions.h>
+#include <nnapi/hal/1.3/Utils.h>
+
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+ auto result = nn::convert(object);
+ if (!result.has_value()) {
+ result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return result;
+}
+
+class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
+ public:
+ explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
+ : kCallback(callback) {
+ CHECK(callback != nullptr);
+ }
+
+ Return<void> getExecutionInfo(getExecutionInfo_cb cb) override {
+ const auto result = kCallback();
+ if (!result.has_value()) {
+ const auto& [message, code] = result.error();
+ const auto status =
+ V1_3::utils::convert(code).value_or(V1_3::ErrorStatus::GENERAL_FAILURE);
+ LOG(ERROR) << message;
+ cb(status, V1_2::utils::kNoTiming, V1_2::utils::kNoTiming);
+ return Void();
+ }
+ const auto [timingLaunched, timingFenced] = result.value();
+ const auto hidlTimingLaunched = V1_3::utils::convert(timingLaunched).value();
+ const auto hidlTimingFenced = V1_3::utils::convert(timingFenced).value();
+ cb(V1_3::ErrorStatus::NONE, hidlTimingLaunched, hidlTimingFenced);
+ return Void();
+ }
+
+ private:
+ const nn::ExecuteFencedInfoCallback kCallback;
+};
+
+using ExecutionResult = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
+
+void notify(V1_0::IExecutionCallback* callback, nn::ErrorStatus status,
+ const std::vector<nn::OutputShape>& /*outputShapes*/, const nn::Timing& /*timing*/) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_0::utils::convert(status).value();
+ const auto ret = callback->notify(hidlStatus);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_0::IExecutionCallback::notify failed with " << ret.description();
+ }
+ }
+}
+
+void notify(V1_2::IExecutionCallback* callback, nn::ErrorStatus status,
+ const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_2::utils::convert(status).value();
+ const auto hidlOutputShapes = V1_2::utils::convert(outputShapes).value();
+ const auto hidlTiming = V1_2::utils::convert(timing).value();
+ const auto ret = callback->notify_1_2(hidlStatus, hidlOutputShapes, hidlTiming);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_2::IExecutionCallback::notify_1_2 failed with " << ret.description();
+ }
+ }
+}
+
+void notify(V1_3::IExecutionCallback* callback, nn::ErrorStatus status,
+ const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
+ if (callback != nullptr) {
+ const auto hidlStatus = V1_3::utils::convert(status).value();
+ const auto hidlOutputShapes = V1_3::utils::convert(outputShapes).value();
+ const auto hidlTiming = V1_3::utils::convert(timing).value();
+ const auto ret = callback->notify_1_3(hidlStatus, hidlOutputShapes, hidlTiming);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "V1_3::IExecutionCallback::notify_1_3 failed with " << ret.description();
+ }
+ }
+}
+
+template <typename CallbackType>
+void notify(CallbackType* callback, ExecutionResult result) {
+ if (!result.has_value()) {
+ const auto [message, status, outputShapes] = std::move(result).error();
+ LOG(ERROR) << message;
+ notify(callback, status, outputShapes, {});
+ } else {
+ const auto [outputShapes, timing] = std::move(result).value();
+ notify(callback, nn::ErrorStatus::NONE, outputShapes, timing);
+ }
+}
+
+nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel,
+ const V1_0::Request& request,
+ const sp<V1_0::IExecutionCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ const auto nnRequest = NN_TRY(convertInput(request));
+
+ auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {}, {}, {});
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+ const auto& [message, code, outputShapes] = result.error();
+ return nn::error(code) << message;
+ }
+
+ notify(callback.get(), std::move(result));
+ return {};
+}
+
+nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel,
+ const V1_0::Request& request, V1_2::MeasureTiming measure,
+ const sp<V1_2::IExecutionCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+
+ auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {});
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+ const auto& [message, code, outputShapes] = result.error();
+ return nn::error(code) << message;
+ }
+
+ notify(callback.get(), std::move(result));
+ return {};
+}
+
+nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel,
+ const V1_3::Request& request, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const sp<V1_3::IExecutionCallback>& callback) {
+ if (callback.get() == nullptr) {
+ return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+ }
+
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+
+ auto result =
+ preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration, {}, {});
+
+ if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+ const auto& [message, code, outputShapes] = result.error();
+ return nn::error(code) << message;
+ }
+
+ notify(callback.get(), std::move(result));
+ return {};
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
+ const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
+ V1_2::MeasureTiming measure) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+
+ const auto [outputShapes, timing] =
+ NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {}));
+
+ auto hidlOutputShapes = NN_TRY(V1_2::utils::convert(outputShapes));
+ const auto hidlTiming = NN_TRY(V1_2::utils::convert(timing));
+ return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously_1_3(
+ const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
+ V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+
+ const auto [outputShapes, timing] = NN_TRY(preparedModel->execute(
+ nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration, {}, {}));
+
+ auto hidlOutputShapes = NN_TRY(V1_3::utils::convert(outputShapes));
+ const auto hidlTiming = NN_TRY(V1_3::utils::convert(timing));
+ return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
+}
+
+nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
+ const hidl_vec<hidl_handle>& handles) {
+ auto nnHandles = NN_TRY(convertInput(handles));
+ std::vector<nn::SyncFence> syncFences;
+ syncFences.reserve(handles.size());
+ for (auto&& handle : nnHandles) {
+ if (auto syncFence = nn::SyncFence::create(std::move(handle)); !syncFence.ok()) {
+ return nn::error(nn::ErrorStatus::INVALID_ARGUMENT) << std::move(syncFence).error();
+ } else {
+ syncFences.push_back(std::move(syncFence).value());
+ }
+ }
+ return syncFences;
+}
+
+nn::GeneralResult<sp<V1_2::IBurstContext>> configureExecutionBurst(
+ const nn::SharedPreparedModel& preparedModel, const sp<V1_2::IBurstCallback>& callback,
+ const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+ const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel) {
+ auto burstExecutor = NN_TRY(preparedModel->configureExecutionBurst());
+ return Burst::create(callback, requestChannel, resultChannel, std::move(burstExecutor),
+ V1_2::utils::getBurstServerPollingTimeWindow());
+}
+
+nn::GeneralResult<std::pair<hidl_handle, sp<V1_3::IFencedExecutionCallback>>> executeFenced(
+ const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
+ const hidl_vec<hidl_handle>& waitFor, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const V1_3::OptionalTimeoutDuration& duration) {
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+ const auto nnDuration = NN_TRY(convertInput(duration));
+
+ auto [syncFence, executeFencedCallback] =
+ NN_TRY(preparedModel->executeFenced(nnRequest, nnWaitFor, nnMeasure, nnDeadline,
+ nnLoopTimeoutDuration, nnDuration, {}, {}));
+
+ auto hidlSyncFence = NN_TRY(V1_3::utils::convert(syncFence.getSharedHandle()));
+ auto hidlExecuteFencedCallback = sp<FencedExecutionCallback>::make(executeFencedCallback);
+ return std::make_pair(std::move(hidlSyncFence), std::move(hidlExecuteFencedCallback));
+}
+
+} // namespace
+
+PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel)
+ : kPreparedModel(std::move(preparedModel)) {
+ CHECK(kPreparedModel != nullptr);
+}
+
+nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
+ return kPreparedModel;
+}
+
+Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
+ const sp<V1_0::IExecutionCallback>& callback) {
+ auto result = adapter::execute(kPreparedModel, request, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
+ notify(callback.get(), code, {}, {});
+ return V1_0::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
+ V1_2::MeasureTiming measure,
+ const sp<V1_2::IExecutionCallback>& callback) {
+ auto result = adapter::execute_1_2(kPreparedModel, request, measure, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
+ notify(callback.get(), code, {}, {});
+ return V1_2::utils::convert(code).value();
+ }
+ return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> PreparedModel::execute_1_3(
+ const V1_3::Request& request, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const sp<V1_3::IExecutionCallback>& callback) {
+ auto result = adapter::execute_1_3(kPreparedModel, request, measure, deadline,
+ loopTimeoutDuration, callback);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::execute_1_3 failed with " << code << ": " << message;
+ notify(callback.get(), code, {}, {});
+ return V1_3::utils::convert(code).value();
+ }
+ return V1_3::ErrorStatus::NONE;
+}
+
+Return<void> PreparedModel::executeSynchronously(const V1_0::Request& request,
+ V1_2::MeasureTiming measure,
+ executeSynchronously_cb cb) {
+ auto result = adapter::executeSynchronously(kPreparedModel, request, measure);
+ if (!result.has_value()) {
+ auto [message, code, outputShapes] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::executeSynchronously failed with " << code << ": "
+ << message;
+ cb(V1_2::utils::convert(code).value(), V1_2::utils::convert(outputShapes).value(),
+ V1_2::utils::kNoTiming);
+ return Void();
+ }
+ auto [outputShapes, timing] = std::move(result).value();
+ cb(V1_0::ErrorStatus::NONE, outputShapes, timing);
+ return Void();
+}
+
+Return<void> PreparedModel::executeSynchronously_1_3(
+ const V1_3::Request& request, V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration, executeSynchronously_1_3_cb cb) {
+ auto result = adapter::executeSynchronously_1_3(kPreparedModel, request, measure, deadline,
+ loopTimeoutDuration);
+ if (!result.has_value()) {
+ auto [message, code, outputShapes] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::executeSynchronously_1_3 failed with " << code
+ << ": " << message;
+ cb(V1_3::utils::convert(code).value(), V1_3::utils::convert(outputShapes).value(),
+ V1_2::utils::kNoTiming);
+ return Void();
+ }
+ auto [outputShapes, timing] = std::move(result).value();
+ cb(V1_3::ErrorStatus::NONE, outputShapes, timing);
+ return Void();
+}
+
+Return<void> PreparedModel::configureExecutionBurst(
+ const sp<V1_2::IBurstCallback>& callback,
+ const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+ const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+ configureExecutionBurst_cb cb) {
+ auto result = adapter::configureExecutionBurst(kPreparedModel, callback, requestChannel,
+ resultChannel);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::configureExecutionBurst failed with " << code << ": "
+ << message;
+ cb(V1_2::utils::convert(code).value(), nullptr);
+ return Void();
+ }
+ const auto burstContext = std::move(result).value();
+ cb(V1_0::ErrorStatus::NONE, burstContext);
+ return Void();
+}
+
+Return<void> PreparedModel::executeFenced(const V1_3::Request& request,
+ const hidl_vec<hidl_handle>& waitFor,
+ V1_2::MeasureTiming measure,
+ const V1_3::OptionalTimePoint& deadline,
+ const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+ const V1_3::OptionalTimeoutDuration& duration,
+ executeFenced_cb callback) {
+ auto result = adapter::executeFenced(kPreparedModel, request, waitFor, measure, deadline,
+ loopTimeoutDuration, duration);
+ if (!result.has_value()) {
+ auto [message, code] = std::move(result).error();
+ LOG(ERROR) << "adapter::PreparedModel::executeFenced failed with " << code << ": "
+ << message;
+ callback(V1_3::utils::convert(code).value(), {}, nullptr);
+ return Void();
+ }
+ auto [syncFence, executeFencedCallback] = std::move(result).value();
+ callback(V1_3::ErrorStatus::NONE, syncFence, executeFencedCallback);
+ return Void();
+}
+
+} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h b/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h
deleted file mode 100644
index da00a09..0000000
--- a/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
-
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <nnapi/IDevice.h>
-#include <nnapi/Types.h>
-#include <sys/types.h>
-#include <functional>
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-/**
- * A self-contained unit of work to be executed.
- */
-using Task = std::function<void()>;
-
-/**
- * A type-erased executor which executes a task asynchronously.
- *
- * This executor is also provided with an Application ID (Android User ID) and an optional deadline
- * for when the caller expects is the upper bound for the amount of time to complete the task.
- */
-using Executor = std::function<void(Task, uid_t, nn::OptionalTimePoint)>;
-
-/**
- * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
- *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
- * @param device NNAPI canonical IDevice interface object to be adapted.
- * @param executor Type-erased executor to handle executing tasks asynchronously.
- * @return HIDL NN HAL IDevice interface object.
- */
-sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor);
-
-/**
- * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
- *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
- * This function uses a default executor, which will execute tasks from a detached thread.
- *
- * @param device NNAPI canonical IDevice interface object to be adapted.
- * @return HIDL NN HAL IDevice interface object.
- */
-sp<V1_3::IDevice> adapt(nn::SharedDevice device);
-
-} // namespace android::hardware::neuralnetworks::adapter
-
-#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h b/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h
deleted file mode 100644
index 65763b8..0000000
--- a/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
-
-#include "nnapi/hal/Adapter.h"
-
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/Types.h>
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-// Class that adapts nn::IPreparedModel to V1_3::IPreparedModel.
-class PreparedModel final : public V1_3::IPreparedModel {
- public:
- PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor, uid_t userId);
-
- Return<V1_0::ErrorStatus> execute(const V1_0::Request& request,
- const sp<V1_0::IExecutionCallback>& callback) override;
- Return<V1_0::ErrorStatus> execute_1_2(const V1_0::Request& request, V1_2::MeasureTiming measure,
- const sp<V1_2::IExecutionCallback>& callback) override;
- Return<V1_3::ErrorStatus> execute_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const sp<V1_3::IExecutionCallback>& callback) override;
- Return<void> executeSynchronously(const V1_0::Request& request, V1_2::MeasureTiming measure,
- executeSynchronously_cb cb) override;
- Return<void> executeSynchronously_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- executeSynchronously_1_3_cb cb) override;
- Return<void> configureExecutionBurst(
- const sp<V1_2::IBurstCallback>& callback,
- const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
- const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
- configureExecutionBurst_cb cb) override;
- Return<void> executeFenced(const V1_3::Request& request, const hidl_vec<hidl_handle>& waitFor,
- V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const V1_3::OptionalTimeoutDuration& duration,
- executeFenced_cb callback) override;
-
- nn::SharedPreparedModel getUnderlyingPreparedModel() const;
-
- private:
- const nn::SharedPreparedModel kPreparedModel;
- const Executor kExecutor;
- const uid_t kUserId;
-};
-
-} // namespace android::hardware::neuralnetworks::adapter
-
-#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/adapter/src/Adapter.cpp b/neuralnetworks/utils/adapter/src/Adapter.cpp
deleted file mode 100644
index d6f53f0..0000000
--- a/neuralnetworks/utils/adapter/src/Adapter.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Adapter.h"
-
-#include "Device.h"
-
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <nnapi/IDevice.h>
-#include <nnapi/Types.h>
-#include <sys/types.h>
-
-#include <functional>
-#include <memory>
-#include <thread>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor) {
- return sp<Device>::make(std::move(device), std::move(executor));
-}
-
-sp<V1_3::IDevice> adapt(nn::SharedDevice device) {
- Executor defaultExecutor = [](Task task, uid_t /*uid*/, nn::OptionalTimePoint /*deadline*/) {
- std::thread(std::move(task)).detach();
- };
- return adapt(std::move(device), std::move(defaultExecutor));
-}
-
-} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/Burst.cpp b/neuralnetworks/utils/adapter/src/Burst.cpp
deleted file mode 100644
index 8b2e1dd..0000000
--- a/neuralnetworks/utils/adapter/src/Burst.cpp
+++ /dev/null
@@ -1,259 +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 "Burst.h"
-
-#include <android-base/logging.h>
-#include <nnapi/IBurst.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.0/HandleError.h>
-#include <nnapi/hal/1.0/ProtectCallback.h>
-#include <nnapi/hal/1.2/BurstUtils.h>
-#include <nnapi/hal/1.2/Conversions.h>
-#include <nnapi/hal/TransferValue.h>
-
-#include <algorithm>
-#include <cstring>
-#include <limits>
-#include <map>
-#include <memory>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "Tracing.h"
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-constexpr V1_2::Timing kTiming = {std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::max()};
-
-nn::GeneralResult<std::vector<nn::SharedMemory>> getMemoriesCallback(
- V1_0::ErrorStatus status, const hidl_vec<hidl_memory>& memories) {
- HANDLE_STATUS_HIDL(status) << "getting burst memories failed with " << toString(status);
- std::vector<nn::SharedMemory> canonicalMemories;
- canonicalMemories.reserve(memories.size());
- for (const auto& memory : memories) {
- canonicalMemories.push_back(NN_TRY(nn::convert(memory)));
- }
- return canonicalMemories;
-}
-
-} // anonymous namespace
-
-Burst::MemoryCache::MemoryCache(nn::SharedBurst burstExecutor,
- sp<V1_2::IBurstCallback> burstCallback)
- : kBurstExecutor(std::move(burstExecutor)), kBurstCallback(std::move(burstCallback)) {
- CHECK(kBurstExecutor != nullptr);
- CHECK(kBurstCallback != nullptr);
-}
-
-nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
-Burst::MemoryCache::getCacheEntries(const std::vector<int32_t>& slots) {
- std::lock_guard guard(mMutex);
- NN_TRY(ensureCacheEntriesArePresentLocked(slots));
-
- std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> results;
- results.reserve(slots.size());
- for (int32_t slot : slots) {
- results.push_back(NN_TRY(getCacheEntryLocked(slot)));
- }
-
- return results;
-}
-
-nn::GeneralResult<void> Burst::MemoryCache::ensureCacheEntriesArePresentLocked(
- const std::vector<int32_t>& slots) {
- const auto slotIsKnown = [this](int32_t slot)
- REQUIRES(mMutex) { return mCache.count(slot) > 0; };
-
- // find unique unknown slots
- std::vector<int32_t> unknownSlots = slots;
- std::sort(unknownSlots.begin(), unknownSlots.end());
- auto unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlots.end());
- unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown);
- unknownSlots.erase(unknownSlotsEnd, unknownSlots.end());
-
- // quick-exit if all slots are known
- if (unknownSlots.empty()) {
- return {};
- }
-
- auto cb = neuralnetworks::utils::CallbackValue(getMemoriesCallback);
-
- const auto ret = kBurstCallback->getMemories(unknownSlots, cb);
- HANDLE_TRANSPORT_FAILURE(ret);
-
- auto returnedMemories = NN_TRY(cb.take());
-
- if (returnedMemories.size() != unknownSlots.size()) {
- return NN_ERROR() << "Burst::MemoryCache::ensureCacheEntriesArePresentLocked: Error "
- "retrieving memories -- count mismatch between requested memories ("
- << unknownSlots.size() << ") and returned memories ("
- << returnedMemories.size() << ")";
- }
-
- // add memories to unknown slots
- for (size_t i = 0; i < unknownSlots.size(); ++i) {
- addCacheEntryLocked(unknownSlots[i], std::move(returnedMemories[i]));
- }
-
- return {};
-}
-
-nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
-Burst::MemoryCache::getCacheEntryLocked(int32_t slot) {
- if (const auto iter = mCache.find(slot); iter != mCache.end()) {
- return iter->second;
- }
- return NN_ERROR() << "Burst::MemoryCache::getCacheEntryLocked failed because slot " << slot
- << " is not present in the cache";
-}
-
-void Burst::MemoryCache::addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) {
- auto hold = kBurstExecutor->cacheMemory(memory);
- mCache.emplace(slot, std::make_pair(std::move(memory), std::move(hold)));
-}
-
-void Burst::MemoryCache::removeCacheEntry(int32_t slot) {
- std::lock_guard guard(mMutex);
- mCache.erase(slot);
-}
-
-// Burst methods
-
-nn::GeneralResult<sp<Burst>> Burst::create(
- const sp<V1_2::IBurstCallback>& callback,
- const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
- const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor,
- std::chrono::microseconds pollingTimeWindow) {
- // check inputs
- if (callback == nullptr || burstExecutor == nullptr) {
- return NN_ERROR() << "Burst::create passed a nullptr";
- }
-
- // create FMQ objects
- auto requestChannelReceiver =
- NN_TRY(V1_2::utils::RequestChannelReceiver::create(requestChannel, pollingTimeWindow));
- auto resultChannelSender = NN_TRY(V1_2::utils::ResultChannelSender::create(resultChannel));
-
- // check FMQ objects
- CHECK(requestChannelReceiver != nullptr);
- CHECK(resultChannelSender != nullptr);
-
- // make and return context
- return sp<Burst>::make(PrivateConstructorTag{}, callback, std::move(requestChannelReceiver),
- std::move(resultChannelSender), std::move(burstExecutor));
-}
-
-Burst::Burst(PrivateConstructorTag /*tag*/, const sp<V1_2::IBurstCallback>& callback,
- std::unique_ptr<V1_2::utils::RequestChannelReceiver> requestChannel,
- std::unique_ptr<V1_2::utils::ResultChannelSender> resultChannel,
- nn::SharedBurst burstExecutor)
- : mCallback(callback),
- mRequestChannelReceiver(std::move(requestChannel)),
- mResultChannelSender(std::move(resultChannel)),
- mBurstExecutor(std::move(burstExecutor)),
- mMemoryCache(mBurstExecutor, mCallback) {
- // TODO: highly document the threading behavior of this class
- mWorker = std::thread([this] { task(); });
-}
-
-Burst::~Burst() {
- // set teardown flag
- mTeardown = true;
- mRequestChannelReceiver->invalidate();
-
- // wait for task thread to end
- mWorker.join();
-}
-
-Return<void> Burst::freeMemory(int32_t slot) {
- mMemoryCache.removeCacheEntry(slot);
- return Void();
-}
-
-void Burst::task() {
- // loop until the burst object is being destroyed
- while (!mTeardown) {
- // receive request
- auto arguments = mRequestChannelReceiver->getBlocking();
-
- // if the request packet was not properly received, return a generic error and skip the
- // execution
- //
- // if the burst is being torn down, skip the execution so the "task" function can end
- if (!arguments.has_value()) {
- if (!mTeardown) {
- mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kTiming);
- }
- continue;
- }
-
- // unpack the arguments; types are Request, std::vector<int32_t>, and V1_2::MeasureTiming,
- // respectively
- const auto [requestWithoutPools, slotsOfPools, measure] = std::move(arguments).value();
-
- auto result = execute(requestWithoutPools, slotsOfPools, measure);
-
- // return result
- if (result.has_value()) {
- const auto& [outputShapes, timing] = result.value();
- mResultChannelSender->send(V1_0::ErrorStatus::NONE, outputShapes, timing);
- } else {
- const auto& [message, code, outputShapes] = result.error();
- LOG(ERROR) << "IBurst::execute failed with " << code << ": " << message;
- mResultChannelSender->send(V1_2::utils::convert(code).value(),
- V1_2::utils::convert(outputShapes).value(), kTiming);
- }
- }
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> Burst::execute(
- const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
- V1_2::MeasureTiming measure) {
- NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
- "Burst getting memory, executing, and returning results");
-
- // ensure executor with cache has required memory
- const auto cacheEntries = NN_TRY(mMemoryCache.getCacheEntries(slotsOfPools));
-
- // convert request, populating its pools
- // This code performs an unvalidated convert because the request object without its pools is
- // invalid because it is incomplete. Instead, the validation is performed after the memory pools
- // have been added to the request.
- auto canonicalRequest = NN_TRY(nn::unvalidatedConvert(requestWithoutPools));
- CHECK(canonicalRequest.pools.empty());
- std::transform(cacheEntries.begin(), cacheEntries.end(),
- std::back_inserter(canonicalRequest.pools),
- [](const auto& cacheEntry) { return cacheEntry.first; });
- NN_TRY(validate(canonicalRequest));
-
- nn::MeasureTiming canonicalMeasure = NN_TRY(nn::convert(measure));
-
- const auto [outputShapes, timing] =
- NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}));
-
- return std::make_pair(NN_TRY(V1_2::utils::convert(outputShapes)),
- NN_TRY(V1_2::utils::convert(timing)));
-}
-
-} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/Device.cpp b/neuralnetworks/utils/adapter/src/Device.cpp
deleted file mode 100644
index 96142c3..0000000
--- a/neuralnetworks/utils/adapter/src/Device.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Device.h"
-
-#include "Buffer.h"
-#include "PreparedModel.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <hwbinder/IPCThreadState.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 <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/1.0/Utils.h>
-#include <nnapi/hal/1.1/Conversions.h>
-#include <nnapi/hal/1.1/Utils.h>
-#include <nnapi/hal/1.2/Conversions.h>
-#include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/1.3/Conversions.h>
-#include <nnapi/hal/1.3/Utils.h>
-#include <sys/types.h>
-
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-template <typename Type>
-auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
- auto result = nn::convert(object);
- if (!result.has_value()) {
- result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
- }
- return result;
-}
-
-using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
-
-sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel, Executor executor,
- uid_t userId) {
- if (preparedModel == nullptr) {
- return nullptr;
- }
- return sp<PreparedModel>::make(std::move(preparedModel), std::move(executor), userId);
-}
-
-void notify(V1_0::IPreparedModelCallback* callback, nn::ErrorStatus status,
- const sp<PreparedModel>& hidlPreparedModel) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_0::utils::convert(status).value();
- const auto ret = callback->notify(hidlStatus, hidlPreparedModel);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_0::IPreparedModelCallback::notify failed with " << ret.description();
- }
- }
-}
-
-void notify(V1_2::IPreparedModelCallback* callback, nn::ErrorStatus status,
- const sp<PreparedModel>& hidlPreparedModel) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_2::utils::convert(status).value();
- const auto ret = callback->notify_1_2(hidlStatus, hidlPreparedModel);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_2::IPreparedModelCallback::notify_1_2 failed with "
- << ret.description();
- }
- }
-}
-
-void notify(V1_3::IPreparedModelCallback* callback, nn::ErrorStatus status,
- const sp<PreparedModel>& hidlPreparedModel) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_3::utils::convert(status).value();
- const auto ret = callback->notify_1_3(hidlStatus, hidlPreparedModel);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_3::IPreparedModelCallback::notify_1_3 failed with "
- << ret.description();
- }
- }
-}
-
-template <typename CallbackType>
-void notify(CallbackType* callback, PrepareModelResult result, Executor executor, uid_t userId) {
- if (!result.has_value()) {
- const auto [message, status] = std::move(result).error();
- LOG(ERROR) << message;
- notify(callback, status, nullptr);
- } else {
- auto preparedModel = std::move(result).value();
- auto hidlPreparedModel =
- adaptPreparedModel(std::move(preparedModel), std::move(executor), userId);
- notify(callback, nn::ErrorStatus::NONE, std::move(hidlPreparedModel));
- }
-}
-
-template <typename ModelType>
-nn::GeneralResult<hidl_vec<bool>> getSupportedOperations(const nn::SharedDevice& device,
- const ModelType& model) {
- const auto nnModel = NN_TRY(convertInput(model));
- return NN_TRY(device->getSupportedOperations(nnModel));
-}
-
-nn::GeneralResult<void> prepareModel(const nn::SharedDevice& device, const Executor& executor,
- const V1_0::Model& model,
- const sp<V1_0::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnModel = NN_TRY(convertInput(model));
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- Task task = [device, nnModel = std::move(nnModel), userId, executor, callback] {
- auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
- nn::Priority::DEFAULT, {}, {}, {}, {});
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_1(const nn::SharedDevice& device, const Executor& executor,
- const V1_1::Model& model,
- V1_1::ExecutionPreference preference,
- const sp<V1_0::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnModel = NN_TRY(convertInput(model));
- const auto nnPreference = NN_TRY(convertInput(preference));
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- Task task = [device, nnModel = std::move(nnModel), nnPreference, userId, executor, callback] {
- auto result =
- device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {}, {});
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_2(const nn::SharedDevice& device, const Executor& executor,
- const V1_2::Model& model,
- V1_1::ExecutionPreference preference,
- const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache,
- const CacheToken& token,
- const sp<V1_2::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnModel = NN_TRY(convertInput(model));
- const auto nnPreference = NN_TRY(convertInput(preference));
- auto nnModelCache = NN_TRY(convertInput(modelCache));
- auto nnDataCache = NN_TRY(convertInput(dataCache));
- const auto nnToken = nn::CacheToken(token);
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- Task task = [device, nnModel = std::move(nnModel), nnPreference,
- nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
- nnToken, userId, executor, callback] {
- auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
- nnModelCache, nnDataCache, nnToken);
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_3(
- const nn::SharedDevice& device, const Executor& executor, const V1_3::Model& model,
- V1_1::ExecutionPreference preference, V1_3::Priority priority,
- const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
- const sp<V1_3::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnModel = NN_TRY(convertInput(model));
- const auto nnPreference = NN_TRY(convertInput(preference));
- const auto nnPriority = NN_TRY(convertInput(priority));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- auto nnModelCache = NN_TRY(convertInput(modelCache));
- auto nnDataCache = NN_TRY(convertInput(dataCache));
- const auto nnToken = nn::CacheToken(token);
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
- nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
- nnToken, userId, executor, callback] {
- auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
- nnModelCache, nnDataCache, nnToken);
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, nnDeadline);
-
- return {};
-}
-
-nn::GeneralResult<void> prepareModelFromCache(const nn::SharedDevice& device,
- const Executor& executor,
- const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache,
- const CacheToken& token,
- const sp<V1_2::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnModelCache = NN_TRY(convertInput(modelCache));
- auto nnDataCache = NN_TRY(convertInput(dataCache));
- const auto nnToken = nn::CacheToken(token);
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- Task task = [device, nnModelCache = std::move(nnModelCache),
- nnDataCache = std::move(nnDataCache), nnToken, userId, executor, callback] {
- auto result = device->prepareModelFromCache({}, nnModelCache, nnDataCache, nnToken);
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> prepareModelFromCache_1_3(
- const nn::SharedDevice& device, const Executor& executor,
- const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
- const sp<V1_3::IPreparedModelCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- auto nnModelCache = NN_TRY(convertInput(modelCache));
- auto nnDataCache = NN_TRY(convertInput(dataCache));
- const auto nnToken = nn::CacheToken(token);
-
- const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
- auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
- nnDataCache = std::move(nnDataCache), nnToken, userId, executor, callback] {
- auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
- notify(callback.get(), std::move(result), executor, userId);
- };
- executor(std::move(task), userId, nnDeadline);
-
- return {};
-}
-
-nn::GeneralResult<nn::SharedPreparedModel> downcast(const sp<V1_3::IPreparedModel>& preparedModel) {
- if (preparedModel == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
- }
- if (preparedModel->isRemote()) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
- }
-
- // This static_cast is safe because adapter::PreparedModel is the only class that implements
- // the IPreparedModel interface in the adapter service code.
- const auto* casted = static_cast<const PreparedModel*>(preparedModel.get());
- return casted->getUnderlyingPreparedModel();
-}
-
-nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
- const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels) {
- std::vector<nn::SharedPreparedModel> canonical;
- canonical.reserve(preparedModels.size());
- for (const auto& preparedModel : preparedModels) {
- canonical.push_back(NN_TRY(downcast(preparedModel)));
- }
- return canonical;
-}
-
-nn::GeneralResult<std::pair<sp<V1_3::IBuffer>, uint32_t>> allocate(
- const nn::SharedDevice& device, const V1_3::BufferDesc& desc,
- const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
- const hidl_vec<V1_3::BufferRole>& inputRoles,
- const hidl_vec<V1_3::BufferRole>& outputRoles) {
- auto nnDesc = NN_TRY(convertInput(desc));
- auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
- auto nnInputRoles = NN_TRY(convertInput(inputRoles));
- auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
-
- auto buffer = NN_TRY(device->allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
-
- const nn::Request::MemoryDomainToken token = buffer->getToken();
- auto hidlBuffer = sp<Buffer>::make(std::move(buffer));
- return std::make_pair(std::move(hidlBuffer), static_cast<uint32_t>(token));
-}
-
-} // namespace
-
-Device::Device(nn::SharedDevice device, Executor executor)
- : kDevice(std::move(device)), kExecutor(std::move(executor)) {
- CHECK(kDevice != nullptr);
- CHECK(kExecutor != nullptr);
-}
-
-Return<void> Device::getCapabilities(getCapabilities_cb cb) {
- const auto capabilities = V1_0::utils::convert(kDevice->getCapabilities()).value();
- cb(V1_0::ErrorStatus::NONE, capabilities);
- return Void();
-}
-
-Return<void> Device::getCapabilities_1_1(getCapabilities_1_1_cb cb) {
- const auto capabilities = V1_1::utils::convert(kDevice->getCapabilities()).value();
- cb(V1_0::ErrorStatus::NONE, capabilities);
- return Void();
-}
-
-Return<void> Device::getCapabilities_1_2(getCapabilities_1_2_cb cb) {
- const auto capabilities = V1_2::utils::convert(kDevice->getCapabilities()).value();
- cb(V1_0::ErrorStatus::NONE, capabilities);
- return Void();
-}
-
-Return<void> Device::getCapabilities_1_3(getCapabilities_1_3_cb cb) {
- const auto capabilities = V1_3::utils::convert(kDevice->getCapabilities()).value();
- cb(V1_3::ErrorStatus::NONE, capabilities);
- return Void();
-}
-
-Return<void> Device::getVersionString(getVersionString_cb cb) {
- cb(V1_0::ErrorStatus::NONE, kDevice->getVersionString());
- return Void();
-}
-
-Return<void> Device::getType(getType_cb cb) {
- const auto maybeDeviceType = V1_2::utils::convert(kDevice->getType());
- if (!maybeDeviceType.has_value()) {
- const auto& [message, code] = maybeDeviceType.error();
- LOG(ERROR) << "adapter::Device::getType failed with " << code << ": " << message;
- cb(V1_2::utils::convert(code).value(), {});
- } else {
- cb(V1_0::ErrorStatus::NONE, maybeDeviceType.value());
- }
- return Void();
-}
-
-Return<void> Device::getSupportedExtensions(getSupportedExtensions_cb cb) {
- const auto maybeSupportedExtensions = V1_2::utils::convert(kDevice->getSupportedExtensions());
- if (!maybeSupportedExtensions.has_value()) {
- const auto& [message, code] = maybeSupportedExtensions.error();
- LOG(ERROR) << "adapter::Device::getSupportedExtensions failed with " << code << ": "
- << message;
- cb(V1_2::utils::convert(code).value(), {});
- } else {
- cb(V1_0::ErrorStatus::NONE, maybeSupportedExtensions.value());
- }
- return Void();
-}
-
-Return<void> Device::getSupportedOperations(const V1_0::Model& model,
- getSupportedOperations_cb cb) {
- const auto result = adapter::getSupportedOperations(kDevice, model);
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- LOG(ERROR) << "adapter::Device::getSupportedOperations_1_0 failed with " << code << ": "
- << message;
- cb(V1_0::utils::convert(code).value(), {});
- } else {
- cb(V1_0::ErrorStatus::NONE, result.value());
- }
- return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_1(const V1_1::Model& model,
- getSupportedOperations_1_1_cb cb) {
- const auto result = adapter::getSupportedOperations(kDevice, model);
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- LOG(ERROR) << "adapter::Device::getSupportedOperations_1_1 failed with " << code << ": "
- << message;
- cb(V1_1::utils::convert(code).value(), {});
- } else {
- cb(V1_0::ErrorStatus::NONE, result.value());
- }
- return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_2(const V1_2::Model& model,
- getSupportedOperations_1_2_cb cb) {
- const auto result = adapter::getSupportedOperations(kDevice, model);
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- LOG(ERROR) << "adapter::Device::getSupportedOperations_1_2 failed with " << code << ": "
- << message;
- cb(V1_2::utils::convert(code).value(), {});
- } else {
- cb(V1_0::ErrorStatus::NONE, result.value());
- }
- return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_3(const V1_3::Model& model,
- getSupportedOperations_1_3_cb cb) {
- const auto result = adapter::getSupportedOperations(kDevice, model);
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- LOG(ERROR) << "adapter::Device::getSupportedOperations_1_3 failed with " << code << ": "
- << message;
- cb(V1_3::utils::convert(code).value(), {});
- } else {
- cb(V1_3::ErrorStatus::NONE, result.value());
- }
- return Void();
-}
-
-Return<void> Device::getNumberOfCacheFilesNeeded(getNumberOfCacheFilesNeeded_cb cb) {
- const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
- cb(V1_0::ErrorStatus::NONE, numModelCache, numDataCache);
- return Void();
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel(const V1_0::Model& model,
- const sp<V1_0::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModel(kDevice, kExecutor, model, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModel failed with " << code << ": " << message;
- notify(callback.get(), code, nullptr);
- return V1_0::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel_1_1(
- const V1_1::Model& model, V1_1::ExecutionPreference preference,
- const sp<V1_0::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModel_1_1(kDevice, kExecutor, model, preference, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModel_1_1 failed with " << code << ": " << message;
- notify(callback.get(), code, nullptr);
- return V1_1::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel_1_2(
- const V1_2::Model& model, V1_1::ExecutionPreference preference,
- const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
- const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModel_1_2(kDevice, kExecutor, model, preference, modelCache,
- dataCache, token, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModel_1_2 failed with " << code << ": " << message;
- notify(callback.get(), code, nullptr);
- return V1_2::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> Device::prepareModel_1_3(
- const V1_3::Model& model, V1_1::ExecutionPreference preference, V1_3::Priority priority,
- const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
- const sp<V1_3::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModel_1_3(kDevice, kExecutor, model, preference, priority,
- deadline, modelCache, dataCache, token, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModel_1_3 failed with " << code << ": " << message;
- notify(callback.get(), code, nullptr);
- return V1_3::utils::convert(code).value();
- }
- return V1_3::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModelFromCache(
- const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
- const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModelFromCache(kDevice, kExecutor, modelCache, dataCache, token,
- callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModelFromCache failed with " << code << ": "
- << message;
- notify(callback.get(), code, nullptr);
- return V1_2::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> Device::prepareModelFromCache_1_3(
- const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
- const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
- const sp<V1_3::IPreparedModelCallback>& callback) {
- auto result = adapter::prepareModelFromCache_1_3(kDevice, kExecutor, deadline, modelCache,
- dataCache, token, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::prepareModelFromCache_1_3 failed with " << code << ": "
- << message;
- notify(callback.get(), code, nullptr);
- return V1_3::utils::convert(code).value();
- }
- return V1_3::ErrorStatus::NONE;
-}
-
-Return<V1_0::DeviceStatus> Device::getStatus() {
- return V1_0::DeviceStatus::AVAILABLE;
-}
-
-Return<void> Device::allocate(const V1_3::BufferDesc& desc,
- const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
- const hidl_vec<V1_3::BufferRole>& inputRoles,
- const hidl_vec<V1_3::BufferRole>& outputRoles, allocate_cb cb) {
- auto result = adapter::allocate(kDevice, desc, preparedModels, inputRoles, outputRoles);
- if (!result.has_value()) {
- const auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::Device::allocate failed with " << code << ": " << message;
- cb(V1_3::utils::convert(code).value(), nullptr, /*token=*/0);
- return Void();
- }
- auto [buffer, token] = std::move(result).value();
- cb(V1_3::ErrorStatus::NONE, buffer, token);
- return Void();
-}
-
-} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/src/PreparedModel.cpp
deleted file mode 100644
index a14e782..0000000
--- a/neuralnetworks/utils/adapter/src/PreparedModel.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "PreparedModel.h"
-
-#include "Burst.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <hwbinder/IPCThreadState.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/Validation.h>
-#include <nnapi/hal/1.0/Utils.h>
-#include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/1.3/Conversions.h>
-#include <nnapi/hal/1.3/Utils.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <thread>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-template <typename Type>
-auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
- auto result = nn::convert(object);
- if (!result.has_value()) {
- result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
- }
- return result;
-}
-
-nn::GeneralResult<nn::Version> validateRequestForModel(const nn::Request& request,
- const nn::Model& model) {
- nn::GeneralResult<nn::Version> version = nn::validateRequestForModel(request, model);
- if (!version.ok()) {
- version.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
- }
- return version;
-}
-
-class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
- public:
- explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
- : kCallback(callback) {
- CHECK(callback != nullptr);
- }
-
- Return<void> getExecutionInfo(getExecutionInfo_cb cb) override {
- const auto result = kCallback();
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- const auto status =
- V1_3::utils::convert(code).value_or(V1_3::ErrorStatus::GENERAL_FAILURE);
- LOG(ERROR) << message;
- cb(status, V1_2::utils::kNoTiming, V1_2::utils::kNoTiming);
- return Void();
- }
- const auto [timingLaunched, timingFenced] = result.value();
- const auto hidlTimingLaunched = V1_3::utils::convert(timingLaunched).value();
- const auto hidlTimingFenced = V1_3::utils::convert(timingFenced).value();
- cb(V1_3::ErrorStatus::NONE, hidlTimingLaunched, hidlTimingFenced);
- return Void();
- }
-
- private:
- const nn::ExecuteFencedInfoCallback kCallback;
-};
-
-using ExecutionResult = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
-
-void notify(V1_0::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& /*outputShapes*/, const nn::Timing& /*timing*/) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_0::utils::convert(status).value();
- const auto ret = callback->notify(hidlStatus);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_0::IExecutionCallback::notify failed with " << ret.description();
- }
- }
-}
-
-void notify(V1_2::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_2::utils::convert(status).value();
- const auto hidlOutputShapes = V1_2::utils::convert(outputShapes).value();
- const auto hidlTiming = V1_2::utils::convert(timing).value();
- const auto ret = callback->notify_1_2(hidlStatus, hidlOutputShapes, hidlTiming);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_2::IExecutionCallback::notify_1_2 failed with " << ret.description();
- }
- }
-}
-
-void notify(V1_3::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_3::utils::convert(status).value();
- const auto hidlOutputShapes = V1_3::utils::convert(outputShapes).value();
- const auto hidlTiming = V1_3::utils::convert(timing).value();
- const auto ret = callback->notify_1_3(hidlStatus, hidlOutputShapes, hidlTiming);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_3::IExecutionCallback::notify_1_3 failed with " << ret.description();
- }
- }
-}
-
-template <typename CallbackType>
-void notify(CallbackType* callback, ExecutionResult result) {
- if (!result.has_value()) {
- const auto [message, status, outputShapes] = std::move(result).error();
- LOG(ERROR) << message;
- notify(callback, status, outputShapes, {});
- } else {
- const auto [outputShapes, timing] = std::move(result).value();
- notify(callback, nn::ErrorStatus::NONE, outputShapes, timing);
- }
-}
-
-nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_0::Request& request,
- const sp<V1_0::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
- auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {});
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- const sp<V1_2::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
- auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {});
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_3::Request& request,
- V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const sp<V1_3::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
- nnLoopTimeoutDuration, callback] {
- auto result =
- preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration);
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, nnDeadline);
-
- return {};
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
- const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
- V1_2::MeasureTiming measure) {
- const auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
-
- const auto [outputShapes, timing] =
- NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}));
-
- auto hidlOutputShapes = NN_TRY(V1_2::utils::convert(outputShapes));
- const auto hidlTiming = NN_TRY(V1_2::utils::convert(timing));
- return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously_1_3(
- const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
- V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
- const auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
-
- const auto [outputShapes, timing] =
- NN_TRY(preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration));
-
- auto hidlOutputShapes = NN_TRY(V1_3::utils::convert(outputShapes));
- const auto hidlTiming = NN_TRY(V1_3::utils::convert(timing));
- return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
- const hidl_vec<hidl_handle>& handles) {
- auto nnHandles = NN_TRY(convertInput(handles));
- std::vector<nn::SyncFence> syncFences;
- syncFences.reserve(handles.size());
- for (auto&& handle : nnHandles) {
- if (auto syncFence = nn::SyncFence::create(std::move(handle)); !syncFence.ok()) {
- return nn::error(nn::ErrorStatus::INVALID_ARGUMENT) << std::move(syncFence).error();
- } else {
- syncFences.push_back(std::move(syncFence).value());
- }
- }
- return syncFences;
-}
-
-nn::GeneralResult<sp<V1_2::IBurstContext>> configureExecutionBurst(
- const nn::SharedPreparedModel& preparedModel, const sp<V1_2::IBurstCallback>& callback,
- const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
- const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel) {
- auto burstExecutor = NN_TRY(preparedModel->configureExecutionBurst());
- return Burst::create(callback, requestChannel, resultChannel, std::move(burstExecutor),
- V1_2::utils::getBurstServerPollingTimeWindow());
-}
-
-nn::GeneralResult<std::pair<hidl_handle, sp<V1_3::IFencedExecutionCallback>>> executeFenced(
- const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
- const hidl_vec<hidl_handle>& waitFor, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const V1_3::OptionalTimeoutDuration& duration) {
- const auto nnRequest = NN_TRY(convertInput(request));
- const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
- const auto nnMeasure = NN_TRY(convertInput(measure));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
- const auto nnDuration = NN_TRY(convertInput(duration));
-
- auto [syncFence, executeFencedCallback] = NN_TRY(preparedModel->executeFenced(
- nnRequest, nnWaitFor, nnMeasure, nnDeadline, nnLoopTimeoutDuration, nnDuration));
-
- auto hidlSyncFence = NN_TRY(V1_3::utils::convert(syncFence.getSharedHandle()));
- auto hidlExecuteFencedCallback = sp<FencedExecutionCallback>::make(executeFencedCallback);
- return std::make_pair(std::move(hidlSyncFence), std::move(hidlExecuteFencedCallback));
-}
-
-} // namespace
-
-PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor, uid_t userId)
- : kPreparedModel(std::move(preparedModel)), kExecutor(std::move(executor)), kUserId(userId) {
- CHECK(kPreparedModel != nullptr);
- CHECK(kExecutor != nullptr);
-}
-
-nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
- return kPreparedModel;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
- const sp<V1_0::IExecutionCallback>& callback) {
- auto result = adapter::execute(kPreparedModel, kUserId, kExecutor, request, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_0::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- const sp<V1_2::IExecutionCallback>& callback) {
- auto result =
- adapter::execute_1_2(kPreparedModel, kUserId, kExecutor, request, measure, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_2::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> PreparedModel::execute_1_3(
- const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const sp<V1_3::IExecutionCallback>& callback) {
- auto result = adapter::execute_1_3(kPreparedModel, kUserId, kExecutor, request, measure,
- deadline, loopTimeoutDuration, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute_1_3 failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_3::utils::convert(code).value();
- }
- return V1_3::ErrorStatus::NONE;
-}
-
-Return<void> PreparedModel::executeSynchronously(const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- executeSynchronously_cb cb) {
- auto result = adapter::executeSynchronously(kPreparedModel, request, measure);
- if (!result.has_value()) {
- auto [message, code, outputShapes] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeSynchronously failed with " << code << ": "
- << message;
- cb(V1_2::utils::convert(code).value(), V1_2::utils::convert(outputShapes).value(),
- V1_2::utils::kNoTiming);
- return Void();
- }
- auto [outputShapes, timing] = std::move(result).value();
- cb(V1_0::ErrorStatus::NONE, outputShapes, timing);
- return Void();
-}
-
-Return<void> PreparedModel::executeSynchronously_1_3(
- const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration, executeSynchronously_1_3_cb cb) {
- auto result = adapter::executeSynchronously_1_3(kPreparedModel, request, measure, deadline,
- loopTimeoutDuration);
- if (!result.has_value()) {
- auto [message, code, outputShapes] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeSynchronously_1_3 failed with " << code
- << ": " << message;
- cb(V1_3::utils::convert(code).value(), V1_3::utils::convert(outputShapes).value(),
- V1_2::utils::kNoTiming);
- return Void();
- }
- auto [outputShapes, timing] = std::move(result).value();
- cb(V1_3::ErrorStatus::NONE, outputShapes, timing);
- return Void();
-}
-
-Return<void> PreparedModel::configureExecutionBurst(
- const sp<V1_2::IBurstCallback>& callback,
- const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
- const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
- configureExecutionBurst_cb cb) {
- auto result = adapter::configureExecutionBurst(kPreparedModel, callback, requestChannel,
- resultChannel);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::configureExecutionBurst failed with " << code << ": "
- << message;
- cb(V1_2::utils::convert(code).value(), nullptr);
- return Void();
- }
- auto burstContext = std::move(result).value();
- cb(V1_0::ErrorStatus::NONE, std::move(burstContext));
- return Void();
-}
-
-Return<void> PreparedModel::executeFenced(const V1_3::Request& request,
- const hidl_vec<hidl_handle>& waitFor,
- V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const V1_3::OptionalTimeoutDuration& duration,
- executeFenced_cb callback) {
- auto result = adapter::executeFenced(kPreparedModel, request, waitFor, measure, deadline,
- loopTimeoutDuration, duration);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeFenced failed with " << code << ": "
- << message;
- callback(V1_3::utils::convert(code).value(), {}, nullptr);
- return Void();
- }
- auto [syncFence, executeFencedCallback] = std::move(result).value();
- callback(V1_3::ErrorStatus::NONE, syncFence, executeFencedCallback);
- return Void();
-}
-
-} // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index 39927a3..91fca2f 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -36,23 +36,16 @@
cc_test {
name: "neuralnetworks_utils_hal_common_test",
host_supported: true,
+ tidy_timeout_srcs: ["test/ResilientDeviceTest.cpp"],
srcs: ["test/*.cpp"],
static_libs: [
"libgmock",
- "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
],
shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
"libbase",
"libcutils",
- "libfmq",
- "libhidlbase",
- "libhidlmemory",
- "liblog",
- "libutils",
],
target: {
android: {
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
index ae0d092..c04294a 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -20,6 +20,7 @@
#include <nnapi/Result.h>
#include <nnapi/SharedMemory.h>
#include <nnapi/Types.h>
+
#include <functional>
#include <vector>
@@ -47,81 +48,10 @@
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. If `model` has no Operand::LifeTime::POINTER data,
-// the function returns with a reference to `model`. If `model` has Operand::LifeTime::POINTER data,
-// the model is copied to `maybeModelInSharedOut` with the POINTER data relocated to a memory pool,
-// and the function returns with a reference to `*maybeModelInSharedOut`.
-nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
- const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut);
-
-// Record a relocation mapping between pointer-based data and shared memory.
-// Only two specializations of this template may exist:
-// - RelocationInfo<const void*> for request inputs
-// - RelocationInfo<void*> for request outputs
-template <typename PointerType>
-struct RelocationInfo {
- PointerType data;
- size_t length;
- size_t offset;
-};
-using InputRelocationInfo = RelocationInfo<const void*>;
-using OutputRelocationInfo = RelocationInfo<void*>;
-
-// Keep track of the relocation mapping between pointer-based data and shared memory pool,
-// and provide method to copy the data between pointers and the shared memory pool.
-// Only two specializations of this template may exist:
-// - RelocationTracker<InputRelocationInfo> for request inputs
-// - RelocationTracker<OutputRelocationInfo> for request outputs
-template <typename RelocationInfoType>
-class RelocationTracker {
- public:
- static nn::GeneralResult<std::unique_ptr<RelocationTracker>> create(
- std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory) {
- auto mapping = NN_TRY(map(memory));
- return std::make_unique<RelocationTracker<RelocationInfoType>>(
- std::move(relocationInfos), std::move(memory), std::move(mapping));
- }
-
- RelocationTracker(std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory,
- nn::Mapping mapping)
- : kRelocationInfos(std::move(relocationInfos)),
- kMemory(std::move(memory)),
- kMapping(std::move(mapping)) {}
-
- // Specializations defined in CommonUtils.cpp.
- // For InputRelocationTracker, this method will copy pointer data to the shared memory pool.
- // For OutputRelocationTracker, this method will copy shared memory data to the pointers.
- void flush() const;
-
- private:
- const std::vector<RelocationInfoType> kRelocationInfos;
- const nn::SharedMemory kMemory;
- const nn::Mapping kMapping;
-};
-using InputRelocationTracker = RelocationTracker<InputRelocationInfo>;
-using OutputRelocationTracker = RelocationTracker<OutputRelocationInfo>;
-
-struct RequestRelocation {
- std::unique_ptr<InputRelocationTracker> input;
- std::unique_ptr<OutputRelocationTracker> output;
-};
-
-// Relocate pointer-based data to shared memory. If `request` has no
-// Request::Argument::LifeTime::POINTER data, the function returns with a reference to `request`. If
-// `request` has Request::Argument::LifeTime::POINTER data, the request is copied to
-// `maybeRequestInSharedOut` with the POINTER data relocated to a memory pool, and the function
-// returns with a reference to `*maybeRequestInSharedOut`. The `relocationOut` will be set to track
-// the input and output relocations.
-//
-// Unlike `flushDataFromPointerToShared`, this method will not copy the input pointer data to the
-// shared memory pool. Use `relocationOut` to flush the input or output data after the call.
-nn::GeneralResult<std::reference_wrapper<const nn::Request>> convertRequestFromPointerToShared(
- const nn::Request* request, uint32_t alignment, uint32_t padding,
- std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut);
+using nn::convertRequestFromPointerToShared;
+using nn::flushDataFromPointerToShared;
+using nn::hasNoPointerData;
+using nn::RequestRelocation;
} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
index e86edda..1f1245f 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
@@ -33,12 +33,15 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
};
} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
index 5e62b9a..9582873 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -52,8 +52,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
index de30aae..3f1f290 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -31,18 +31,23 @@
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::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
index fde2486..129431f 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
@@ -48,18 +48,23 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
private:
bool isValidInternal() const EXCLUDES(mMutex);
nn::GeneralResult<nn::SharedExecution> createReusableExecutionInternal(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
const Factory kMakeBurst;
mutable std::mutex mMutex;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 84ae799..267d634 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -65,8 +65,9 @@
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
@@ -83,7 +84,9 @@
nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
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;
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCacheInternal(
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
index 86533ed..bbfc220 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -49,18 +49,23 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) 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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedExecution> createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const override;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
@@ -70,7 +75,9 @@
bool isValidInternal() const EXCLUDES(mMutex);
nn::GeneralResult<nn::SharedExecution> createReusableExecutionInternal(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const;
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& metaData,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
nn::GeneralResult<nn::SharedBurst> configureExecutionBurstInternal() const;
const Factory kMakePreparedModel;
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index b249881..dd55add 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -31,59 +31,6 @@
#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,
@@ -104,131 +51,4 @@
.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;
-}
-
-template <>
-void InputRelocationTracker::flush() const {
- // Copy from pointers to shared memory.
- uint8_t* memoryPtr = static_cast<uint8_t*>(std::get<void*>(kMapping.pointer));
- for (const auto& [data, length, offset] : kRelocationInfos) {
- std::memcpy(memoryPtr + offset, data, length);
- }
-}
-
-template <>
-void OutputRelocationTracker::flush() const {
- // Copy from shared memory to pointers.
- const uint8_t* memoryPtr = static_cast<const uint8_t*>(
- std::visit([](auto ptr) { return static_cast<const void*>(ptr); }, kMapping.pointer));
- for (const auto& [data, length, offset] : kRelocationInfos) {
- std::memcpy(data, memoryPtr + offset, length);
- }
-}
-
-nn::GeneralResult<std::reference_wrapper<const nn::Request>> convertRequestFromPointerToShared(
- const nn::Request* request, uint32_t alignment, uint32_t padding,
- std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut) {
- CHECK(request != nullptr);
- CHECK(maybeRequestInSharedOut != nullptr);
- CHECK(relocationOut != 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;
-
- RequestRelocation relocation;
-
- // Change input pointers to shared memory.
- nn::MutableMemoryBuilder inputBuilder(requestInShared.pools.size());
- std::vector<InputRelocationInfo> inputRelocationInfos;
- 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(location.length, alignment, padding);
- inputRelocationInfos.push_back({data, input.location.length, input.location.offset});
- }
-
- // Allocate input memory.
- if (!inputBuilder.empty()) {
- auto memory = NN_TRY(inputBuilder.finish());
- requestInShared.pools.push_back(memory);
- relocation.input = NN_TRY(
- InputRelocationTracker::create(std::move(inputRelocationInfos), std::move(memory)));
- }
-
- // Change output pointers to shared memory.
- nn::MutableMemoryBuilder outputBuilder(requestInShared.pools.size());
- std::vector<OutputRelocationInfo> outputRelocationInfos;
- 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;
- void* data = std::get<void*>(location.pointer);
- CHECK(data != nullptr);
- output.location = outputBuilder.append(location.length, alignment, padding);
- outputRelocationInfos.push_back({data, output.location.length, output.location.offset});
- }
-
- // Allocate output memory.
- if (!outputBuilder.empty()) {
- auto memory = NN_TRY(outputBuilder.finish());
- requestInShared.pools.push_back(memory);
- relocation.output = NN_TRY(OutputRelocationTracker::create(std::move(outputRelocationInfos),
- std::move(memory)));
- }
-
- *maybeRequestInSharedOut = requestInShared;
- *relocationOut = std::move(relocation);
- return **maybeRequestInSharedOut;
-}
-
} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidBurst.cpp b/neuralnetworks/utils/common/src/InvalidBurst.cpp
index 0191533..3fdfb5c 100644
--- a/neuralnetworks/utils/common/src/InvalidBurst.cpp
+++ b/neuralnetworks/utils/common/src/InvalidBurst.cpp
@@ -34,13 +34,17 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> InvalidBurst::execute(
const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
const nn::OptionalTimePoint& /*deadline*/,
- const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidBurst";
}
nn::GeneralResult<nn::SharedExecution> InvalidBurst::createReusableExecution(
const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
- const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidBurst";
}
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
index 535ccb4..c8cc287 100644
--- a/neuralnetworks/utils/common/src/InvalidDevice.cpp
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -84,7 +84,9 @@
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 {
+ const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidDevice";
}
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
index 8195462..f6f978d 100644
--- a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -27,9 +27,12 @@
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::OptionalDuration& /*loopTimeoutDuration*/) const {
+InvalidPreparedModel::execute(
+ const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
+ const nn::OptionalTimePoint& /*deadline*/,
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidPreparedModel";
}
@@ -38,13 +41,17 @@
const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
const nn::OptionalDuration& /*loopTimeoutDuration*/,
- const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+ const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidPreparedModel";
}
nn::GeneralResult<nn::SharedExecution> InvalidPreparedModel::createReusableExecution(
const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
- const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+ const nn::OptionalDuration& /*loopTimeoutDuration*/,
+ const std::vector<nn::TokenValuePair>& /*hints*/,
+ const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
return NN_ERROR() << "InvalidPreparedModel";
}
diff --git a/neuralnetworks/utils/common/src/ResilientBurst.cpp b/neuralnetworks/utils/common/src/ResilientBurst.cpp
index 79cbe39..bf7a8ea 100644
--- a/neuralnetworks/utils/common/src/ResilientBurst.cpp
+++ b/neuralnetworks/utils/common/src/ResilientBurst.cpp
@@ -105,37 +105,49 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> ResilientBurst::execute(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalTimePoint& deadline,
- const nn::OptionalDuration& loopTimeoutDuration) const {
- const auto fn = [&request, measure, deadline, loopTimeoutDuration](const nn::IBurst& burst) {
- return burst.execute(request, measure, deadline, loopTimeoutDuration);
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ const auto fn = [&request, measure, deadline, loopTimeoutDuration, &hints,
+ &extensionNameToPrefix](const nn::IBurst& burst) {
+ return burst.execute(request, measure, deadline, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
};
return protect(*this, fn);
}
nn::GeneralResult<nn::SharedExecution> ResilientBurst::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
#if 0
auto self = shared_from_this();
- ResilientExecution::Factory makeExecution =
- [burst = std::move(self), request, measure, loopTimeoutDuration] {
- return burst->createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+ ResilientExecution::Factory makeExecution = [burst = std::move(self), request, measure,
+ loopTimeoutDuration, &hints,
+ &extensionNameToPrefix] {
+ return burst->createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
};
return ResilientExecution::create(std::move(makeExecution));
#else
- return createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+ return createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
#endif
}
nn::GeneralResult<nn::SharedExecution> ResilientBurst::createReusableExecutionInternal(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
if (!isValidInternal()) {
return std::make_shared<const InvalidExecution>();
}
- const auto fn = [&request, measure, &loopTimeoutDuration](const nn::IBurst& burst) {
- return burst.createReusableExecution(request, measure, loopTimeoutDuration);
+ const auto fn = [&request, measure, &loopTimeoutDuration, &hints,
+ &extensionNameToPrefix](const nn::IBurst& burst) {
+ return burst.createReusableExecution(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
};
return protect(*this, fn);
}
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 2023c9a..a5c2640 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -179,19 +179,21 @@
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 {
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
#if 0
auto self = shared_from_this();
ResilientPreparedModel::Factory makePreparedModel = [device = std::move(self), model,
preference, priority, deadline, modelCache,
- dataCache, token] {
+ dataCache, token, hints, extensionNameToPrefix] {
return device->prepareModelInternal(model, preference, priority, deadline, modelCache,
- dataCache, token);
+ dataCache, token, hints, extensionNameToPrefix);
};
return ResilientPreparedModel::create(std::move(makePreparedModel));
#else
- return prepareModelInternal(model, preference, priority, deadline, modelCache, dataCache,
- token);
+ return prepareModelInternal(model, preference, priority, deadline, modelCache, dataCache, token,
+ hints, extensionNameToPrefix);
#endif
}
@@ -234,14 +236,16 @@
nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
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 {
+ const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
if (!isValidInternal()) {
return std::make_shared<const InvalidPreparedModel>();
}
- const auto fn = [&model, preference, priority, &deadline, &modelCache, &dataCache,
- &token](const nn::IDevice& device) {
+ const auto fn = [&model, preference, priority, &deadline, &modelCache, &dataCache, &token,
+ &hints, &extensionNameToPrefix](const nn::IDevice& device) {
return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
- token);
+ token, hints, extensionNameToPrefix);
};
return protect(*this, fn, /*blocking=*/false);
}
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
index 1ae19bc..b5843c0 100644
--- a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -104,43 +104,53 @@
}
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::OptionalDuration& loopTimeoutDuration) const {
- const auto fn = [&request, measure, &deadline,
- &loopTimeoutDuration](const nn::IPreparedModel& preparedModel) {
- return preparedModel.execute(request, measure, deadline, loopTimeoutDuration);
+ResilientPreparedModel::execute(
+ const nn::Request& request, nn::MeasureTiming measure,
+ const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+ const auto fn = [&request, measure, &deadline, &loopTimeoutDuration, &hints,
+ &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
+ return preparedModel.execute(request, measure, deadline, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
};
return protect(*this, fn);
}
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::OptionalDuration& loopTimeoutDuration,
- const nn::OptionalDuration& timeoutDurationAfterFence) const {
+ResilientPreparedModel::executeFenced(
+ const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+ nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const nn::OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
const auto fn = [&request, &waitFor, measure, &deadline, &loopTimeoutDuration,
- &timeoutDurationAfterFence](const nn::IPreparedModel& preparedModel) {
+ &timeoutDurationAfterFence, &hints,
+ &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
return preparedModel.executeFenced(request, waitFor, measure, deadline, loopTimeoutDuration,
- timeoutDurationAfterFence);
+ timeoutDurationAfterFence, hints, extensionNameToPrefix);
};
return protect(*this, fn);
}
nn::GeneralResult<nn::SharedExecution> ResilientPreparedModel::createReusableExecution(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
#if 0
auto self = shared_from_this();
- ResilientExecution::Factory makeExecution =
- [preparedModel = std::move(self), request, measure, loopTimeoutDuration] {
- return preparedModel->createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+ ResilientExecution::Factory makeExecution = [preparedModel = std::move(self), request, measure,
+ loopTimeoutDuration, hints,
+ extensionNameToPrefix] {
+ return preparedModel->createReusableExecutionInternal(request, measure, loopTimeoutDuration,
+ hints, extensionNameToPrefix);
};
return ResilientExecution::create(std::move(makeExecution));
#else
- return createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+ return createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
#endif
}
@@ -159,13 +169,16 @@
nn::GeneralResult<nn::SharedExecution> ResilientPreparedModel::createReusableExecutionInternal(
const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration) const {
+ const nn::OptionalDuration& loopTimeoutDuration,
+ const std::vector<nn::TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
if (!isValidInternal()) {
return std::make_shared<const InvalidExecution>();
}
- const auto fn = [&request, measure,
- &loopTimeoutDuration](const nn::IPreparedModel& preparedModel) {
- return preparedModel.createReusableExecution(request, measure, loopTimeoutDuration);
+ const auto fn = [&request, measure, &loopTimeoutDuration, &hints,
+ &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
+ return preparedModel.createReusableExecution(request, measure, loopTimeoutDuration, hints,
+ extensionNameToPrefix);
};
return protect(*this, fn);
}
diff --git a/neuralnetworks/utils/common/test/MockDevice.h b/neuralnetworks/utils/common/test/MockDevice.h
index a9428bc..a0fc5c3 100644
--- a/neuralnetworks/utils/common/test/MockDevice.h
+++ b/neuralnetworks/utils/common/test/MockDevice.h
@@ -39,7 +39,9 @@
MOCK_METHOD(GeneralResult<SharedPreparedModel>, prepareModel,
(const Model& model, ExecutionPreference preference, Priority priority,
OptionalTimePoint deadline, const std::vector<SharedHandle>& modelCache,
- const std::vector<SharedHandle>& dataCache, const CacheToken& token),
+ const std::vector<SharedHandle>& dataCache, const CacheToken& token,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
(const, override));
MOCK_METHOD(GeneralResult<SharedPreparedModel>, prepareModelFromCache,
(OptionalTimePoint deadline, const std::vector<SharedHandle>& modelCache,
diff --git a/neuralnetworks/utils/common/test/MockPreparedModel.h b/neuralnetworks/utils/common/test/MockPreparedModel.h
index c8ce006..b8613b2 100644
--- a/neuralnetworks/utils/common/test/MockPreparedModel.h
+++ b/neuralnetworks/utils/common/test/MockPreparedModel.h
@@ -27,17 +27,23 @@
public:
MOCK_METHOD((ExecutionResult<std::pair<std::vector<OutputShape>, Timing>>), execute,
(const Request& request, MeasureTiming measure, const OptionalTimePoint& deadline,
- const OptionalDuration& loopTimeoutDuration),
+ const OptionalDuration& loopTimeoutDuration,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
(const, override));
MOCK_METHOD((GeneralResult<std::pair<SyncFence, ExecuteFencedInfoCallback>>), executeFenced,
(const Request& request, const std::vector<SyncFence>& waitFor,
MeasureTiming measure, const OptionalTimePoint& deadline,
const OptionalDuration& loopTimeoutDuration,
- const OptionalDuration& timeoutDurationAfterFence),
+ const OptionalDuration& timeoutDurationAfterFence,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
(const, override));
MOCK_METHOD((GeneralResult<SharedExecution>), createReusableExecution,
- (const nn::Request& request, nn::MeasureTiming measure,
- const nn::OptionalDuration& loopTimeoutDuration),
+ (const Request& request, MeasureTiming measure,
+ const OptionalDuration& loopTimeoutDuration,
+ const std::vector<TokenValuePair>& hints,
+ const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
(const, override));
MOCK_METHOD(GeneralResult<SharedBurst>, configureExecutionBurst, (), (const, override));
MOCK_METHOD(std::any, getUnderlyingResource, (), (const, override));
diff --git a/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp b/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
index 0488b63..d9b8505 100644
--- a/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
+++ b/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
@@ -309,12 +309,12 @@
// setup call
const auto [mockDevice, mockDeviceFactory, device] = setup();
const auto mockPreparedModel = std::make_shared<const nn::MockPreparedModel>();
- EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+ EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Return(mockPreparedModel));
// run test
- const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+ const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -324,12 +324,12 @@
TEST(ResilientDeviceTest, prepareModelError) {
// setup call
const auto [mockDevice, mockDeviceFactory, device] = setup();
- EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+ EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnGeneralFailure);
// run test
- const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+ const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -339,13 +339,13 @@
TEST(ResilientDeviceTest, prepareModelDeadObjectFailedRecovery) {
// setup call
const auto [mockDevice, mockDeviceFactory, device] = setup();
- EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+ EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnDeadObject);
EXPECT_CALL(*mockDeviceFactory, Call(false)).Times(1).WillOnce(kReturnGeneralFailure);
// run test
- const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+ const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -355,18 +355,18 @@
TEST(ResilientDeviceTest, prepareModelDeadObjectSuccessfulRecovery) {
// setup call
const auto [mockDevice, mockDeviceFactory, device] = setup();
- EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+ EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnDeadObject);
const auto recoveredMockDevice = createConfiguredMockDevice();
const auto mockPreparedModel = std::make_shared<const nn::MockPreparedModel>();
- EXPECT_CALL(*recoveredMockDevice, prepareModel(_, _, _, _, _, _, _))
+ EXPECT_CALL(*recoveredMockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Return(mockPreparedModel));
EXPECT_CALL(*mockDeviceFactory, Call(false)).Times(1).WillOnce(Return(recoveredMockDevice));
// run test
- const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+ const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -679,7 +679,7 @@
device->recover(mockDevice.get(), /*blocking=*/false);
// run test
- auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+ auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
diff --git a/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp b/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
index d396ca8..276bfba 100644
--- a/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
+++ b/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
@@ -104,12 +104,12 @@
TEST(ResilientPreparedModelTest, execute) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _))
+ EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(kNoExecutionError));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -119,10 +119,12 @@
TEST(ResilientPreparedModelTest, executeError) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnGeneralFailure);
+ EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(kReturnGeneralFailure);
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -132,12 +134,12 @@
TEST(ResilientPreparedModelTest, executeDeadObjectFailedRecovery) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
+ EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
constexpr auto ret = [] { return nn::error(nn::ErrorStatus::GENERAL_FAILURE); };
EXPECT_CALL(*mockPreparedModelFactory, Call()).Times(1).WillOnce(ret);
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -147,9 +149,9 @@
TEST(ResilientPreparedModelTest, executeDeadObjectSuccessfulRecovery) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
+ EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
const auto recoveredMockPreparedModel = createConfiguredMockPreparedModel();
- EXPECT_CALL(*recoveredMockPreparedModel, execute(_, _, _, _))
+ EXPECT_CALL(*recoveredMockPreparedModel, execute(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(kNoExecutionError));
EXPECT_CALL(*mockPreparedModelFactory, Call())
@@ -157,7 +159,7 @@
.WillOnce(Return(recoveredMockPreparedModel));
// run test
- const auto result = preparedModel->execute({}, {}, {}, {});
+ const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -167,12 +169,12 @@
TEST(ResilientPreparedModelTest, executeFenced) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Return(kNoFencedExecutionError));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -182,12 +184,12 @@
TEST(ResilientPreparedModelTest, executeFencedError) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnGeneralFailure);
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -197,13 +199,13 @@
TEST(ResilientPreparedModelTest, executeFencedDeadObjectFailedRecovery) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnDeadObject);
EXPECT_CALL(*mockPreparedModelFactory, Call()).Times(1).WillOnce(kReturnGeneralFailure);
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
@@ -213,11 +215,11 @@
TEST(ResilientPreparedModelTest, executeFencedDeadObjectSuccessfulRecovery) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(kReturnDeadObject);
const auto recoveredMockPreparedModel = createConfiguredMockPreparedModel();
- EXPECT_CALL(*recoveredMockPreparedModel, executeFenced(_, _, _, _, _, _))
+ EXPECT_CALL(*recoveredMockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Return(kNoFencedExecutionError));
EXPECT_CALL(*mockPreparedModelFactory, Call())
@@ -225,7 +227,7 @@
.WillOnce(Return(recoveredMockPreparedModel));
// run test
- const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+ const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -235,12 +237,12 @@
TEST(ResilientPreparedModelTest, createReusableExecution) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _, _, _))
.Times(1)
.WillOnce(Return(kNoCreateReusableExecutionError));
// run test
- const auto result = preparedModel->createReusableExecution({}, {}, {});
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
// verify result
ASSERT_TRUE(result.has_value())
@@ -250,12 +252,12 @@
TEST(ResilientPreparedModelTest, createReusableExecutionError) {
// setup call
const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
- EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+ EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _, _, _))
.Times(1)
.WillOnce(kReturnGeneralFailure);
// run test
- const auto result = preparedModel->createReusableExecution({}, {}, {});
+ const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
// verify result
ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index c3272ae..452078b 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -33,6 +33,10 @@
local_include_dirs: ["include/nnapi/hal"],
export_include_dirs: ["include"],
static_libs: [
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
"neuralnetworks_types",
"neuralnetworks_utils_hal_1_0",
"neuralnetworks_utils_hal_1_1",
@@ -40,10 +44,4 @@
"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
index 2fd5237..38d2a54 100644
--- a/neuralnetworks/utils/service/include/nnapi/hal/Service.h
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -24,12 +24,16 @@
namespace android::hardware::neuralnetworks::service {
-struct SharedDeviceAndUpdatability {
- nn::SharedDevice device;
- bool isDeviceUpdatable = false;
-};
-
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers);
+/**
+ * @brief Get the NNAPI sAIDL and HIDL services declared in the VINTF.
+ *
+ * @pre maxFeatureLevelAllowed >= Version::Level::FEATURE_LEVEL_5
+ *
+ * @param maxFeatureLevelAllowed Maximum version of driver allowed to be used. Any driver version
+ * exceeding this must be clamped to `maxFeatureLevelAllowed`.
+ * @return A list of devices and whether each device is updatable or not.
+ */
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed);
} // namespace android::hardware::neuralnetworks::service
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index 2286288..dd37dae 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -51,7 +51,7 @@
using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
- std::vector<SharedDeviceAndUpdatability>* devices,
+ std::vector<nn::SharedDevice>* devices,
std::unordered_set<std::string>* registeredDevices) {
CHECK(devices != nullptr);
CHECK(registeredDevices != nullptr);
@@ -63,7 +63,7 @@
if (maybeDevice.has_value()) {
auto device = std::move(maybeDevice).value();
CHECK(device != nullptr);
- devices->push_back({.device = std::move(device)});
+ devices->push_back(std::move(device));
} else {
LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
<< ": " << maybeDevice.error().message;
@@ -72,9 +72,9 @@
}
}
-void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
+void getAidlDevices(std::vector<nn::SharedDevice>* devices,
std::unordered_set<std::string>* registeredDevices,
- bool includeUpdatableDrivers) {
+ nn::Version::Level maxFeatureLevelAllowed) {
CHECK(devices != nullptr);
CHECK(registeredDevices != nullptr);
@@ -91,21 +91,12 @@
}
for (const auto& name : names) {
- bool isDeviceUpdatable = false;
- if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
- const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name;
- isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str());
- }
- if (isDeviceUpdatable && !includeUpdatableDrivers) {
- continue;
- }
if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
- auto maybeDevice = aidl_hal::utils::getDevice(name);
+ auto maybeDevice = aidl_hal::utils::getDevice(name, maxFeatureLevelAllowed);
if (maybeDevice.has_value()) {
auto device = std::move(maybeDevice).value();
CHECK(device != nullptr);
- devices->push_back(
- {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable});
+ devices->push_back(std::move(device));
} else {
LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
<< ": " << maybeDevice.error().message;
@@ -116,11 +107,13 @@
} // namespace
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers) {
- std::vector<SharedDeviceAndUpdatability> devices;
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed) {
+ std::vector<nn::SharedDevice> devices;
std::unordered_set<std::string> registeredDevices;
- getAidlDevices(&devices, ®isteredDevices, includeUpdatableDrivers);
+ CHECK_GE(maxFeatureLevelAllowed, nn::Version::Level::FEATURE_LEVEL_5);
+
+ getAidlDevices(&devices, ®isteredDevices, maxFeatureLevelAllowed);
getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
®isteredDevices);
diff --git a/nfc/OWNERS b/nfc/OWNERS
new file mode 100644
index 0000000..7867204
--- /dev/null
+++ b/nfc/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 48448
+alisher@google.com
+georgekgchang@google.com
+jackcwyu@google.com
+
+
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
new file mode 100644
index 0000000..30365f6
--- /dev/null
+++ b/nfc/aidl/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.nfc",
+ vendor_available: true,
+ srcs: ["android/hardware/nfc/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ enabled: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/nfc/aidl/TEST_MAPPING b/nfc/aidl/TEST_MAPPING
new file mode 100644
index 0000000..3a10084
--- /dev/null
+++ b/nfc/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsAidlHalNfcTargetTest"
+ }
+ ]
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..7a0ae54
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+interface INfc {
+ void open(in android.hardware.nfc.INfcClientCallback clientCallback);
+ void close(in android.hardware.nfc.NfcCloseType type);
+ void coreInitialized();
+ void factoryReset();
+ android.hardware.nfc.NfcConfig getConfig();
+ void powerCycle();
+ void preDiscover();
+ int write(in byte[] data);
+ void setEnableVerboseLogging(in boolean enable);
+ boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..8150e81
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+interface INfcClientCallback {
+ void sendData(in byte[] data);
+ void sendEvent(in android.hardware.nfc.NfcEvent event, in android.hardware.nfc.NfcStatus status);
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..7d44d48
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcCloseType {
+ DISABLE = 0,
+ HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..92e0a9a
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+parcelable NfcConfig {
+ boolean nfaPollBailOutMode;
+ android.hardware.nfc.PresenceCheckAlgorithm presenceCheckAlgorithm;
+ android.hardware.nfc.ProtocolDiscoveryConfig nfaProprietaryCfg;
+ byte defaultOffHostRoute;
+ byte defaultOffHostRouteFelica;
+ byte defaultSystemCodeRoute;
+ byte defaultSystemCodePowerState;
+ byte defaultRoute;
+ byte offHostESEPipeId;
+ byte offHostSIMPipeId;
+ int maxIsoDepTransceiveLength;
+ byte[] hostAllowlist;
+ byte[] offHostRouteUicc;
+ byte[] offHostRouteEse;
+ byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..dda258e
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcEvent {
+ OPEN_CPLT = 0,
+ CLOSE_CPLT = 1,
+ POST_INIT_CPLT = 2,
+ PRE_DISCOVER_CPLT = 3,
+ HCI_NETWORK_RESET = 4,
+ ERROR = 5,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..2632480
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcStatus {
+ OK = 0,
+ FAILED = 1,
+ ERR_TRANSPORT = 2,
+ ERR_CMD_TIMEOUT = 3,
+ REFUSED = 4,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..9a9be21
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="byte") @VintfStability
+enum PresenceCheckAlgorithm {
+ DEFAULT = 0,
+ I_BLOCK = 1,
+ ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..021dfe2
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+ byte protocol18092Active;
+ byte protocolBPrime;
+ byte protocolDual;
+ byte protocol15693;
+ byte protocolKovio;
+ byte protocolMifare;
+ byte discoveryPollKovio;
+ byte discoveryPollBPrime;
+ byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfc.aidl b/nfc/aidl/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..662f8d4
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+import android.hardware.nfc.INfcClientCallback;
+import android.hardware.nfc.NfcCloseType;
+import android.hardware.nfc.NfcConfig;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfc {
+ /**
+ * Opens the NFC controller device and performs initialization.
+ * This may include patch download and other vendor-specific initialization.
+ *
+ * If open completes successfully, the controller must be ready to perform NCI
+ * initialization - ie accept CORE_RESET and subsequent commands through the write()
+ * call.
+ *
+ * Returns ok() if initialization starts successfully.
+ * If open() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+ * callback before continuing.
+ * If a NfcEvent.OPEN_CPLT callback received with status NfcStatus::OK, the controller
+ * must be ready to perform NCI initialization - ie accept CORE_RESET and subsequent
+ * commands through the write() call.
+ */
+ void open(in INfcClientCallback clientCallback);
+
+ /**
+ * Close the NFC HAL and setup NFC controller close type.
+ * Associated resources such as clientCallback must be released.
+ * The clientCallback reference from open() must be invalid after close().
+ * If close() returns ok(), the NCI stack must wait for a NfcEvent.CLOSE_CPLT
+ * callback before continuing.
+ * Returns an error if close may be called more than once.
+ * Calls to any other method which expect a callback after this must return
+ * a service-specific error NfcStatus::FAILED.
+ * HAL close automatically if the client drops the reference to the HAL or
+ * crashes.
+ */
+ void close(in NfcCloseType type);
+
+ /**
+ * coreInitialized() is called after the CORE_INIT_RSP is received from the
+ * NFCC. At this time, the HAL can do any chip-specific configuration.
+ *
+ * If coreInitialized() returns ok(), the NCI stack must wait for a
+ * NfcEvent.POST_INIT_CPLT before continuing.
+ * If coreInitialized() returns an error, the NCI stack must continue immediately.
+ *
+ * coreInitialized() must be called after open() registers the clientCallback
+ * or return a service-specific error NfcStatus::FAILED directly.
+ *
+ */
+ void coreInitialized();
+
+ /**
+ * Clears the NFC chip.
+ *
+ * Must be called during factory reset and/or before the first time the HAL is
+ * initialized after a factory reset.
+ */
+ void factoryReset();
+
+ /**
+ * Fetches vendor specific configurations.
+ * @return NfcConfig indicates support for certain features and
+ * populates the vendor specific configs.
+ */
+ NfcConfig getConfig();
+
+ /**
+ * Restart controller by power cyle;
+ * It's similar to open but just reset the controller without initialize all the
+ * resources.
+ *
+ * If powerCycle() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+ * before continuing.
+ *
+ * powerCycle() must be called after open() registers the clientCallback
+ * or return a service-specific error NfcStatus::FAILED directly.
+ */
+ void powerCycle();
+
+ /**
+ * preDiscover is called every time before starting RF discovery.
+ * It is a good place to do vendor-specific configuration that must be
+ * performed every time RF discovery is about to be started.
+ *
+ * If preDiscover() returns ok(), the NCI stack must wait for a
+ * NfcEvent.PREDISCOVER_CPLT before continuing.
+ *
+ * preDiscover() must be called after open() registers the clientCallback
+ * or return a service-specific error NfcStatus::FAILED directly.
+ *
+ * If preDiscover() reports an error, the NCI stack must start RF discovery immediately.
+ */
+ void preDiscover();
+
+ /**
+ * Performs an NCI write.
+ *
+ * This method may queue writes and return immediately. The only
+ * requirement is that the writes are executed in order.
+ *
+ * @param data
+ * Data packet to transmit NCI Commands and Data Messages over write.
+ * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+ * https://nfc-forum.org/our-work/specification-releases/
+ *
+ * @return number of bytes written to the NFCC.
+ */
+ int write(in byte[] data);
+
+ /**
+ * Set the logging flag for NFC HAL to enable it's verbose logging.
+ * If verbose logging is not supported, the call must not have any effect on logging verbosity.
+ * However, isVerboseLoggingEnabled() must still return the value set by the last call to
+ * setEnableVerboseLogging().
+ * @param enable for setting the verbose logging flag to HAL
+ */
+ void setEnableVerboseLogging(in boolean enable);
+
+ /**
+ * Get the verbose logging flag value from NFC HAL.
+ * @return true if verbose logging flag value is enabled, false if disabled.
+ */
+ boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..43d4f5c
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+import android.hardware.nfc.NfcEvent;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfcClientCallback {
+ /**
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass incomming response data to the stack.
+ *
+ * @param data
+ * Data packet to transmit NCI Responses, Notifications, and Data
+ * Messages over sendData.
+ * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+ * https://nfc-forum.org/our-work/specification-releases/
+ */
+ void sendData(in byte[] data);
+
+ /**
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass events back to the stack.
+ */
+ void sendEvent(in NfcEvent event, in NfcStatus status);
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..5160532
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/**
+ * Different closing types for NFC HAL.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcCloseType {
+ /**
+ * Close the NFC controller and free NFC HAL resources.
+ */
+ DISABLE = 0,
+
+ /**
+ * Switch the NFC controller operation mode and free NFC HAL resources.
+ * Enable NFC functionality for off host card emulation usecases in
+ * device(host) power off(switched off) state, if the device
+ * supports power off use cases. If the device doesn't support power
+ * off use cases, this call should be same as DISABLE.
+ */
+ HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..1b4fcfb
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+import android.hardware.nfc.PresenceCheckAlgorithm;
+import android.hardware.nfc.ProtocolDiscoveryConfig;
+
+/**
+ * Define Nfc related configurations based on:
+ * NFC Controller Interface (NCI) Technical Specification
+ * https://nfc-forum.org/our-work/specification-releases/
+ */
+@VintfStability
+parcelable NfcConfig {
+ /**
+ * If true, NFCC is using bail out mode for either Type A or Type B poll
+ * based on: Nfc-Forum Activity Technical Specification
+ * https://nfc-forum.org/our-work/specification-releases/
+ */
+ boolean nfaPollBailOutMode;
+ PresenceCheckAlgorithm presenceCheckAlgorithm;
+ ProtocolDiscoveryConfig nfaProprietaryCfg;
+ /**
+ * Default off-host route. 0x00 if there aren't any. Refer to NCI spec.
+ */
+ byte defaultOffHostRoute;
+ /**
+ * Default off-host route for Felica. 0x00 if there aren't any. Refer to
+ * NCI spec.
+ */
+ byte defaultOffHostRouteFelica;
+ /**
+ * Default system code route. 0x00 if there aren't any. Refer NCI spec.
+ */
+ byte defaultSystemCodeRoute;
+ /**
+ * Default power state for system code route. 0x00 if there aren't any.
+ * Refer to NCI spec.
+ */
+ byte defaultSystemCodePowerState;
+ /**
+ * Default route for all remaining protocols and technology which haven't
+ * been configured.
+ * Device Host(0x00) is the default. Refer to NCI spec.
+ *
+ */
+ byte defaultRoute;
+ /**
+ * Pipe ID for eSE. 0x00 if there aren't any.
+ */
+ byte offHostESEPipeId;
+ /**
+ * Pipe ID for UICC. 0x00 if there aren't any.
+ */
+ byte offHostSIMPipeId;
+ /**
+ * Extended APDU length for ISO_DEP. If not supported default length is 261
+ */
+ int maxIsoDepTransceiveLength;
+ /**
+ * list of allowed host ids, as per ETSI TS 102 622
+ * https://www.etsi.org/
+ */
+ byte[] hostAllowlist;
+ /**
+ * NFCEE ID for offhost UICC & eSE secure element.
+ * 0x00 if there aren't any. Refer to NCI spec.
+ */
+ byte[] offHostRouteUicc;
+ byte[] offHostRouteEse;
+ /**
+ * Default IsoDep route. 0x00 if there aren't any. Refer to NCI spec.
+ */
+ byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..a78b1cd
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/**
+ * Nfc event to notify nfc status change.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcEvent {
+ /**
+ * Open complete event to notify upper layer when NFC HAL and NFCC
+ * initialization complete.
+ */
+ OPEN_CPLT = 0,
+ /**
+ * Close complete event to notify upper layer when HAL close is done.
+ */
+ CLOSE_CPLT = 1,
+ /**
+ * Post init complete event to notify upper layer when post init operations
+ * are done.
+ */
+ POST_INIT_CPLT = 2,
+ /**
+ * Pre-discover complete event to notify upper layer when pre-discover
+ * operations are done.
+ */
+ PRE_DISCOVER_CPLT = 3,
+ /**
+ * HCI network reset event to notify upplayer when HCI network needs to
+ * be re-initialized in case of an error.
+ */
+ HCI_NETWORK_RESET = 4,
+ /**
+ * Error event to notify upper layer when there's an unknown error.
+ */
+ ERROR = 5,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..a38d370
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/**
+ * Used to specify the status of the NfcEvent
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcStatus {
+ /**
+ * Default status when NfcEvent with status OK.
+ */
+ OK = 0,
+ /**
+ * Generic error.
+ */
+ FAILED = 1,
+ /**
+ * Transport error.
+ */
+ ERR_TRANSPORT = 2,
+ /**
+ * Command timeout error.
+ */
+ ERR_CMD_TIMEOUT = 3,
+ /**
+ * Refused error when command is rejected.
+ */
+ REFUSED = 4,
+}
diff --git a/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..20e7bff
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/*
+ * Presence Check Algorithm as defined in ISO/IEC 14443-4:
+ * https://www.iso.org/standard/73599.html
+ */
+@VintfStability
+@Backing(type="byte")
+enum PresenceCheckAlgorithm {
+ /**
+ * Let the stack select an algorithm
+ */
+ DEFAULT = 0,
+ /**
+ * ISO-DEP protocol's empty I-block
+ */
+ I_BLOCK = 1,
+ /**
+ * Type - 4 tag protocol iso-dep nak presence check command is sent waiting for
+ * response and notification.
+ */
+ ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..f8e3228
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/**
+ * Vendor Specific Proprietary Protocol & Discovery Configuration.
+ * Set to 0xFF if not supported.
+ * discovery* fields map to "RF Technology and Mode" in NCI Spec
+ * protocol* fields map to "RF protocols" in NCI Spec
+ */
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+ byte protocol18092Active;
+ byte protocolBPrime;
+ byte protocolDual;
+ byte protocol15693;
+ byte protocolKovio;
+ byte protocolMifare;
+ byte discoveryPollKovio;
+ byte discoveryPollBPrime;
+ byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/default/Android.bp b/nfc/aidl/default/Android.bp
new file mode 100644
index 0000000..6daebe5
--- /dev/null
+++ b/nfc/aidl/default/Android.bp
@@ -0,0 +1,32 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+ name: "android.hardware.nfc-service.example",
+ relative_install_path: "hw",
+ init_rc: ["nfc-service-example.rc"],
+ vintf_fragments: ["nfc-service-example.xml"],
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ "libbinder_ndk",
+ "android.hardware.nfc-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ "Nfc.cpp",
+ "Vendor_hal_api.cpp",
+ ],
+}
diff --git a/nfc/aidl/default/Nfc.cpp b/nfc/aidl/default/Nfc.cpp
new file mode 100644
index 0000000..4685b59
--- /dev/null
+++ b/nfc/aidl/default/Nfc.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Nfc.h"
+
+#include <android-base/logging.h>
+
+#include "Vendor_hal_api.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+std::shared_ptr<INfcClientCallback> Nfc::mCallback = nullptr;
+AIBinder_DeathRecipient* clientDeathRecipient = nullptr;
+
+void OnDeath(void* cookie) {
+ if (Nfc::mCallback != nullptr && !AIBinder_isAlive(Nfc::mCallback->asBinder().get())) {
+ LOG(INFO) << __func__ << " Nfc service has died";
+ Nfc* nfc = static_cast<Nfc*>(cookie);
+ nfc->close(NfcCloseType::DISABLE);
+ }
+}
+
+::ndk::ScopedAStatus Nfc::open(const std::shared_ptr<INfcClientCallback>& clientCallback) {
+ LOG(INFO) << "open";
+ if (clientCallback == nullptr) {
+ LOG(INFO) << "Nfc::open null callback";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ Nfc::mCallback = clientCallback;
+
+ clientDeathRecipient = AIBinder_DeathRecipient_new(OnDeath);
+ auto linkRet = AIBinder_linkToDeath(clientCallback->asBinder().get(), clientDeathRecipient,
+ this /* cookie */);
+ if (linkRet != STATUS_OK) {
+ LOG(ERROR) << __func__ << ": linkToDeath failed: " << linkRet;
+ // Just ignore the error.
+ }
+
+ int ret = Vendor_hal_open(eventCallback, dataCallback);
+ return ret == 0 ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::close(NfcCloseType type) {
+ LOG(INFO) << "close";
+ if (Nfc::mCallback == nullptr) {
+ LOG(ERROR) << __func__ << "mCallback null";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ int ret = 0;
+ if (type == NfcCloseType::HOST_SWITCHED_OFF) {
+ ret = Vendor_hal_close_off();
+ } else {
+ ret = Vendor_hal_close();
+ }
+ Nfc::mCallback = nullptr;
+ AIBinder_DeathRecipient_delete(clientDeathRecipient);
+ clientDeathRecipient = nullptr;
+ return ret == 0 ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::coreInitialized() {
+ LOG(INFO) << "coreInitialized";
+ if (Nfc::mCallback == nullptr) {
+ LOG(ERROR) << __func__ << "mCallback null";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ int ret = Vendor_hal_core_initialized();
+
+ return ret == 0 ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::factoryReset() {
+ LOG(INFO) << "factoryReset";
+ Vendor_hal_factoryReset();
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::getConfig(NfcConfig* _aidl_return) {
+ LOG(INFO) << "getConfig";
+ NfcConfig nfcVendorConfig;
+ Vendor_hal_getConfig(nfcVendorConfig);
+
+ *_aidl_return = nfcVendorConfig;
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::powerCycle() {
+ LOG(INFO) << "powerCycle";
+ if (Nfc::mCallback == nullptr) {
+ LOG(ERROR) << __func__ << "mCallback null";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ return Vendor_hal_power_cycle() ? ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED))
+ : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::preDiscover() {
+ LOG(INFO) << "preDiscover";
+ if (Nfc::mCallback == nullptr) {
+ LOG(ERROR) << __func__ << "mCallback null";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ return Vendor_hal_pre_discover() ? ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED))
+ : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::write(const std::vector<uint8_t>& data, int32_t* _aidl_return) {
+ LOG(INFO) << "write";
+ if (Nfc::mCallback == nullptr) {
+ LOG(ERROR) << __func__ << "mCallback null";
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(NfcStatus::FAILED));
+ }
+ *_aidl_return = Vendor_hal_write(data.size(), &data[0]);
+ return ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus Nfc::setEnableVerboseLogging(bool enable) {
+ LOG(INFO) << "setVerboseLogging";
+ Vendor_hal_setVerboseLogging(enable);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::isVerboseLoggingEnabled(bool* _aidl_return) {
+ *_aidl_return = Vendor_hal_getVerboseLogging();
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace nfc
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/nfc/aidl/default/Nfc.h b/nfc/aidl/default/Nfc.h
new file mode 100644
index 0000000..1b14534
--- /dev/null
+++ b/nfc/aidl/default/Nfc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/INfcClientCallback.h>
+#include <android-base/logging.h>
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+using ::aidl::android::hardware::nfc::NfcCloseType;
+using ::aidl::android::hardware::nfc::NfcConfig;
+using ::aidl::android::hardware::nfc::NfcStatus;
+
+// Default implementation that reports no support NFC.
+struct Nfc : public BnNfc {
+ public:
+ Nfc() = default;
+
+ ::ndk::ScopedAStatus open(const std::shared_ptr<INfcClientCallback>& clientCallback) override;
+ ::ndk::ScopedAStatus close(NfcCloseType type) override;
+ ::ndk::ScopedAStatus coreInitialized() override;
+ ::ndk::ScopedAStatus factoryReset() override;
+ ::ndk::ScopedAStatus getConfig(NfcConfig* _aidl_return) override;
+ ::ndk::ScopedAStatus powerCycle() override;
+ ::ndk::ScopedAStatus preDiscover() override;
+ ::ndk::ScopedAStatus write(const std::vector<uint8_t>& data, int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus setEnableVerboseLogging(bool enable) override;
+ ::ndk::ScopedAStatus isVerboseLoggingEnabled(bool* _aidl_return) override;
+
+ static void eventCallback(uint8_t event, uint8_t status) {
+ if (mCallback != nullptr) {
+ auto ret = mCallback->sendEvent((NfcEvent)event, (NfcStatus)status);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "Failed to send event!";
+ }
+ }
+ }
+
+ static void dataCallback(uint16_t data_len, uint8_t* p_data) {
+ std::vector<uint8_t> data(p_data, p_data + data_len);
+ if (mCallback != nullptr) {
+ auto ret = mCallback->sendData(data);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "Failed to send data!";
+ }
+ }
+ }
+
+ static std::shared_ptr<INfcClientCallback> mCallback;
+};
+
+} // namespace nfc
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/nfc/aidl/default/Vendor_hal_api.cpp b/nfc/aidl/default/Vendor_hal_api.cpp
new file mode 100644
index 0000000..66a2ebc
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/properties.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "Vendor_hal_api.h"
+
+bool logging = false;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback) {
+ (void)p_cback;
+ (void)p_data_cback;
+ // nothing to open in this example
+ return -1;
+}
+
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data) {
+ (void)data_len;
+ (void)p_data;
+ return -1;
+}
+
+int Vendor_hal_core_initialized() {
+ return -1;
+}
+
+int Vendor_hal_pre_discover() {
+ return -1;
+}
+
+int Vendor_hal_close() {
+ return -1;
+}
+
+int Vendor_hal_close_off() {
+ return -1;
+}
+
+int Vendor_hal_power_cycle() {
+ return -1;
+}
+
+void Vendor_hal_factoryReset() {}
+
+void Vendor_hal_getConfig(NfcConfig& config) {
+ (void)config;
+}
+
+void Vendor_hal_setVerboseLogging(bool enable) {
+ logging = enable;
+}
+
+bool Vendor_hal_getVerboseLogging() {
+ return logging;
+}
diff --git a/nfc/aidl/default/Vendor_hal_api.h b/nfc/aidl/default/Vendor_hal_api.h
new file mode 100644
index 0000000..595c2dd
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <aidl/android/hardware/nfc/NfcConfig.h>
+#include <aidl/android/hardware/nfc/NfcEvent.h>
+#include <aidl/android/hardware/nfc/NfcStatus.h>
+#include <aidl/android/hardware/nfc/PresenceCheckAlgorithm.h>
+#include <aidl/android/hardware/nfc/ProtocolDiscoveryConfig.h>
+#include "hardware_nfc.h"
+
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+using aidl::android::hardware::nfc::ProtocolDiscoveryConfig;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback);
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data);
+
+int Vendor_hal_core_initialized();
+
+int Vendor_hal_pre_discover();
+
+int Vendor_hal_close();
+
+int Vendor_hal_close_off();
+
+int Vendor_hal_power_cycle();
+
+void Vendor_hal_factoryReset();
+
+void Vendor_hal_getConfig(NfcConfig& config);
+
+void Vendor_hal_setVerboseLogging(bool enable);
+
+bool Vendor_hal_getVerboseLogging();
diff --git a/nfc/aidl/default/hardware_nfc.h b/nfc/aidl/default/hardware_nfc.h
new file mode 100644
index 0000000..0f856c5
--- /dev/null
+++ b/nfc/aidl/default/hardware_nfc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+
+typedef uint8_t nfc_event_t;
+typedef uint8_t nfc_status_t;
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass events back to the stack.
+ */
+typedef void(nfc_stack_callback_t)(nfc_event_t event, nfc_status_t event_status);
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass incomming data to the stack.
+ */
+typedef void(nfc_stack_data_callback_t)(uint16_t data_len, uint8_t* p_data);
diff --git a/nfc/aidl/default/main.cpp b/nfc/aidl/default/main.cpp
new file mode 100644
index 0000000..0cc51e7
--- /dev/null
+++ b/nfc/aidl/default/main.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Nfc.h"
+using ::aidl::android::hardware::nfc::Nfc;
+
+int main() {
+ LOG(INFO) << "NFC HAL starting up";
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+ LOG(INFO) << "failed to set thread pool max thread count";
+ return 1;
+ }
+ std::shared_ptr<Nfc> nfc_service = ndk::SharedRefBase::make<Nfc>();
+
+ const std::string instance = std::string() + Nfc::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(nfc_service->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/nfc/aidl/default/nfc-service-example.rc b/nfc/aidl/default/nfc-service-example.rc
new file mode 100644
index 0000000..7d7052e
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.rc
@@ -0,0 +1,4 @@
+service nfc_hal_service /vendor/bin/hw/android.hardware.nfc-service.st
+ class hal
+ user nfc
+ group nfc
diff --git a/nfc/aidl/default/nfc-service-example.xml b/nfc/aidl/default/nfc-service-example.xml
new file mode 100644
index 0000000..70fed20
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.nfc</name>
+ <fqname>INfc/default</fqname>
+ </hal>
+</manifest>
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..99eecd0
--- /dev/null
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsAidlHalNfcTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsAidlHalNfcTargetTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.nfc-V1-ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
new file mode 100644
index 0000000..977b25c
--- /dev/null
+++ b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "nfc_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/BnNfcClientCallback.h>
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <chrono>
+#include <future>
+
+using aidl::android::hardware::nfc::INfc;
+using aidl::android::hardware::nfc::INfcClientCallback;
+using aidl::android::hardware::nfc::NfcCloseType;
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+
+using android::getAidlHalInstanceNames;
+using android::PrintInstanceNameToString;
+using android::base::StringPrintf;
+using ndk::enum_range;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+
+constexpr static int kCallbackTimeoutMs = 10000;
+
+// 261 bytes is the default and minimum transceive length
+constexpr unsigned int MIN_ISO_DEP_TRANSCEIVE_LENGTH = 261;
+
+// Range of valid off host route ids
+constexpr uint8_t MIN_OFFHOST_ROUTE_ID = 0x01;
+constexpr uint8_t MAX_OFFHOST_ROUTE_ID = 0xFE;
+
+class NfcClientCallback : public aidl::android::hardware::nfc::BnNfcClientCallback {
+ public:
+ NfcClientCallback(const std::function<void(NfcEvent, NfcStatus)>& on_hal_event_cb,
+ const std::function<void(const std::vector<uint8_t>&)>& on_nci_data_cb)
+ : on_nci_data_cb_(on_nci_data_cb), on_hal_event_cb_(on_hal_event_cb) {}
+ virtual ~NfcClientCallback() = default;
+
+ ::ndk::ScopedAStatus sendEvent(NfcEvent event, NfcStatus event_status) override {
+ on_hal_event_cb_(event, event_status);
+ return ::ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus sendData(const std::vector<uint8_t>& data) override {
+ on_nci_data_cb_(data);
+ return ::ndk::ScopedAStatus::ok();
+ };
+
+ private:
+ std::function<void(const std::vector<uint8_t>&)> on_nci_data_cb_;
+ std::function<void(NfcEvent, NfcStatus)> on_hal_event_cb_;
+};
+
+class NfcAidl : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+ infc_ = INfc::fromBinder(binder);
+ ASSERT_NE(infc_, nullptr);
+ }
+ std::shared_ptr<INfc> infc_;
+};
+
+/*
+ * OpenAndCloseForDisable:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::DISABLE) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForDisable) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ LOG(INFO) << StringPrintf("%s,%d ", __func__, event);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close DISABLE";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ LOG(INFO) << "wait for close";
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAndCloseForHostSwitchedOff:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::HOST_SWITCHED_OFF) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForHostSwitchedOff) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close HOST_SWITCHED_OFF";
+ EXPECT_TRUE(infc_->close(NfcCloseType::HOST_SWITCHED_OFF).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAfterOpen:
+ * Calls open() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, OpenAfterOpen) {
+ int open_count = 0;
+ std::promise<void> open_cb_promise;
+ std::promise<void> open2_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto open2_cb_future = open2_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &open2_cb_promise, &open_count](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) {
+ open_count == 0 ? open_cb_promise.set_value() : open2_cb_promise.set_value();
+ open_count++;
+ }
+ },
+ [](auto) {});
+
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Open again and wait for OPEN_CPLT
+ LOG(INFO) << "open again";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open2_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CloseAfterClose:
+ * Calls close() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, CloseAfterClose) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+ // Close again should fail.
+ LOG(INFO) << "close again";
+ EXPECT_TRUE(!(infc_->close(NfcCloseType::DISABLE).isOk()));
+}
+
+/*
+ * PowerCycleAfterOpen:
+ * Calls powerCycle() after open
+ * Waits for NfcEvent.OPEN_CPLT
+ * Checks status
+ */
+TEST_P(NfcAidl, PowerCycleAfterOpen) {
+ int open_cplt_count = 0;
+ std::promise<void> open_cb_promise;
+ std::promise<void> power_cycle_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto power_cycle_cb_future = power_cycle_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise, &power_cycle_cb_promise, &open_cplt_count](
+ auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) {
+ if (open_cplt_count == 0) {
+ open_cplt_count++;
+ open_cb_promise.set_value();
+ } else {
+ power_cycle_cb_promise.set_value();
+ }
+ }
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // PowerCycle and wait for OPEN_CPLT
+ LOG(INFO) << "PowerCycle";
+ EXPECT_TRUE(infc_->powerCycle().isOk());
+ EXPECT_EQ(power_cycle_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * PowerCycleAfterClose:
+ * Calls powerCycle() after close
+ * PowerCycle should fail immediately
+ */
+TEST_P(NfcAidl, PowerCycleAfterClose) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // PowerCycle should fail
+ LOG(INFO) << "PowerCycle";
+ EXPECT_TRUE(!(infc_->powerCycle().isOk()));
+}
+
+/*
+ * CoreInitializedAfterOpen:
+ * Calls coreInitialized() after open
+ * Waits for NfcEvent.POST_INIT_CPLT
+ */
+TEST_P(NfcAidl, CoreInitializedAfterOpen) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> core_init_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto core_init_cb_future = core_init_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise, &core_init_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::POST_INIT_CPLT) core_init_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // CoreInitialized and wait for POST_INIT_CPLT
+ LOG(INFO) << "coreInitialized";
+ EXPECT_TRUE(infc_->coreInitialized().isOk());
+ EXPECT_EQ(core_init_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CoreInitializedAfterClose:
+ * Calls coreInitialized() after close
+ * coreInitialized() should fail immediately
+ */
+TEST_P(NfcAidl, CoreInitializedAfterClose) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // coreInitialized should fail
+ LOG(INFO) << "CoreInitialized";
+ EXPECT_TRUE(!(infc_->coreInitialized().isOk()));
+}
+
+/*
+ * PreDiscoverAfterClose:
+ * Call preDiscover() after close
+ * preDiscover() should fail immediately
+ */
+TEST_P(NfcAidl, PreDiscoverAfterClose) {
+ std::promise<void> open_cb_promise;
+ std::promise<void> close_cb_promise;
+ auto open_cb_future = open_cb_promise.get_future();
+ auto close_cb_future = close_cb_promise.get_future();
+ std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+ [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+ EXPECT_EQ(status, NfcStatus::OK);
+ if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+ if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+ },
+ [](auto) {});
+ std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+ // Open and wait for OPEN_CPLT
+ LOG(INFO) << "open";
+ EXPECT_TRUE(infc_->open(mCallback).isOk());
+ EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // Close and wait for CLOSE_CPLT
+ LOG(INFO) << "close";
+ EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+ EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+ // preDiscover should fail
+ LOG(INFO) << "preDiscover";
+ EXPECT_TRUE(!(infc_->preDiscover().isOk()));
+}
+
+/*
+ * checkGetConfigValues:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_P(NfcAidl, CheckGetConfigValues) {
+ NfcConfig configValue;
+ EXPECT_TRUE(infc_->getConfig(&configValue).isOk());
+ EXPECT_GE(configValue.maxIsoDepTransceiveLength, MIN_ISO_DEP_TRANSCEIVE_LENGTH);
+ LOG(INFO) << StringPrintf("configValue.maxIsoDepTransceiveLength = %x",
+ configValue.maxIsoDepTransceiveLength);
+ for (auto uicc : configValue.offHostRouteUicc) {
+ LOG(INFO) << StringPrintf("offHostRouteUicc = %x", uicc);
+ EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
+ EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
+ }
+ for (auto ese : configValue.offHostRouteEse) {
+ LOG(INFO) << StringPrintf("offHostRouteEse = %x", ese);
+ EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
+ EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
+ }
+ if (configValue.defaultIsoDepRoute != 0) {
+ EXPECT_GE((uint8_t)configValue.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
+ EXPECT_LE((uint8_t)configValue.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
+ }
+}
+
+/*
+ * CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging:
+ * Calls setEnableVerboseLogging()
+ * checks the return value of isVerboseLoggingEnabled
+ */
+TEST_P(NfcAidl, CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging) {
+ bool enabled = false;
+ EXPECT_TRUE(infc_->setEnableVerboseLogging(true).isOk());
+ EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+ EXPECT_TRUE(enabled);
+ EXPECT_TRUE(infc_->setEnableVerboseLogging(false).isOk());
+ EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+ EXPECT_TRUE(!enabled);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcAidl);
+INSTANTIATE_TEST_SUITE_P(Nfc, NfcAidl,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ std::system("/system/bin/svc nfc disable"); /* Turn off NFC */
+ sleep(5);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ std::system("/system/bin/svc nfc enable"); /* Turn on NFC */
+ sleep(5);
+ return status;
+}
diff --git a/oemlock/aidl/default/service.cpp b/oemlock/aidl/default/service.cpp
index af828a0..9fa7d63 100644
--- a/oemlock/aidl/default/service.cpp
+++ b/oemlock/aidl/default/service.cpp
@@ -28,7 +28,7 @@
const std::string instance = std::string() + OemLock::descriptor + "/default";
binder_status_t status = AServiceManager_addService(oemlock->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return -1; // Should never be reached
diff --git a/power/aidl/default/main.cpp b/power/aidl/default/main.cpp
index 964bd96..306b91b 100644
--- a/power/aidl/default/main.cpp
+++ b/power/aidl/default/main.cpp
@@ -28,7 +28,7 @@
const std::string instance = std::string() + Power::descriptor + "/default";
binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/power/stats/aidl/default/main.cpp b/power/stats/aidl/default/main.cpp
index 2fe3d2e..9e78247 100644
--- a/power/stats/aidl/default/main.cpp
+++ b/power/stats/aidl/default/main.cpp
@@ -73,7 +73,7 @@
const std::string instance = std::string() + PowerStats::descriptor + "/default";
binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index cd64bca..8d0d782 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -23,5 +23,9 @@
interfaces: [
"android.hidl.base@1.0",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth",
+ ],
gen_java: true,
}
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index fe10587..5224624 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -16,8 +16,37 @@
#include <sap_hidl_hal_utils.h>
+bool isServiceValidForDeviceConfiguration(hidl_string& serviceName) {
+ if (isSsSsEnabled()) {
+ // Device is configured as SSSS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME) {
+ LOG(DEBUG) << "Not valid for SSSS device.";
+ return false;
+ }
+ } else if (isDsDsEnabled()) {
+ // Device is configured as DSDS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME) {
+ LOG(DEBUG) << "Not valid for DSDS device.";
+ return false;
+ }
+ } else if (isTsTsEnabled()) {
+ // Device is configured as TSTS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME &&
+ serviceName != SAP_SERVICE_SLOT3_NAME) {
+ LOG(DEBUG) << "Not valid for TSTS device.";
+ return false;
+ }
+ }
+ return true;
+}
+
void SapHidlTest::SetUp() {
- sap = ISap::getService(GetParam());
+ hidl_string serviceName = GetParam();
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ LOG(DEBUG) << "Skipped the test due to device configuration.";
+ GTEST_SKIP();
+ }
+ sap = ISap::getService(serviceName);
ASSERT_NE(sap, nullptr);
sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index 2fc9ae3..8e86591 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -36,7 +36,15 @@
using ::android::sp;
#define TIMEOUT_PERIOD 40
-#define SAP_SERVICE_NAME "slot1"
+
+// HAL instance name for SIM slot 1 or single SIM device
+#define SAP_SERVICE_SLOT1_NAME "slot1"
+
+// HAL instance name for SIM slot 2 on dual SIM device
+#define SAP_SERVICE_SLOT2_NAME "slot2"
+
+// HAL instance name for SIM slot 3 on triple SIM device
+#define SAP_SERVICE_SLOT3_NAME "slot3"
class SapHidlTest;
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 d108951..152858f 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -1271,8 +1271,12 @@
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
+ int32_t boardApiLevel = android::base::GetIntProperty<int32_t>("ro.board.first_api_level", 0);
// Allow devices shipping with Radio::1_5 and Android 11 to not support barring info.
- if (firstApiLevel > 0 && firstApiLevel <= 30) {
+ // b/212384410 Some GRF targets lauched with S release but with vendor R release
+ // do not support getBarringInfo API. Allow these devices to not support barring info.
+ if ((firstApiLevel > 0 && firstApiLevel <= 30) ||
+ (boardApiLevel > 0 && boardApiLevel <= 30)) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
// Early exit for devices that don't support barring info.
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 6982d40..980b042 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -47,4 +47,7 @@
EMERGENCY = 512,
MCX = 1024,
XCAP = 2048,
+ VSIM = 4096,
+ BIP = 8192,
+ ENTERPRISE = 16384,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index cfcd42c..02bbf21 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -46,12 +46,14 @@
int maxConns;
int waitTime;
boolean enabled;
- android.hardware.radio.data.ApnTypes supportedApnTypesBitmap;
- android.hardware.radio.RadioAccessFamily bearerBitmap;
+ int supportedApnTypesBitmap;
+ int bearerBitmap;
int mtuV4;
int mtuV6;
boolean preferred;
boolean persistent;
+ boolean alwaysOn;
+ android.hardware.radio.data.TrafficDescriptor trafficDescriptor;
const int ID_DEFAULT = 0;
const int ID_TETHERED = 1;
const int ID_IMS = 2;
@@ -60,6 +62,6 @@
const int ID_OEM_BASE = 1000;
const int ID_INVALID = -1;
const int TYPE_COMMON = 0;
- const int TYPE_THREE_GPP = 1;
- const int TYPE_THREE_GPP2 = 2;
+ const int TYPE_3GPP = 1;
+ const int TYPE_3GPP2 = 2;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
index a648675..7b572f1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
@@ -44,9 +44,9 @@
oneway void setDataAllowed(in int serial, in boolean allow);
oneway void setDataProfile(in int serial, in android.hardware.radio.data.DataProfileInfo[] profiles);
oneway void setDataThrottling(in int serial, in android.hardware.radio.data.DataThrottlingAction dataThrottlingAction, in long completionDurationMillis);
- oneway void setInitialAttachApn(in int serial, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
+ oneway void setInitialAttachApn(in int serial, in @nullable android.hardware.radio.data.DataProfileInfo dataProfileInfo);
oneway void setResponseFunctions(in android.hardware.radio.data.IRadioDataResponse radioDataResponse, in android.hardware.radio.data.IRadioDataIndication radioDataIndication);
- oneway void setupDataCall(in int serial, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo, in boolean roamingAllowed, in android.hardware.radio.data.DataRequestReason reason, in android.hardware.radio.data.LinkAddress[] addresses, in String[] dnses, in int pduSessionId, in @nullable android.hardware.radio.data.SliceInfo sliceInfo, in @nullable android.hardware.radio.data.TrafficDescriptor trafficDescriptor, in boolean matchAllRuleAllowed);
+ oneway void setupDataCall(in int serial, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo, in boolean roamingAllowed, in android.hardware.radio.data.DataRequestReason reason, in android.hardware.radio.data.LinkAddress[] addresses, in String[] dnses, in int pduSessionId, in @nullable android.hardware.radio.data.SliceInfo sliceInfo, in boolean matchAllRuleAllowed);
oneway void startHandover(in int serial, in int callId);
oneway void startKeepalive(in int serial, in android.hardware.radio.data.KeepaliveRequest keepalive);
oneway void stopKeepalive(in int serial, in int sessionHandle);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
index e496c7b..0ffa1f7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -37,5 +37,6 @@
oneway void dataCallListChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SetupDataCallResult[] dcList);
oneway void keepaliveStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.KeepaliveStatus status);
oneway void pcoData(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.PcoDataInfo pco);
- oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in String apn);
+ oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
+ oneway void slicingConfigChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SlicingConfig slicingConfig);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
index b0fc349..dfec59a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -37,7 +37,6 @@
oneway void acknowledgeIncomingGsmSmsWithPdu(in int serial, in boolean success, in String ackPdu);
oneway void acknowledgeLastIncomingCdmaSms(in int serial, in android.hardware.radio.messaging.CdmaSmsAck smsAck);
oneway void acknowledgeLastIncomingGsmSms(in int serial, in boolean success, in android.hardware.radio.messaging.SmsAcknowledgeFailCause cause);
- oneway void cancelPendingUssd(in int serial);
oneway void deleteSmsOnRuim(in int serial, in int index);
oneway void deleteSmsOnSim(in int serial, in int index);
oneway void getCdmaBroadcastConfig(in int serial);
@@ -50,7 +49,6 @@
oneway void sendImsSms(in int serial, in android.hardware.radio.messaging.ImsSmsMessage message);
oneway void sendSms(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message);
oneway void sendSmsExpectMore(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message);
- oneway void sendUssd(in int serial, in String ussd);
oneway void setCdmaBroadcastActivation(in int serial, in boolean activate);
oneway void setCdmaBroadcastConfig(in int serial, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configInfo);
oneway void setGsmBroadcastActivation(in int serial, in boolean activate);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
index 89a0f3b..8f7824f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -40,6 +40,5 @@
oneway void newSms(in android.hardware.radio.RadioIndicationType type, in byte[] pdu);
oneway void newSmsOnSim(in android.hardware.radio.RadioIndicationType type, in int recordNumber);
oneway void newSmsStatusReport(in android.hardware.radio.RadioIndicationType type, in byte[] pdu);
- oneway void onUssd(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.messaging.UssdModeType modeType, in String msg);
oneway void simSmsStorageFull(in android.hardware.radio.RadioIndicationType type);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
index 156f24b..c3af7a6 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -38,7 +38,6 @@
oneway void acknowledgeLastIncomingCdmaSmsResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void acknowledgeLastIncomingGsmSmsResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void acknowledgeRequest(in int serial);
- oneway void cancelPendingUssdResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void deleteSmsOnRuimResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void deleteSmsOnSimResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void getCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configs);
@@ -50,7 +49,6 @@
oneway void sendImsSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
oneway void sendSmsExpectMoreResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
oneway void sendSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
- oneway void sendUssdResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setCdmaBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setGsmBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/UssdModeType.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/UssdModeType.aidl
deleted file mode 100644
index 5395b11..0000000
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/UssdModeType.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-// the interface (from the latest frozen version), the build system will
-// prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.radio.messaging;
-@Backing(type="int") @VintfStability
-enum UssdModeType {
- NOTIFY = 0,
- REQUEST = 1,
- NW_RELEASE = 2,
- LOCAL_CLIENT = 3,
- NOT_SUPPORTED = 4,
- NW_TIMEOUT = 5,
-}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
index 2da0167..93940fd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -36,6 +36,5 @@
parcelable ActivityStatsInfo {
int sleepModeTimeMs;
int idleModeTimeMs;
- int[] txmModetimeMs;
- int rxModeTimeMs;
+ android.hardware.radio.modem.ActivityStatsTechSpecificInfo[] techSpecificInfo;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
new file mode 100644
index 0000000..798ec36
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@VintfStability
+parcelable ActivityStatsTechSpecificInfo {
+ android.hardware.radio.AccessNetwork rat;
+ int frequencyRange;
+ int[] txmModetimeMs;
+ int rxModeTimeMs;
+ const int FREQUENCY_RANGE_UNKNOWN = 0;
+ const int FREQUENCY_RANGE_LOW = 1;
+ const int FREQUENCY_RANGE_MID = 2;
+ const int FREQUENCY_RANGE_HIGH = 3;
+ const int FREQUENCY_RANGE_MMWAVE = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
index d5716ac..5aaf5a7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
@@ -36,7 +36,7 @@
parcelable RadioCapability {
int session;
int phase;
- android.hardware.radio.RadioAccessFamily raf;
+ int raf;
String logicalModemUuid;
int status;
const int PHASE_CONFIGURED = 0;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 16433be..2b70e45 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -50,12 +50,12 @@
oneway void getVoiceRegistrationState(in int serial);
oneway void isNrDualConnectivityEnabled(in int serial);
oneway void responseAcknowledgement();
- oneway void setAllowedNetworkTypesBitmap(in int serial, in android.hardware.radio.RadioAccessFamily networkTypeBitmap);
+ oneway void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
oneway void setBandMode(in int serial, in android.hardware.radio.network.RadioBandMode mode);
oneway void setBarringPassword(in int serial, in String facility, in String oldPassword, in String newPassword);
oneway void setCdmaRoamingPreference(in int serial, in android.hardware.radio.network.CdmaRoamingType type);
oneway void setCellInfoListRate(in int serial, in int rate);
- oneway void setIndicationFilter(in int serial, in android.hardware.radio.network.IndicationFilter indicationFilter);
+ oneway void setIndicationFilter(in int serial, in int indicationFilter);
oneway void setLinkCapacityReportingCriteria(in int serial, in int hysteresisMs, in int hysteresisDlKbps, in int hysteresisUlKbps, in int[] thresholdsDownlinkKbps, in int[] thresholdsUplinkKbps, in android.hardware.radio.AccessNetwork accessNetwork);
oneway void setLocationUpdates(in int serial, in boolean enable);
oneway void setNetworkSelectionModeAutomatic(in int serial);
@@ -68,4 +68,6 @@
oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
oneway void stopNetworkScan(in int serial);
oneway void supplyNetworkDepersonalization(in int serial, in String netPin);
+ oneway void setUsageSetting(in int serial, in android.hardware.radio.network.UsageSetting usageSetting);
+ oneway void getUsageSetting(in int serial);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
index d135a69..bd03c51 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -44,7 +44,7 @@
oneway void networkScanResult(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.NetworkScanResult result);
oneway void networkStateChanged(in android.hardware.radio.RadioIndicationType type);
oneway void nitzTimeReceived(in android.hardware.radio.RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
- oneway void registrationFailed(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in String chosenPlmn, in android.hardware.radio.network.Domain domain, in int causeCode, in int additionalCauseCode);
+ oneway void registrationFailed(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
oneway void restrictedStateChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.PhoneRestrictedState state);
oneway void suppSvcNotify(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.SuppSvcNotification suppSvc);
oneway void voiceRadioTechChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.RadioTechnology rat);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index ff95396..5f6c736 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -35,7 +35,7 @@
@VintfStability
interface IRadioNetworkResponse {
oneway void acknowledgeRequest(in int serial);
- oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.RadioAccessFamily networkTypeBitmap);
+ oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in int networkTypeBitmap);
oneway void getAvailableBandModesResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioBandMode[] bandModes);
oneway void getAvailableNetworksResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.OperatorInfo[] networkInfos);
oneway void getBarringInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
@@ -67,4 +67,6 @@
oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void stopNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void supplyNetworkDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+ oneway void setUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void getUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.UsageSetting usageSetting);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NeighboringCell.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NeighboringCell.aidl
deleted file mode 100644
index 4f29c0b..0000000
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NeighboringCell.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-// the interface (from the latest frozen version), the build system will
-// prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.radio.network;
-@VintfStability
-parcelable NeighboringCell {
- String cid;
- int rssi;
-}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..7fdf831
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @VintfStability
+enum UsageSetting {
+ VOICE_CENTRIC = 1,
+ DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
index ef9c779..85cf86e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -36,6 +36,5 @@
parcelable CarrierRestrictions {
android.hardware.radio.sim.Carrier[] allowedCarriers;
android.hardware.radio.sim.Carrier[] excludedCarriers;
- boolean priority;
boolean allowedCarriersPrioritized;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
index 4f415ee..39bcf1a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -37,7 +37,7 @@
String number;
String mcc;
String mnc;
- android.hardware.radio.voice.EmergencyServiceCategory categories;
+ int categories;
String[] urns;
int sources;
const int SOURCE_NETWORK_SIGNALING = 1;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
index 68c82fa..603b1d6 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
@@ -35,9 +35,10 @@
@VintfStability
interface IRadioVoice {
oneway void acceptCall(in int serial);
+ oneway void cancelPendingUssd(in int serial);
oneway void conference(in int serial);
oneway void dial(in int serial, in android.hardware.radio.voice.Dial dialInfo);
- oneway void emergencyDial(in int serial, in android.hardware.radio.voice.Dial dialInfo, in android.hardware.radio.voice.EmergencyServiceCategory categories, in String[] urns, in android.hardware.radio.voice.EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency, in boolean isTesting);
+ oneway void emergencyDial(in int serial, in android.hardware.radio.voice.Dial dialInfo, in int categories, in String[] urns, in android.hardware.radio.voice.EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency, in boolean isTesting);
oneway void exitEmergencyCallbackMode(in int serial);
oneway void explicitCallTransfer(in int serial);
oneway void getCallForwardStatus(in int serial, in android.hardware.radio.voice.CallForwardInfo callInfo);
@@ -59,6 +60,7 @@
oneway void sendBurstDtmf(in int serial, in String dtmf, in int on, in int off);
oneway void sendCdmaFeatureCode(in int serial, in String featureCode);
oneway void sendDtmf(in int serial, in String s);
+ oneway void sendUssd(in int serial, in String ussd);
oneway void separateConnection(in int serial, in int gsmIndex);
oneway void setCallForward(in int serial, in android.hardware.radio.voice.CallForwardInfo callInfo);
oneway void setCallWaiting(in int serial, in boolean enable, in int serviceClass);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
index af3417d..189ed43 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -44,6 +44,7 @@
oneway void exitEmergencyCallbackMode(in android.hardware.radio.RadioIndicationType type);
oneway void indicateRingbackTone(in android.hardware.radio.RadioIndicationType type, in boolean start);
oneway void onSupplementaryServiceIndication(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.StkCcUnsolSsResult ss);
+ oneway void onUssd(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.UssdModeType modeType, in String msg);
oneway void resendIncallMute(in android.hardware.radio.RadioIndicationType type);
oneway void srvccStateNotify(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.SrvccState state);
oneway void stkCallControlAlphaNotify(in android.hardware.radio.RadioIndicationType type, in String alpha);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
index a3b5e58..7acc044 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -36,6 +36,7 @@
interface IRadioVoiceResponse {
oneway void acceptCallResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void acknowledgeRequest(in int serial);
+ oneway void cancelPendingUssdResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void conferenceResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void dialResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void emergencyDialResponse(in android.hardware.radio.RadioResponseInfo info);
@@ -59,6 +60,7 @@
oneway void sendBurstDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void sendCdmaFeatureCodeResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void sendDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void sendUssdResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void separateConnectionResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setCallForwardResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setCallWaitingResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
new file mode 100644
index 0000000..9a9d723
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @VintfStability
+enum UssdModeType {
+ NOTIFY = 0,
+ REQUEST = 1,
+ NW_RELEASE = 2,
+ LOCAL_CLIENT = 3,
+ NOT_SUPPORTED = 4,
+ NW_TIMEOUT = 5,
+}
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index a1c3c27..b5cf633 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -42,7 +42,13 @@
*/
String eid;
/**
- * PortInfo contains the ICCID, logical slot ID, and port state
+ * PortInfo contains the ICCID, logical slot ID, and port state.
+ * Cardstate has no relationship with whether the slot is active or inactive. Should always
+ * report up at least 1 port otherwise the logicalSlotIndex and portActive info will be lost.
+ * For example, the pSIM can be removed, but the slot can still be active. In that case, the
+ * SIM_STATUS reported for the corresponding logical stack will show CARDSTATE_ABSENT.
+ * Similarly, even if there is no profile enabled on the eSIM, that port can still be the
+ * active port in the slot mapping.
*/
SimPortInfo[] portInfo;
}
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index e780d8e..ae103fc 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -73,4 +73,16 @@
* APN type for XCAP
*/
XCAP = 1 << 11,
+ /**
+ * APN type for VSIM.
+ */
+ VSIM = 1 << 12,
+ /**
+ * APN type for BIP.
+ */
+ BIP = 1 << 13,
+ /**
+ * APN type for ENTERPRISE
+ */
+ ENTERPRISE = 1 << 14
}
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index 7657fc9..123b3ed 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -16,10 +16,9 @@
package android.hardware.radio.data;
-import android.hardware.radio.RadioAccessFamily;
import android.hardware.radio.data.ApnAuthType;
-import android.hardware.radio.data.ApnTypes;
import android.hardware.radio.data.PdpProtocolType;
+import android.hardware.radio.data.TrafficDescriptor;
@VintfStability
parcelable DataProfileInfo {
@@ -35,8 +34,8 @@
const int ID_INVALID = 0xFFFFFFFF;
const int TYPE_COMMON = 0;
- const int TYPE_THREE_GPP = 1;
- const int TYPE_THREE_GPP2 = 2;
+ const int TYPE_3GPP = 1;
+ const int TYPE_3GPP2 = 2;
/**
* ID of the data profile.
@@ -92,11 +91,11 @@
/**
* Supported APN types bitmap. See ApnTypes for the value of each bit.
*/
- ApnTypes supportedApnTypesBitmap;
+ int supportedApnTypesBitmap;
/**
* The bearer bitmap. See RadioAccessFamily for the value of each bit.
*/
- RadioAccessFamily bearerBitmap;
+ int bearerBitmap;
/**
* Maximum transmission unit (MTU) size in bytes for IPv4.
*/
@@ -115,4 +114,19 @@
* If the same data profile exists, this data profile must overwrite it.
*/
boolean persistent;
+ /**
+ * Indicates the PDU session brought up by this data profile should be always-on.
+ * An always-on PDU Session is a PDU Session for which User Plane resources have to be
+ * activated during every transition from CM-IDLE mode to CM-CONNECTED state.
+ * See 3GPP TS 23.501 section 5.6.13 for the details.
+ */
+ boolean alwaysOn;
+ /**
+ * TrafficDescriptor for which data connection needs to be established.
+ * It is used for URSP traffic matching as described in TS 24.526 Section 4.2.2.
+ * It includes an optional DNN which, if present, must be used for traffic matching --
+ * it does not specify the end point to be used for the data call. The end point is specified by
+ * apn; apn must be used as the end point if one is not specified through URSP rules.
+ */
+ TrafficDescriptor trafficDescriptor;
}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
index 9f5ba4c..e1ba568 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
@@ -159,14 +159,15 @@
in long completionDurationMillis);
/**
- * Set an APN to initial attach network.
+ * Set an APN to initial attach network or clear the existing initial attach APN.
*
* @param serial Serial number of request.
- * @param dataProfileInfo data profile containing APN settings
+ * @param dataProfileInfo Data profile containing APN settings or null to clear the existing
+ * initial attach APN.
*
* Response function is IRadioDataResponse.setInitialAttachApnResponse()
*/
- void setInitialAttachApn(in int serial, in DataProfileInfo dataProfileInfo);
+ void setInitialAttachApn(in int serial, in @nullable DataProfileInfo dataProfileInfo);
/**
* Set response functions for data radio requests and indications.
@@ -219,12 +220,6 @@
* EPDG to 5G. It is valid only when accessNetwork is AccessNetwork:NGRAN. If the slice
* passed from EPDG is rejected, then the data failure cause must be
* DataCallFailCause:SLICE_REJECTED.
- * @param trafficDescriptor TrafficDescriptor for which data connection needs to be established.
- * It is used for URSP traffic matching as described in TS 24.526 Section 4.2.2.
- * It includes an optional DNN which, if present, must be used for traffic matching --
- * it does not specify the end point to be used for the data call. The end point is
- * specified by DataProfileInfo.apn; DataProfileInfo.apn must be used as the end point if
- * one is not specified through URSP rules.
* @param matchAllRuleAllowed bool to indicate if using default match-all URSP rule for this
* request is allowed. If false, this request must not use the match-all URSP rule and if
* a non-match-all rule is not found (or if URSP rules are not available) it should
@@ -238,7 +233,6 @@
in DataProfileInfo dataProfileInfo, in boolean roamingAllowed,
in DataRequestReason reason, in LinkAddress[] addresses, in String[] dnses,
in int pduSessionId, in @nullable SliceInfo sliceInfo,
- in @nullable TrafficDescriptor trafficDescriptor,
in boolean matchAllRuleAllowed);
/**
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
index 8e73ee3..938c695 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -17,9 +17,11 @@
package android.hardware.radio.data;
import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.data.DataProfileInfo;
import android.hardware.radio.data.KeepaliveStatus;
import android.hardware.radio.data.PcoDataInfo;
import android.hardware.radio.data.SetupDataCallResult;
+import android.hardware.radio.data.SlicingConfig;
/**
* Interface declaring unsolicited radio indications for data APIs.
@@ -68,7 +70,20 @@
* is sent, AOSP will no longer throttle calls to IRadioData.SetupDataCall for the given APN.
*
* @param type Type of radio indication
- * @param apn Apn to unthrottle
+ * @param dataProfileInfo Data profile info.
*/
- void unthrottleApn(in RadioIndicationType type, in String apn);
+ void unthrottleApn(in RadioIndicationType type, in DataProfileInfo dataProfileInfo);
+
+ /**
+ * Indicates the current slicing configuration including URSP rules and NSSAIs
+ * (configured, allowed and rejected). URSP stands for UE route selection policy and is defined
+ * in 3GPP TS 24.526 Section 4.2. An NSSAI is a collection of network slices. Each network slice
+ * is identified by an S-NSSAI and is represented by the struct SliceInfo. NSSAI and S-NSSAI
+ * are defined in 3GPP TS 24.501.
+ *
+ * @param type Type of radio indication
+ * @param slicingConfig Current slicing configuration
+ *
+ */
+ void slicingConfigChanged(in RadioIndicationType type, in SlicingConfig slicingConfig);
}
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
index 1dbaed3..8bd84a3 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -79,15 +79,6 @@
in int serial, in boolean success, in SmsAcknowledgeFailCause cause);
/**
- * Cancel the current USSD session if one exists.
- *
- * @param serial Serial number of request.
- *
- * Response function is IRadioMessagingResponse.cancelPendingUssdResponse()
- */
- void cancelPendingUssd(in int serial);
-
- /**
* Deletes a CDMA SMS message from RUIM memory.
*
* @param serial Serial number of request.
@@ -212,23 +203,6 @@
void sendSmsExpectMore(in int serial, in GsmSmsMessage message);
/**
- * Send a USSD message. If a USSD session already exists, the message must be sent in the
- * context of that session. Otherwise, a new session must be created. The network reply must be
- * reported via unsolOnUssd.
- *
- * Only one USSD session must exist at a time, and the session is assumed to exist until:
- * a) The android system invokes cancelUssd()
- * b) The implementation sends a unsolOnUssd() with a type code of
- * "0" (USSD-Notify/no further action) or "2" (session terminated)
- *
- * @param serial Serial number of request.
- * @param ussd string containing the USSD request in UTF-8 format
- *
- * Response function is IRadioMessagingResponse.sendUssdResponse()
- */
- void sendUssd(in int serial, in String ussd);
-
- /**
* Enable or disable the reception of CDMA Cell Broadcast SMS
*
* @param serial Serial number of request.
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
index 4b40bfb..8834cd9 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -18,7 +18,6 @@
import android.hardware.radio.RadioIndicationType;
import android.hardware.radio.messaging.CdmaSmsMessage;
-import android.hardware.radio.messaging.UssdModeType;
/**
* Interface declaring unsolicited radio indications for messaging APIs.
@@ -86,16 +85,6 @@
void newSmsStatusReport(in RadioIndicationType type, in byte[] pdu);
/**
- * Indicates when a new USSD message is received. The USSD session is assumed to persist if the
- * type code is REQUEST, otherwise the current session (if any) is assumed to have terminated.
- *
- * @param type Type of radio indication
- * @param modeType USSD type code
- * @param msg Message string in UTF-8, if applicable
- */
- void onUssd(in RadioIndicationType type, in UssdModeType modeType, in String msg);
-
- /**
* Indicates that SMS storage on the SIM is full. Sent when the network attempts to deliver a
* new SMS message. Messages cannot be saved on the SIM until space is freed. In particular,
* incoming Class 2 messages must not be stored.
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
index 75fa390..492755f 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -92,27 +92,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:SIM_BUSY
- * RadioError:OPERATION_NOT_ALLOWED
- * RadioError:MODEM_ERR
- * RadioError:INTERNAL_ERR
- * RadioError:NO_MEMORY
- * RadioError:INVALID_STATE
- * RadioError:INVALID_ARGUMENTS
- * RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
- * RadioError:INVALID_MODEM_STATE
- * RadioError:NO_RESOURCES
- * RadioError:CANCELLED
- */
- void cancelPendingUssdResponse(in RadioResponseInfo info);
-
- /**
- * @param info Response info struct containing response type, serial no. and error
- *
- * Valid errors returned:
- * RadioError:NONE
- * RadioError:RADIO_NOT_AVAILABLE
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_MEMORY
* RadioError:SYSTEM_ERR
@@ -407,32 +386,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:FDN_CHECK_FAILURE
- * RadioError:USSD_MODIFIED_TO_DIAL
- * RadioError:USSD_MODIFIED_TO_SS
- * RadioError:USSD_MODIFIED_TO_USSD
- * RadioError:SIM_BUSY
- * RadioError:OPERATION_NOT_ALLOWED
- * RadioError:INVALID_ARGUMENTS
- * RadioError:NO_MEMORY
- * RadioError:MODEM_ERR
- * RadioError:INTERNAL_ERR
- * RadioError:ABORTED
- * RadioError:SYSTEM_ERR
- * RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
- * RadioError:INVALID_MODEM_STATE
- * RadioError:NO_RESOURCES
- * RadioError:CANCELLED
- */
- void sendUssdResponse(in RadioResponseInfo info);
-
- /**
- * @param info Response info struct containing response type, serial no. and error
- *
- * Valid errors returned:
- * RadioError:NONE
- * RadioError:RADIO_NOT_AVAILABLE
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_STATE
* RadioError:NO_MEMORY
diff --git a/radio/aidl/android/hardware/radio/messaging/UssdModeType.aidl b/radio/aidl/android/hardware/radio/messaging/UssdModeType.aidl
deleted file mode 100644
index c3c111e..0000000
--- a/radio/aidl/android/hardware/radio/messaging/UssdModeType.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.messaging;
-
-@VintfStability
-@Backing(type="int")
-enum UssdModeType {
- /**
- * USSD-Notify
- */
- NOTIFY,
- /**
- * USSD-Request
- */
- REQUEST,
- /**
- * Session terminated by network
- */
- NW_RELEASE,
- /**
- * Other local client (eg, SIM Toolkit) has responded
- */
- LOCAL_CLIENT,
- /**
- * Operation not supported
- */
- NOT_SUPPORTED,
- /**
- * Network timeout
- */
- NW_TIMEOUT,
-}
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
index 764a86d..d0aa695 100644
--- a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -16,6 +16,8 @@
package android.hardware.radio.modem;
+import android.hardware.radio.modem.ActivityStatsTechSpecificInfo;
+
@VintfStability
parcelable ActivityStatsInfo {
/**
@@ -28,17 +30,10 @@
*/
int idleModeTimeMs;
/**
- * Each index represent total time (in ms) during which the transmitter is active/awake for a
- * particular power range as shown below.
- * index 0 = tx_power < 0dBm
- * index 1 = 0dBm < tx_power < 5dBm
- * index 2 = 5dBm < tx_power < 15dBm
- * index 3 = 15dBm < tx_power < 20dBm
- * index 4 = tx_power > 20dBm
+ * Technology specific activity stats info.
+ * List of the activity stats for each RATs (2G, 3G, 4G and 5G) and frequency ranges (HIGH for
+ * sub6 and MMWAVE) in case of 5G. In case implementation doesn't have RAT specific activity
+ * stats then send only one activity stats info with RAT unknown.
*/
- int[] txmModetimeMs;
- /**
- * Total time (in ms) for which receiver is active/awake and the transmitter is inactive
- */
- int rxModeTimeMs;
+ ActivityStatsTechSpecificInfo[] techSpecificInfo;
}
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
new file mode 100644
index 0000000..fb14223
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.modem;
+
+import android.hardware.radio.AccessNetwork;
+
+@VintfStability
+parcelable ActivityStatsTechSpecificInfo {
+ /** Indicates the frequency range is unknown. */
+ const int FREQUENCY_RANGE_UNKNOWN = 0;
+ /** Indicates the frequency range is below 1GHz. */
+ const int FREQUENCY_RANGE_LOW = 1;
+ /** Indicates the frequency range is between 1GHz and 3GHz. */
+ const int FREQUENCY_RANGE_MID = 2;
+ /** Indicates the frequency range is between 3GHz and 6GHz. */
+ const int FREQUENCY_RANGE_HIGH = 3;
+ /** Indicates the frequency range is above 6GHz (millimeter wave frequency). */
+ const int FREQUENCY_RANGE_MMWAVE = 4;
+ /**
+ * Radio access technology. Set UNKNOWN if the Activity statistics
+ * is RAT independent.
+ */
+ AccessNetwork rat;
+ /**
+ * Frequency range. Values are FREQUENCY_RANGE_
+ * Set FREQUENCY_RANGE_UNKNOWN if the Activity statistics when frequency range
+ * is not applicable.
+ */
+ int frequencyRange;
+ /**
+ * Each index represent total time (in ms) during which the transmitter is active/awake for a
+ * particular power range as shown below.
+ * index 0 = tx_power <= 0dBm
+ * index 1 = 0dBm < tx_power <= 5dBm
+ * index 2 = 5dBm < tx_power <= 15dBm
+ * index 3 = 15dBm < tx_power <= 20dBm
+ * index 4 = tx_power > 20dBm
+ */
+ int[] txmModetimeMs;
+ /**
+ * Total time (in ms) for which receiver is active/awake and the transmitter is inactive
+ */
+ int rxModeTimeMs;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
index b7b8ef3..96b9d0d 100644
--- a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
@@ -16,8 +16,6 @@
package android.hardware.radio.modem;
-import android.hardware.radio.RadioAccessFamily;
-
@VintfStability
parcelable RadioCapability {
/**
@@ -71,7 +69,7 @@
/**
* 32-bit bitmap of RadioAccessFamily.
*/
- RadioAccessFamily raf;
+ int raf;
/**
* A UUID typically "com.xxxx.lmX" where X is the logical modem.
* RadioConst:MAX_UUID_LENGTH is the max length.
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 1081a75..cce52ff 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -17,7 +17,6 @@
package android.hardware.radio.network;
import android.hardware.radio.AccessNetwork;
-import android.hardware.radio.RadioAccessFamily;
import android.hardware.radio.network.CdmaRoamingType;
import android.hardware.radio.network.IRadioNetworkIndication;
import android.hardware.radio.network.IRadioNetworkResponse;
@@ -27,6 +26,7 @@
import android.hardware.radio.network.RadioAccessSpecifier;
import android.hardware.radio.network.RadioBandMode;
import android.hardware.radio.network.SignalThresholdInfo;
+import android.hardware.radio.network.UsageSetting;
/**
* This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -194,7 +194,7 @@
*
* Response function is IRadioNetworkResponse.setAllowedNetworkTypesBitmapResponse()
*/
- void setAllowedNetworkTypesBitmap(in int serial, in RadioAccessFamily networkTypeBitmap);
+ void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
/**
* Assign a specified band for RF configuration.
@@ -252,7 +252,7 @@
*
* Response function is IRadioNetworkResponse.setIndicationFilterResponse()
*/
- void setIndicationFilter(in int serial, in IndicationFilter indicationFilter);
+ void setIndicationFilter(in int serial, in int indicationFilter);
/**
* Sets the link capacity reporting criteria. The resulting reporting criteria are the AND of
@@ -416,4 +416,25 @@
* Response function is IRadioNetworkResponse.supplyNetworkDepersonalizationResponse()
*/
void supplyNetworkDepersonalization(in int serial, in String netPin);
+
+ /**
+ * Set the UE usage setting for data/voice centric usage.
+ *
+ * <p>Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ * <p>This value must be independently preserved for each SIM; (setting the value is not a
+ * "global" override).
+ *
+ * @param serial Serial number of request.
+ * @param usageSetting the usage setting for the current SIM.
+ */
+ oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+
+ /**
+ * Get the UE usage setting for data/voice centric usage.
+ *
+ * <p>Gets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * @param serial Serial number of request.
+ */
+ oneway void getUsageSetting(in int serial);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index ba7610d..f471433 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -21,7 +21,6 @@
import android.hardware.radio.network.BarringInfo;
import android.hardware.radio.network.CellIdentity;
import android.hardware.radio.network.CellInfo;
-import android.hardware.radio.network.Domain;
import android.hardware.radio.network.LinkCapacityEstimate;
import android.hardware.radio.network.NetworkScanResult;
import android.hardware.radio.network.PhoneRestrictedState;
@@ -136,8 +135,8 @@
* include the time spend in sleep / low power states. If it can not be guaranteed,
* there must not be any caching done at the modem and should fill in 0 for ageMs
*/
- void nitzTimeReceived(in RadioIndicationType type, in String nitzTime,
- in long receivedTimeMs, in long ageMs);
+ void nitzTimeReceived(
+ in RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
/**
* Report that Registration or a Location/Routing/Tracking Area update has failed.
@@ -165,7 +164,7 @@
* MAX_INT if this value is unused.
*/
void registrationFailed(in RadioIndicationType type, in CellIdentity cellIdentity,
- in String chosenPlmn, in Domain domain, in int causeCode, in int additionalCauseCode);
+ in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
/**
* Indicates a restricted state change (eg, for Domain Specific Access Control).
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 429b5a8..dcf0004 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -16,7 +16,6 @@
package android.hardware.radio.network;
-import android.hardware.radio.RadioAccessFamily;
import android.hardware.radio.RadioResponseInfo;
import android.hardware.radio.RadioTechnology;
import android.hardware.radio.RadioTechnologyFamily;
@@ -24,13 +23,12 @@
import android.hardware.radio.network.CdmaRoamingType;
import android.hardware.radio.network.CellIdentity;
import android.hardware.radio.network.CellInfo;
-import android.hardware.radio.network.LceDataInfo;
-import android.hardware.radio.network.NeighboringCell;
import android.hardware.radio.network.OperatorInfo;
import android.hardware.radio.network.RadioAccessSpecifier;
import android.hardware.radio.network.RadioBandMode;
import android.hardware.radio.network.RegStateResult;
import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.UsageSetting;
/**
* Interface declaring response functions to solicited radio requests for network APIs.
@@ -61,8 +59,7 @@
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
*/
- void getAllowedNetworkTypesBitmapResponse(
- in RadioResponseInfo info, in RadioAccessFamily networkTypeBitmap);
+ void getAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info, in int networkTypeBitmap);
/**
* @param info Response info struct containing response type, serial no. and error
@@ -549,4 +546,30 @@
* RadioError:SIM_ABSENT
*/
void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INVALID_STATE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:INTERNAL_ERR
+ * RadioError:SIM_ABSENT
+ */
+ oneway void setUsageSettingResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ * @param usageSetting the usage setting for the current SIM.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INVALID_STATE
+ * RadioError:INTERNAL_ERR
+ * RadioError:SIM_ABSENT
+ */
+ oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
}
diff --git a/radio/aidl/android/hardware/radio/network/NeighboringCell.aidl b/radio/aidl/android/hardware/radio/network/NeighboringCell.aidl
deleted file mode 100644
index 270bdee..0000000
--- a/radio/aidl/android/hardware/radio/network/NeighboringCell.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.network;
-
-@VintfStability
-parcelable NeighboringCell {
- /**
- * Combination of LAC and cell ID in 32 bits in GSM. Upper 16 bits is LAC and lower 16 bits is
- * CID (as described in TS 27.005).
- */
- String cid;
- /**
- * Received RSSI in GSM, level index of CPICH Received Signal Code Power in UMTS
- */
- int rssi;
-}
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..ba8fe93
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.network;
+
+/**
+ * Cellular usage setting with values according to 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
+ * Annex A.
+ */
+@VintfStability
+@Backing(type="int")
+enum UsageSetting {
+ /**
+ * UE operates in voice-centric mode. Generally speaking, in this mode of operation, the UE
+ * will not remain camped on a cell or attached to a network unless that cell/network provides
+ * voice service.
+ */
+ VOICE_CENTRIC = 1,
+
+ /**
+ * UE operates in data-centric mode. Generally speaking, in this mode of operation, the UE
+ * will not reselect away from a cell/network that only provides data services.
+ */
+ DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
index 12df138..ef38fdc 100644
--- a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -31,11 +31,6 @@
*/
Carrier[] excludedCarriers;
/**
- * Whether this is a carrier restriction with priority or not.
- * If this is false, allowedCarriersPrioritized is not applicable.
- */
- boolean priority;
- /**
* True means that only carriers included in the allowed list and not in the excluded list
* are permitted. Eg. allowedCarriers match mcc/mnc, excludedCarriers has same mcc/mnc and
* gid1 is ABCD. It means except the carrier whose gid1 is ABCD, all carriers with the
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index c731caf..7923b14 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -205,6 +205,12 @@
* Open a new logical channel and select the given application. This command
* reflects TS 27.007 "open logical channel" operation (+CCHO).
*
+ * For MEP-A(Multiple enabled profile), only dedicated port 0 is ISDR selectable.
+ * e.g., Port0 - for ISDR access and Port1/Port2 - the currently active ports/subscriptions.
+ * Port 0 should be transparent to AP and iccLogicalChannel API should remain the same.
+ * Even if the ISDR request comes over port1 or port2, Modem would just internally convert the
+ * portID to port0 and add the real port index as the payload of MANAGE_CHANNEL command.
+ *
* @param serial Serial number of request.
* @param aid AID value, See ETSI 102.221 and 101.220.
* @param p2 P2 value, described in ISO 7816-4. Ignore if equal to RadioConst:P2_CONSTANT_NO_P2
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
index aa4dde2..9fed78e 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -16,8 +16,6 @@
package android.hardware.radio.voice;
-import android.hardware.radio.voice.EmergencyServiceCategory;
-
/**
* Emergency number contains information of number, one or more service category(s), zero or more
* emergency uniform resource names, mobile country code (mcc), mobile network country (mnc) and
@@ -78,7 +76,7 @@
* The bitfield of EmergencyServiceCategory(s). See EmergencyServiceCategory for the value of
* each bit.
*/
- EmergencyServiceCategory categories;
+ int categories;
/**
* The list of emergency Uniform Resource Names (URN).
*/
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
index a012be4..c05d237 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
@@ -19,7 +19,6 @@
import android.hardware.radio.voice.CallForwardInfo;
import android.hardware.radio.voice.Dial;
import android.hardware.radio.voice.EmergencyCallRouting;
-import android.hardware.radio.voice.EmergencyServiceCategory;
import android.hardware.radio.voice.IRadioVoiceIndication;
import android.hardware.radio.voice.IRadioVoiceResponse;
import android.hardware.radio.voice.TtyMode;
@@ -45,6 +44,15 @@
void acceptCall(in int serial);
/**
+ * Cancel the current USSD session if one exists.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioVoiceResponse.cancelPendingUssdResponse()
+ */
+ void cancelPendingUssd(in int serial);
+
+ /**
* Conference holding and active (like AT+CHLD=3)
*
* @param serial Serial number of request.
@@ -117,9 +125,9 @@
*
* Response function is IRadioVoiceResponse.emergencyDialResponse()
*/
- void emergencyDial(in int serial, in Dial dialInfo, in EmergencyServiceCategory categories,
- in String[] urns, in EmergencyCallRouting routing,
- in boolean hasKnownUserIntentEmergency, in boolean isTesting);
+ void emergencyDial(in int serial, in Dial dialInfo, in int categories, in String[] urns,
+ in EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency,
+ in boolean isTesting);
/**
* Request the radio's system selection module to exit emergency callback mode. Radio must not
@@ -325,6 +333,23 @@
void sendDtmf(in int serial, in String s);
/**
+ * Send a USSD message. If a USSD session already exists, the message must be sent in the
+ * context of that session. Otherwise, a new session must be created. The network reply must be
+ * reported via unsolOnUssd.
+ *
+ * Only one USSD session must exist at a time, and the session is assumed to exist until:
+ * a) The android system invokes cancelUssd()
+ * b) The implementation sends a unsolOnUssd() with a type code of
+ * "0" (USSD-Notify/no further action) or "2" (session terminated)
+ *
+ * @param serial Serial number of request.
+ * @param ussd string containing the USSD request in UTF-8 format
+ *
+ * Response function is IRadioVoiceResponse.sendUssdResponse()
+ */
+ void sendUssd(in int serial, in String ussd);
+
+ /**
* Separate a party from a multiparty call placing the multiparty call (less the specified
* party) on hold and leaving the specified party as the only other member of the current
* (active) call. Like AT+CHLD=2x.
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
index 25e87b3..437fef6 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -24,6 +24,7 @@
import android.hardware.radio.voice.EmergencyNumber;
import android.hardware.radio.voice.SrvccState;
import android.hardware.radio.voice.StkCcUnsolSsResult;
+import android.hardware.radio.voice.UssdModeType;
/**
* Interface declaring unsolicited radio indications for voice APIs.
@@ -138,6 +139,16 @@
void onSupplementaryServiceIndication(in RadioIndicationType type, in StkCcUnsolSsResult ss);
/**
+ * Indicates when a new USSD message is received. The USSD session is assumed to persist if the
+ * type code is REQUEST, otherwise the current session (if any) is assumed to have terminated.
+ *
+ * @param type Type of radio indication
+ * @param modeType USSD type code
+ * @param msg Message string in UTF-8, if applicable
+ */
+ void onUssd(in RadioIndicationType type, in UssdModeType modeType, in String msg);
+
+ /**
* Indicates that framework/application must reset the uplink mute state.
*
* @param type Type of radio indication
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
index d126fc1..cf1b953 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -62,6 +62,27 @@
*
* Valid errors returned:
* RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:SIM_BUSY
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_MEMORY
+ * RadioError:INVALID_STATE
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:SYSTEM_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_MODEM_STATE
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ */
+ void cancelPendingUssdResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE (radio resetting)
* RadioError:NO_MEMORY
* RadioError:MODEM_ERR
@@ -569,6 +590,32 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:FDN_CHECK_FAILURE
+ * RadioError:USSD_MODIFIED_TO_DIAL
+ * RadioError:USSD_MODIFIED_TO_SS
+ * RadioError:USSD_MODIFIED_TO_USSD
+ * RadioError:SIM_BUSY
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_MEMORY
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:ABORTED
+ * RadioError:SYSTEM_ERR
+ * RadioError:INVALID_STATE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_MODEM_STATE
+ * RadioError:NO_RESOURCES
+ * RadioError:CANCELLED
+ */
+ void sendUssdResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_STATE
* RadioError:NO_RESOURCES
diff --git a/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
new file mode 100644
index 0000000..48d1fca
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.voice;
+
+@VintfStability
+@Backing(type="int")
+enum UssdModeType {
+ /**
+ * USSD-Notify
+ */
+ NOTIFY,
+ /**
+ * USSD-Request
+ */
+ REQUEST,
+ /**
+ * Session terminated by network
+ */
+ NW_RELEASE,
+ /**
+ * Other local client (eg, SIM Toolkit) has responded
+ */
+ LOCAL_CLIENT,
+ /**
+ * Operation not supported
+ */
+ NOT_SUPPORTED,
+ /**
+ * Network timeout
+ */
+ NW_TIMEOUT,
+}
diff --git a/radio/aidl/compat/OWNERS b/radio/aidl/compat/OWNERS
new file mode 100644
index 0000000..471d806
--- /dev/null
+++ b/radio/aidl/compat/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../../1.0/vts/OWNERS
+twasilczyk@google.com
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
new file mode 100644
index 0000000..487d91b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -0,0 +1,95 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+ name: "android.hardware.radio-library.compat",
+ relative_install_path: "hw",
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ ],
+ shared_libs: [
+ "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
+ "android.hardware.radio.config@1.2",
+ "android.hardware.radio.config@1.3",
+ "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.messaging-V1-ndk",
+ "android.hardware.radio.modem-V1-ndk",
+ "android.hardware.radio.network-V1-ndk",
+ "android.hardware.radio.sim-V1-ndk",
+ "android.hardware.radio.voice-V1-ndk",
+ "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.hardware.radio@1.6",
+ "libbase",
+ "libbinder_ndk",
+ "libhidlbase",
+ "libutils",
+ ],
+ srcs: [
+ "CallbackManager.cpp",
+ "DriverContext.cpp",
+ "RadioCompatBase.cpp",
+ "RadioIndication.cpp",
+ "RadioResponse.cpp",
+ "commonStructs.cpp",
+ "config/RadioConfig.cpp",
+ "config/RadioConfigIndication.cpp",
+ "config/RadioConfigResponse.cpp",
+ "config/structs.cpp",
+ "data/RadioIndication-data.cpp",
+ "data/RadioResponse-data.cpp",
+ "data/RadioData.cpp",
+ "data/structs.cpp",
+ "messaging/RadioIndication-messaging.cpp",
+ "messaging/RadioMessaging.cpp",
+ "messaging/RadioResponse-messaging.cpp",
+ "messaging/structs.cpp",
+ "modem/RadioIndication-modem.cpp",
+ "modem/RadioResponse-modem.cpp",
+ "modem/RadioModem.cpp",
+ "modem/structs.cpp",
+ "network/RadioIndication-network.cpp",
+ "network/RadioNetwork.cpp",
+ "network/RadioResponse-network.cpp",
+ "network/structs.cpp",
+ "network/utils.cpp",
+ "sim/RadioIndication-sim.cpp",
+ "sim/RadioResponse-sim.cpp",
+ "sim/RadioSim.cpp",
+ "sim/structs.cpp",
+ "voice/RadioIndication-voice.cpp",
+ "voice/RadioResponse-voice.cpp",
+ "voice/RadioVoice.cpp",
+ "voice/structs.cpp",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
new file mode 100644
index 0000000..c2eaed1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/CallbackManager.h>
+
+#include <android-base/logging.h>
+
+using namespace std::literals::chrono_literals;
+
+namespace android::hardware::radio::compat {
+
+/**
+ * How much setter thread will wait with setting response functions after the last
+ * setResponseFunctions call from the framework. Subsequent calls from the framework reset the
+ * clock, so this number should be larger than the longest time between setResponseFunctions calls
+ * from the framework.
+ *
+ * Real world measurements with Cuttlefish give <10ms delay between Modem and Data and <2ms delays
+ * between all others.
+ */
+static constexpr auto kDelayedSetterDelay = 100ms;
+
+CallbackManager::CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal)
+ : mHidlHal(hidlHal),
+ mRadioResponse(sp<compat::RadioResponse>::make(context)),
+ mRadioIndication(sp<compat::RadioIndication>::make(context)),
+ mDelayedSetterThread(&CallbackManager::delayedSetterThread, this) {}
+
+CallbackManager::~CallbackManager() {
+ {
+ std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+ mDelayedSetterDeadline = std::nullopt;
+ mDestroy = true;
+ mDelayedSetterCv.notify_all();
+ }
+ mDelayedSetterThread.join();
+}
+
+RadioResponse& CallbackManager::response() const {
+ return *mRadioResponse;
+}
+
+void CallbackManager::setResponseFunctionsDelayed() {
+ std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+ mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay;
+ mDelayedSetterCv.notify_all();
+}
+
+void CallbackManager::delayedSetterThread() {
+ while (!mDestroy) {
+ std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+ auto deadline = mDelayedSetterDeadline;
+
+ // not waiting to set response functions
+ if (!deadline) {
+ mDelayedSetterCv.wait(lock);
+ continue;
+ }
+
+ // waiting to set response functions, but not yet
+ if (*deadline > std::chrono::steady_clock::now()) {
+ mDelayedSetterCv.wait_until(lock, *deadline);
+ continue;
+ }
+
+ mHidlHal->setResponseFunctions(mRadioResponse, mRadioIndication).assertOk();
+ mDelayedSetterDeadline = std::nullopt;
+ }
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/DriverContext.cpp b/radio/aidl/compat/libradiocompat/DriverContext.cpp
new file mode 100644
index 0000000..a07173e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/DriverContext.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/DriverContext.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio;
+
+void DriverContext::addDataProfile(const aidl::data::DataProfileInfo& profile) {
+ mDataProfiles[profile.apn] = profile;
+}
+
+aidl::data::DataProfileInfo DriverContext::getDataProfile(const std::string& apn) {
+ const auto it = mDataProfiles.find(apn);
+ if (it != mDataProfiles.end()) return it->second;
+
+ // if not found in cache, return a made up default
+ return {
+ .apn = apn,
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
new file mode 100644
index 0000000..2a2d7a3
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioCompatBase.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+RadioCompatBase::RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+ std::shared_ptr<CallbackManager> cbMgr)
+ : mContext(context),
+ mHal1_5(hidlHal),
+ mHal1_6(V1_6::IRadio::castFrom(hidlHal)),
+ mCallbackManager(cbMgr) {}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioIndication.cpp b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
new file mode 100644
index 0000000..30ef6a0
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+namespace android::hardware::radio::compat {
+
+RadioIndication::RadioIndication(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
new file mode 100644
index 0000000..dab70cc
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "debug.h"
+
+#define RADIO_MODULE "Common"
+
+namespace android::hardware::radio::compat {
+
+RadioResponse::RadioResponse(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
+Return<void> RadioResponse::acknowledgeRequest(int32_t serial) {
+ LOG_CALL << serial;
+ /* We send ACKs to all callbacks instead of the one requested it to make implementation simpler.
+ * If it turns out to be a problem, we would have to track where serials come from and make sure
+ * this tracking data (e.g. a map) doesn't grow indefinitely.
+ */
+ if (mDataCb) mDataCb.get()->acknowledgeRequest(serial);
+ if (mMessagingCb) mMessagingCb.get()->acknowledgeRequest(serial);
+ if (mModemCb) mModemCb.get()->acknowledgeRequest(serial);
+ if (mNetworkCb) mNetworkCb.get()->acknowledgeRequest(serial);
+ if (mSimCb) mSimCb.get()->acknowledgeRequest(serial);
+ if (mVoiceCb) mVoiceCb.get()->acknowledgeRequest(serial);
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/collections.h b/radio/aidl/compat/libradiocompat/collections.h
new file mode 100644
index 0000000..082ef17
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/collections.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <hidl/HidlSupport.h>
+
+#include <type_traits>
+#include <variant>
+
+namespace android::hardware::radio::compat {
+
+/**
+ * Converts hidl_vec<T> HIDL list to std::vector<T> AIDL list.
+ *
+ * To convert values, the template uses toAidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp vector to convert
+ */
+template <typename T>
+auto toAidl(const hidl_vec<T>& inp) {
+ std::vector<decltype(toAidl(T{}))> out(inp.size());
+ for (size_t i = 0; i < inp.size(); i++) {
+ out[i] = toAidl(inp[i]);
+ }
+ return out;
+}
+
+/**
+ * Converts std::vector<T> AIDL list to hidl_vec<T> HIDL list.
+ *
+ * To convert values, the template uses toHidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp vector to convert
+ */
+template <typename T>
+auto toHidl(const std::vector<T>& inp) {
+ hidl_vec<decltype(toHidl(T{}))> out(inp.size());
+ for (size_t i = 0; i < inp.size(); i++) {
+ out[i] = toHidl(inp[i]);
+ }
+ return out;
+}
+
+/**
+ * Converts hidl_array<T> HIDL list to std::vector<T> AIDL list.
+ *
+ * To convert values, the template uses toAidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp array to convert
+ */
+template <typename T, size_t N>
+auto toAidl(const hidl_array<T, N>& inp) {
+ std::vector<decltype(toAidl(T{}))> out(N);
+ for (size_t i = 0; i < N; i++) {
+ out[i] = toAidl(inp[i]);
+ }
+ return out;
+}
+
+/**
+ * Converts T=OptionalX HIDL value to std::optional<X> AIDL value.
+ *
+ * To convert values, the template uses toAidl functions for a given type T.value.
+ */
+template <typename T>
+std::optional<decltype(toAidl(T{}.value()))> toAidl(const T& opt) {
+ if (opt.getDiscriminator() == T::hidl_discriminator::noinit) return std::nullopt;
+ return toAidl(opt.value());
+}
+
+/**
+ * Converts T=OptionalX HIDL value to std::variant<bool, X> AIDL value.
+ *
+ * For some reason, not every OptionalX gets generated into a std::optional<X>.
+ */
+template <typename T>
+std::variant<bool, decltype(toAidl(T{}.value()))> toAidlVariant(const T& opt) {
+ if (opt.getDiscriminator() == T::hidl_discriminator::noinit) return false;
+ return toAidl(opt.value());
+}
+
+/**
+ * Converts std::optional<X> AIDL value to T=OptionalX HIDL value.
+ *
+ * X is inferred from toAidl(T.value) declaration. Please note that toAidl(T.value) doesn't have to
+ * be implemented if it's not needed for anything else than giving this hint to type system.
+ *
+ * To convert values, the template uses toHidl functions for a given type T, assuming it's defined.
+ *
+ * \param opt value to convert
+ */
+template <typename T>
+T toHidl(const std::optional<decltype(toAidl(T{}.value()))>& opt) {
+ T hidl;
+ if (opt.has_value()) hidl.value(toHidl(*opt));
+ return hidl;
+}
+
+/**
+ * Converts U AIDL bitfield value to HIDL T bitfield value.
+ *
+ * \param val value to convert
+ */
+template <typename T, typename U>
+hidl_bitfield<T> toHidlBitfield(U val) {
+ return static_cast<int>(val);
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.cpp b/radio/aidl/compat/libradiocompat/commonStructs.cpp
new file mode 100644
index 0000000..6e4c873
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/commonStructs.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "commonStructs.h"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio;
+
+aidl::RadioResponseInfo notSupported(int32_t serial) {
+ return {
+ .type = aidl::RadioResponseType::SOLICITED,
+ .serial = serial,
+ .error = aidl::RadioError::REQUEST_NOT_SUPPORTED,
+ };
+}
+
+std::string toAidl(const hidl_string& str) {
+ return str;
+}
+
+hidl_string toHidl(const std::string& str) {
+ return str;
+}
+
+uint8_t toAidl(int8_t v) {
+ return v;
+}
+
+int8_t toAidl(uint8_t v) {
+ return v;
+}
+
+int32_t toAidl(uint32_t v) {
+ return v;
+}
+
+aidl::RadioIndicationType toAidl(V1_0::RadioIndicationType type) {
+ return aidl::RadioIndicationType(type);
+}
+
+aidl::RadioResponseType toAidl(V1_0::RadioResponseType type) {
+ return aidl::RadioResponseType(type);
+}
+
+aidl::RadioError toAidl(V1_0::RadioError err) {
+ return aidl::RadioError(err);
+}
+
+aidl::RadioError toAidl(V1_6::RadioError err) {
+ return aidl::RadioError(err);
+}
+
+aidl::RadioResponseInfo toAidl(const V1_0::RadioResponseInfo& info) {
+ return {
+ .type = toAidl(info.type),
+ .serial = info.serial,
+ .error = toAidl(info.error),
+ };
+}
+
+aidl::RadioResponseInfo toAidl(const V1_6::RadioResponseInfo& info) {
+ return {
+ .type = toAidl(info.type),
+ .serial = info.serial,
+ .error = toAidl(info.error),
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.h b/radio/aidl/compat/libradiocompat/commonStructs.h
new file mode 100644
index 0000000..a4a4869
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/commonStructs.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/RadioIndicationType.h>
+#include <aidl/android/hardware/radio/RadioResponseInfo.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+aidl::android::hardware::radio::RadioResponseInfo notSupported(int32_t serial);
+
+std::string toAidl(const hidl_string& str);
+hidl_string toHidl(const std::string& str);
+uint8_t toAidl(int8_t v);
+int8_t toAidl(uint8_t v);
+int32_t toAidl(uint32_t v);
+
+aidl::android::hardware::radio::RadioIndicationType toAidl(V1_0::RadioIndicationType type);
+aidl::android::hardware::radio::RadioResponseType toAidl(V1_0::RadioResponseType type);
+aidl::android::hardware::radio::RadioError toAidl(V1_0::RadioError type);
+aidl::android::hardware::radio::RadioError toAidl(V1_6::RadioError type);
+
+aidl::android::hardware::radio::RadioResponseInfo toAidl(const V1_0::RadioResponseInfo& info);
+aidl::android::hardware::radio::RadioResponseInfo toAidl(const V1_6::RadioResponseInfo& info);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
new file mode 100644
index 0000000..b450418
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioConfig.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Config"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::config;
+constexpr auto ok = &ScopedAStatus::ok;
+
+RadioConfig::RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal)
+ : mHal1_1(hidlHal),
+ mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)),
+ mRadioConfigResponse(sp<RadioConfigResponse>::make()),
+ mRadioConfigIndication(sp<RadioConfigIndication>::make()) {}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfig::respond() {
+ return mRadioConfigResponse->respond();
+}
+
+ScopedAStatus RadioConfig::getHalDeviceCapabilities(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_3) {
+ mHal1_3->getHalDeviceCapabilities(serial);
+ } else {
+ respond()->getHalDeviceCapabilitiesResponse(notSupported(serial), false);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioConfig::getNumOfLiveModems(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_1->getModemsConfig(serial);
+ return ok();
+}
+
+ScopedAStatus RadioConfig::getPhoneCapability(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_1->getPhoneCapability(serial);
+ return ok();
+}
+
+ScopedAStatus RadioConfig::getSimSlotsStatus(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_1->getSimSlotsStatus(serial);
+ return ok();
+}
+
+ScopedAStatus RadioConfig::setNumOfLiveModems(int32_t serial, int8_t numOfLiveModems) {
+ LOG_CALL << serial;
+ mHal1_1->setModemsConfig(serial, {static_cast<uint8_t>(numOfLiveModems)});
+ return ok();
+}
+
+ScopedAStatus RadioConfig::setPreferredDataModem(int32_t serial, int8_t modemId) {
+ LOG_CALL << serial;
+ mHal1_1->setPreferredDataModem(serial, modemId);
+ return ok();
+}
+
+ScopedAStatus RadioConfig::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioConfigResponse>& radioConfigResponse,
+ const std::shared_ptr<aidl::IRadioConfigIndication>& radioConfigIndication) {
+ LOG_CALL << radioConfigResponse << ' ' << radioConfigIndication;
+
+ CHECK(radioConfigResponse);
+ CHECK(radioConfigIndication);
+
+ mRadioConfigResponse->setResponseFunction(radioConfigResponse);
+ mRadioConfigIndication->setResponseFunction(radioConfigIndication);
+ mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication).assertOk();
+
+ return ok();
+}
+
+ScopedAStatus RadioConfig::setSimSlotsMapping( //
+ int32_t serial, const std::vector<aidl::SlotPortMapping>& slotMap) {
+ LOG_CALL << serial;
+ mHal1_1->setSimSlotsMapping(serial, toHidl(slotMap));
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
new file mode 100644
index 0000000..c1e32c1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioConfigIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ConfigIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+void RadioConfigIndication::setResponseFunction(
+ std::shared_ptr<aidl::IRadioConfigIndication> callback) {
+ mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigIndication> RadioConfigIndication::indicate() {
+ return mCallback.get();
+}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged(
+ V1_0::RadioIndicationType type, const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
+ LOG_CALL << type;
+ indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+ return {};
+}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
+ V1_0::RadioIndicationType type, const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
+ LOG_CALL << type;
+ indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
new file mode 100644
index 0000000..523c504
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioConfigResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ConfigResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+void RadioConfigResponse::setResponseFunction(
+ std::shared_ptr<aidl::IRadioConfigResponse> callback) {
+ mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfigResponse::respond() {
+ return mCallback.get();
+}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
+ LOG_CALL << info.serial;
+ respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+ return {};
+};
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
+ LOG_CALL << info.serial;
+ respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+ return {};
+};
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ respond()->setSimSlotsMappingResponse(toAidl(info));
+ return {};
+};
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+ const V1_0::RadioResponseInfo& info, const config::V1_1::PhoneCapability& phoneCapability) {
+ LOG_CALL << info.serial;
+ respond()->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
+ return {};
+};
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ respond()->setPreferredDataModemResponse(toAidl(info));
+ return {};
+};
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ respond()->setNumOfLiveModemsResponse(toAidl(info));
+ return {};
+};
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(
+ const V1_0::RadioResponseInfo& info, const config::V1_1::ModemsConfig& modemsConfig) {
+ LOG_CALL << info.serial;
+ respond()->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
+ return {};
+};
+
+Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+ const V1_6::RadioResponseInfo& info, bool modemReducedFeatureSet1) {
+ LOG_CALL << info.serial;
+ respond()->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
+ return {};
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/structs.cpp b/radio/aidl/compat/libradiocompat/config/structs.cpp
new file mode 100644
index 0000000..39ad944
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/structs.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+uint32_t toHidl(const aidl::SlotPortMapping& slotPortMapping) {
+ if (slotPortMapping.portId != 0) {
+ LOG(ERROR) << "Port ID " << slotPortMapping.portId << " != 0 not supported by HIDL HAL";
+ }
+ return slotPortMapping.physicalSlotId;
+}
+
+aidl::SimSlotStatus toAidl(const config::V1_0::SimSlotStatus& sst) {
+ return toAidl({sst, ""});
+}
+
+aidl::SimSlotStatus toAidl(const config::V1_2::SimSlotStatus& sst) {
+ const aidl::SimPortInfo portInfo = {
+ .iccId = sst.base.iccid,
+ .logicalSlotId = static_cast<int32_t>(sst.base.logicalSlotId),
+ .portActive = sst.base.slotState == config::V1_0::SlotState::ACTIVE,
+ };
+
+ return {
+ .cardState = static_cast<int32_t>(sst.base.cardState),
+ .atr = sst.base.atr,
+ .eid = sst.eid,
+ .portInfo = {portInfo},
+ };
+}
+
+uint8_t toAidl(const config::V1_1::ModemInfo& info) {
+ return info.modemId;
+}
+
+aidl::PhoneCapability toAidl(const config::V1_1::PhoneCapability& phoneCapability) {
+ return {
+ .maxActiveData = static_cast<int8_t>(phoneCapability.maxActiveData),
+ .maxActiveInternetData = static_cast<int8_t>(phoneCapability.maxActiveInternetData),
+ .isInternetLingeringSupported = phoneCapability.isInternetLingeringSupported,
+ .logicalModemIds = toAidl(phoneCapability.logicalModemList),
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/structs.h b/radio/aidl/compat/libradiocompat/config/structs.h
new file mode 100644
index 0000000..6ea4e4a
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/structs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/config/PhoneCapability.h>
+#include <aidl/android/hardware/radio/config/SimSlotStatus.h>
+#include <aidl/android/hardware/radio/config/SlotPortMapping.h>
+#include <android/hardware/radio/config/1.1/types.h>
+#include <android/hardware/radio/config/1.2/types.h>
+
+namespace android::hardware::radio::compat {
+
+uint32_t toHidl(const aidl::android::hardware::radio::config::SlotPortMapping& slotPortMapping);
+
+aidl::android::hardware::radio::config::SimSlotStatus //
+toAidl(const config::V1_0::SimSlotStatus& sst);
+aidl::android::hardware::radio::config::SimSlotStatus //
+toAidl(const config::V1_2::SimSlotStatus& sst);
+
+uint8_t toAidl(const config::V1_1::ModemInfo& info);
+
+aidl::android::hardware::radio::config::PhoneCapability //
+toAidl(const config::V1_1::PhoneCapability& pc);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioData.cpp b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
new file mode 100644
index 0000000..51f5543
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioData.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Data"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::data;
+namespace aidlCommon = ::aidl::android::hardware::radio;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioDataResponse> RadioData::respond() {
+ return mCallbackManager->response().dataCb();
+}
+
+ScopedAStatus RadioData::allocatePduSessionId(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->allocatePduSessionId(serial);
+ } else {
+ respond()->allocatePduSessionIdResponse(notSupported(serial), 0);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::cancelHandover(int32_t serial, int32_t callId) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->cancelHandover(serial, callId);
+ } else {
+ respond()->cancelHandoverResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::deactivateDataCall(int32_t serial, int32_t cid,
+ aidl::DataRequestReason reason) {
+ LOG_CALL << serial;
+ mHal1_5->deactivateDataCall_1_2(serial, cid, V1_2::DataRequestReason(reason));
+ return ok();
+}
+
+ScopedAStatus RadioData::getDataCallList(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getDataCallList_1_6(serial);
+ } else {
+ mHal1_5->getDataCallList(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::getSlicingConfig(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getSlicingConfig(serial);
+ } else {
+ respond()->getSlicingConfigResponse(notSupported(serial), {});
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::releasePduSessionId(int32_t serial, int32_t id) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->releasePduSessionId(serial, id);
+ } else {
+ respond()->releasePduSessionIdResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioData::setDataAllowed(int32_t serial, bool allow) {
+ LOG_CALL << serial;
+ mHal1_5->setDataAllowed(serial, allow);
+ return ok();
+}
+
+ScopedAStatus RadioData::setDataProfile(int32_t serial,
+ const std::vector<aidl::DataProfileInfo>& profiles) {
+ LOG_CALL << serial;
+ mHal1_5->setDataProfile_1_5(serial, toHidl(profiles));
+ return ok();
+}
+
+ScopedAStatus RadioData::setDataThrottling(int32_t serial, aidl::DataThrottlingAction dta,
+ int64_t completionDurationMs) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->setDataThrottling(serial, V1_6::DataThrottlingAction(dta), completionDurationMs);
+ } else {
+ respond()->setDataThrottlingResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::setInitialAttachApn(int32_t serial,
+ const std::optional<aidl::DataProfileInfo>& info) {
+ LOG_CALL << serial;
+ mHal1_5->setInitialAttachApn_1_5(serial, toHidl(info.value()));
+ return ok();
+}
+
+ScopedAStatus RadioData::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioDataResponse>& response,
+ const std::shared_ptr<aidl::IRadioDataIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+ScopedAStatus RadioData::setupDataCall(int32_t serial, aidlCommon::AccessNetwork accessNetwork,
+ const aidl::DataProfileInfo& dataProfileInfo,
+ bool roamingAllowed, aidl::DataRequestReason reason,
+ const std::vector<aidl::LinkAddress>& addresses,
+ const std::vector<std::string>& dnses, int32_t pduSessId,
+ const std::optional<aidl::SliceInfo>& sliceInfo,
+ bool matchAllRuleAllowed) {
+ if (mHal1_6) {
+ mHal1_6->setupDataCall_1_6(
+ serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
+ V1_2::DataRequestReason(reason), toHidl(addresses), toHidl(dnses), pduSessId,
+ toHidl<V1_6::OptionalSliceInfo>(sliceInfo),
+ toHidl<V1_6::OptionalTrafficDescriptor>(dataProfileInfo.trafficDescriptor),
+ matchAllRuleAllowed);
+ mContext->addDataProfile(dataProfileInfo);
+ } else {
+ mHal1_5->setupDataCall_1_5(
+ serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
+ V1_2::DataRequestReason(reason), toHidl(addresses), toHidl(dnses));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::startHandover(int32_t serial, int32_t callId) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->startHandover(serial, callId);
+ } else {
+ respond()->startHandoverResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioData::startKeepalive(int32_t serial, const aidl::KeepaliveRequest& keepalive) {
+ LOG_CALL << serial;
+ mHal1_5->startKeepalive(serial, toHidl(keepalive));
+ return ok();
+}
+
+ScopedAStatus RadioData::stopKeepalive(int32_t serial, int32_t sessionHandle) {
+ LOG_CALL << serial;
+ mHal1_5->stopKeepalive(serial, sessionHandle);
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
new file mode 100644
index 0000000..602bb39
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "DataIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioDataIndication> dataCb) {
+ mDataCb = dataCb;
+}
+
+std::shared_ptr<aidl::IRadioDataIndication> RadioIndication::dataCb() {
+ return mDataCb.get();
+}
+
+Return<void> RadioIndication::dataCallListChanged(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::SetupDataCallResult>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_4(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::SetupDataCallResult>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_5(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_5::SetupDataCallResult>& dcList) {
+ LOG_CALL << type;
+ dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
+ return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_6(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_6::SetupDataCallResult>& dcList) {
+ LOG_CALL << type;
+ dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
+ return {};
+}
+
+Return<void> RadioIndication::keepaliveStatus(V1_0::RadioIndicationType type,
+ const V1_1::KeepaliveStatus& status) {
+ LOG_CALL << type;
+ dataCb()->keepaliveStatus(toAidl(type), toAidl(status));
+ return {};
+}
+
+Return<void> RadioIndication::pcoData(V1_0::RadioIndicationType type,
+ const V1_0::PcoDataInfo& pco) {
+ LOG_CALL << type;
+ dataCb()->pcoData(toAidl(type), toAidl(pco));
+ return {};
+}
+
+Return<void> RadioIndication::unthrottleApn(V1_0::RadioIndicationType type,
+ const hidl_string& apn) {
+ LOG_CALL << type;
+ dataCb()->unthrottleApn(toAidl(type), mContext->getDataProfile(apn));
+ return {};
+}
+
+Return<void> RadioIndication::slicingConfigChanged(V1_0::RadioIndicationType type,
+ const V1_6::SlicingConfig& slicingConfig) {
+ LOG_CALL << type;
+ dataCb()->slicingConfigChanged(toAidl(type), toAidl(slicingConfig));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
new file mode 100644
index 0000000..0bfa2df
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "DataResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioDataResponse> dataCb) {
+ mDataCb = dataCb;
+}
+
+std::shared_ptr<aidl::IRadioDataResponse> RadioResponse::dataCb() {
+ return mDataCb.get();
+}
+
+Return<void> RadioResponse::allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
+ int32_t id) {
+ LOG_CALL << info.serial;
+ dataCb()->allocatePduSessionIdResponse(toAidl(info), id);
+ return {};
+}
+
+Return<void> RadioResponse::cancelHandoverResponse(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->cancelHandoverResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->deactivateDataCallResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::SetupDataCallResult>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_4(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_4::SetupDataCallResult>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_5(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) {
+ LOG_CALL << info.serial;
+ dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+ return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_6(
+ const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) {
+ LOG_CALL << info.serial;
+ dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+ return {};
+}
+
+Return<void> RadioResponse::getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
+ const V1_6::SlicingConfig& slicingConfig) {
+ LOG_CALL << info.serial;
+ dataCb()->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
+ return {};
+}
+
+Return<void> RadioResponse::releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->releasePduSessionIdResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setDataAllowedResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setDataAllowedResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setDataProfileResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setDataProfileResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setDataProfileResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setDataThrottlingResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setInitialAttachApnResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->setInitialAttachApnResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SetupDataCallResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const V1_4::SetupDataCallResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const V1_5::SetupDataCallResult& dcResponse) {
+ LOG_CALL << info.serial;
+ dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+ return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_6::SetupDataCallResult& dcResponse) {
+ LOG_CALL << info.serial;
+ dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+ return {};
+}
+
+Return<void> RadioResponse::startHandoverResponse(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->startHandoverResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
+ const V1_1::KeepaliveStatus& status) {
+ LOG_CALL << info.serial;
+ dataCb()->startKeepaliveResponse(toAidl(info), toAidl(status));
+ return {};
+}
+
+Return<void> RadioResponse::stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ dataCb()->stopKeepaliveResponse(toAidl(info));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/structs.cpp b/radio/aidl/compat/libradiocompat/data/structs.cpp
new file mode 100644
index 0000000..4ff89a1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/structs.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+V1_5::DataProfileInfo toHidl(const aidl::DataProfileInfo& info) {
+ return {
+ .profileId = V1_0::DataProfileId{info.profileId},
+ .apn = info.apn,
+ .protocol = V1_4::PdpProtocolType{info.protocol},
+ .roamingProtocol = V1_4::PdpProtocolType{info.roamingProtocol},
+ .authType = V1_0::ApnAuthType{info.authType},
+ .user = info.user,
+ .password = info.password,
+ .type = V1_0::DataProfileInfoType{info.type},
+ .maxConnsTime = info.maxConnsTime,
+ .maxConns = info.maxConns,
+ .waitTime = info.waitTime,
+ .enabled = info.enabled,
+ .supportedApnTypesBitmap = toHidlBitfield<V1_5::ApnTypes>(info.supportedApnTypesBitmap),
+ .bearerBitmap = toHidlBitfield<V1_4::RadioAccessFamily>(info.bearerBitmap),
+ .mtuV4 = info.mtuV4,
+ .mtuV6 = info.mtuV6,
+ .preferred = info.preferred,
+ .persistent = info.persistent,
+ };
+}
+
+V1_5::LinkAddress toHidl(const aidl::LinkAddress& addr) {
+ return {
+ .address = addr.address,
+ .properties = addr.addressProperties,
+ .deprecationTime = static_cast<uint64_t>(addr.deprecationTime),
+ .expirationTime = static_cast<uint64_t>(addr.expirationTime),
+ };
+}
+
+aidl::SliceInfo toAidl(const V1_6::SliceInfo& info) {
+ return {
+ .sliceServiceType = static_cast<int8_t>(info.sst),
+ .sliceDifferentiator = info.sliceDifferentiator,
+ .mappedHplmnSst = static_cast<int8_t>(info.mappedHplmnSst),
+ .mappedHplmnSd = info.mappedHplmnSD,
+ .status = static_cast<int8_t>(info.status),
+ };
+}
+
+V1_6::SliceInfo toHidl(const aidl::SliceInfo& info) {
+ return {
+ .sst = static_cast<V1_6::SliceServiceType>(info.sliceServiceType),
+ .sliceDifferentiator = info.sliceDifferentiator,
+ .mappedHplmnSst = static_cast<V1_6::SliceServiceType>(info.mappedHplmnSst),
+ .mappedHplmnSD = info.mappedHplmnSd,
+ .status = V1_6::SliceStatus{info.status},
+ };
+}
+
+aidl::TrafficDescriptor toAidl(const V1_6::TrafficDescriptor& descr) {
+ return {
+ .dnn = toAidl(descr.dnn),
+ .osAppId = toAidl(descr.osAppId),
+ };
+}
+
+V1_6::TrafficDescriptor toHidl(const aidl::TrafficDescriptor& descr) {
+ return {
+ .dnn = toHidl<V1_6::OptionalDnn>(descr.dnn),
+ .osAppId = toHidl<V1_6::OptionalOsAppId>(descr.osAppId),
+ };
+}
+
+aidl::OsAppId toAidl(const V1_6::OsAppId& appId) {
+ return {
+ .osAppId = appId.osAppId,
+ };
+}
+
+V1_6::OsAppId toHidl(const aidl::OsAppId& appId) {
+ return {
+ .osAppId = appId.osAppId,
+ };
+}
+
+V1_1::KeepaliveRequest toHidl(const aidl::KeepaliveRequest& keep) {
+ return {
+ .type = V1_1::KeepaliveType{keep.type},
+ .sourceAddress = keep.sourceAddress,
+ .sourcePort = keep.sourcePort,
+ .destinationAddress = keep.destinationAddress,
+ .destinationPort = keep.destinationPort,
+ .maxKeepaliveIntervalMillis = keep.maxKeepaliveIntervalMillis,
+ .cid = keep.cid,
+ };
+}
+
+static aidl::QosBandwidth toAidl(const V1_6::QosBandwidth& bw) {
+ return {
+ .maxBitrateKbps = static_cast<int32_t>(bw.maxBitrateKbps),
+ .guaranteedBitrateKbps = static_cast<int32_t>(bw.guaranteedBitrateKbps),
+ };
+}
+
+static aidl::EpsQos toAidl(const V1_6::EpsQos& qos) {
+ return {
+ .qci = qos.qci,
+ .downlink = toAidl(qos.downlink),
+ .uplink = toAidl(qos.uplink),
+ };
+}
+
+static aidl::NrQos toAidl(const V1_6::NrQos& qos) {
+ return {
+ .fiveQi = qos.fiveQi,
+ .downlink = toAidl(qos.downlink),
+ .uplink = toAidl(qos.uplink),
+ .qfi = static_cast<int8_t>(qos.qfi),
+ .averagingWindowMs = qos.averagingWindowMs,
+ };
+}
+
+static std::variant<bool, aidl::EpsQos, aidl::NrQos> toAidl(const V1_6::Qos& qos) {
+ if (qos.getDiscriminator() == V1_6::Qos::hidl_discriminator::eps) return toAidl(qos.eps());
+ if (qos.getDiscriminator() == V1_6::Qos::hidl_discriminator::nr) return toAidl(qos.nr());
+ return false;
+}
+
+aidl::SetupDataCallResult toAidl(const V1_5::SetupDataCallResult& res) {
+ return {
+ .cause = aidl::DataCallFailCause(res.cause),
+ .suggestedRetryTime = res.suggestedRetryTime,
+ .cid = res.cid,
+ .active = static_cast<int32_t>(res.active),
+ .type = aidl::PdpProtocolType(res.type),
+ .ifname = res.ifname,
+ .addresses = toAidl(res.addresses),
+ .dnses = toAidl(res.dnses),
+ .gateways = toAidl(res.gateways),
+ .pcscf = toAidl(res.pcscf),
+ .mtuV4 = res.mtuV4,
+ .mtuV6 = res.mtuV6,
+ };
+}
+
+aidl::SetupDataCallResult toAidl(const V1_6::SetupDataCallResult& res) {
+ return {
+ .cause = aidl::DataCallFailCause(res.cause),
+ .suggestedRetryTime = res.suggestedRetryTime,
+ .cid = res.cid,
+ .active = static_cast<int32_t>(res.active),
+ .type = aidl::PdpProtocolType(res.type),
+ .ifname = res.ifname,
+ .addresses = toAidl(res.addresses),
+ .dnses = toAidl(res.dnses),
+ .gateways = toAidl(res.gateways),
+ .pcscf = toAidl(res.pcscf),
+ .mtuV4 = res.mtuV4,
+ .mtuV6 = res.mtuV6,
+ .defaultQos = toAidl(res.defaultQos),
+ .qosSessions = toAidl(res.qosSessions),
+ .handoverFailureMode = static_cast<int8_t>(res.handoverFailureMode),
+ .pduSessionId = res.pduSessionId,
+ .sliceInfo = toAidl(res.sliceInfo),
+ .trafficDescriptors = toAidl(res.trafficDescriptors),
+ };
+}
+
+aidl::LinkAddress toAidl(const V1_5::LinkAddress& addr) {
+ return {
+ .address = addr.address,
+ .addressProperties = addr.properties,
+ .deprecationTime = static_cast<int64_t>(addr.deprecationTime),
+ .expirationTime = static_cast<int64_t>(addr.expirationTime),
+ };
+}
+
+aidl::QosSession toAidl(const V1_6::QosSession& sess) {
+ return {
+ .qosSessionId = sess.qosSessionId,
+ .qos = toAidl(sess.qos),
+ .qosFilters = toAidl(sess.qosFilters),
+ };
+}
+
+static aidl::PortRange toAidl(const V1_6::PortRange& range) {
+ return {
+ .start = range.start,
+ .end = range.end,
+ };
+}
+
+static std::optional<aidl::PortRange> toAidl(const V1_6::MaybePort& opt) {
+ if (opt.getDiscriminator() == V1_6::MaybePort::hidl_discriminator::noinit) return std::nullopt;
+ return toAidl(opt.range()); // can't use MaybeX template - this field is not named "value"
+}
+
+aidl::QosFilter toAidl(const V1_6::QosFilter& filter) {
+ return {
+ .localAddresses = toAidl(filter.localAddresses),
+ .remoteAddresses = toAidl(filter.remoteAddresses),
+ .localPort = toAidl(filter.localPort),
+ .remotePort = toAidl(filter.remotePort),
+ .protocol = static_cast<int8_t>(filter.protocol),
+ .tos = toAidlVariant(filter.tos),
+ .flowLabel = toAidlVariant(filter.flowLabel),
+ .spi = toAidlVariant(filter.spi),
+ .direction = static_cast<int8_t>(filter.direction),
+ .precedence = filter.precedence,
+ };
+}
+
+aidl::KeepaliveStatus toAidl(const V1_1::KeepaliveStatus& status) {
+ return {
+ .sessionHandle = status.sessionHandle,
+ .code = static_cast<int32_t>(status.code),
+ };
+}
+
+aidl::PcoDataInfo toAidl(const V1_0::PcoDataInfo& info) {
+ return {
+ .cid = info.cid,
+ .bearerProto = info.bearerProto,
+ .pcoId = info.pcoId,
+ .contents = info.contents,
+ };
+}
+
+aidl::SlicingConfig toAidl(const V1_6::SlicingConfig& cfg) {
+ return {
+ .urspRules = toAidl(cfg.urspRules),
+ .sliceInfo = toAidl(cfg.sliceInfo),
+ };
+}
+
+aidl::UrspRule toAidl(const V1_6::UrspRule& rule) {
+ return {
+ .precedence = rule.precedence,
+ .trafficDescriptors = toAidl(rule.trafficDescriptors),
+ .routeSelectionDescriptor = toAidl(rule.routeSelectionDescriptor),
+ };
+}
+
+static int8_t toAidl(const V1_6::OptionalSscMode& opt) {
+ if (opt.getDiscriminator() == V1_6::OptionalSscMode::hidl_discriminator::noinit) {
+ return aidl::RouteSelectionDescriptor::SSC_MODE_UNKNOWN;
+ }
+ return static_cast<int8_t>(opt.value());
+}
+
+static aidl::PdpProtocolType toAidl(const V1_6::OptionalPdpProtocolType& opt) {
+ using discriminator = V1_6::OptionalPdpProtocolType::hidl_discriminator;
+ if (opt.getDiscriminator() == discriminator::noinit) return aidl::PdpProtocolType::UNKNOWN;
+ return aidl::PdpProtocolType(opt.value());
+}
+
+aidl::RouteSelectionDescriptor toAidl(const V1_6::RouteSelectionDescriptor& descr) {
+ return {
+ .precedence = static_cast<int8_t>(descr.precedence),
+ .sessionType = toAidl(descr.sessionType),
+ .sscMode = toAidl(descr.sscMode),
+ .sliceInfo = toAidl(descr.sliceInfo),
+ .dnn = toAidl(descr.dnn),
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/structs.h b/radio/aidl/compat/libradiocompat/data/structs.h
new file mode 100644
index 0000000..60fad57
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/structs.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/data/DataProfileInfo.h>
+#include <aidl/android/hardware/radio/data/KeepaliveRequest.h>
+#include <aidl/android/hardware/radio/data/KeepaliveStatus.h>
+#include <aidl/android/hardware/radio/data/LinkAddress.h>
+#include <aidl/android/hardware/radio/data/OsAppId.h>
+#include <aidl/android/hardware/radio/data/PcoDataInfo.h>
+#include <aidl/android/hardware/radio/data/RouteSelectionDescriptor.h>
+#include <aidl/android/hardware/radio/data/SetupDataCallResult.h>
+#include <aidl/android/hardware/radio/data/SliceInfo.h>
+#include <aidl/android/hardware/radio/data/SlicingConfig.h>
+#include <aidl/android/hardware/radio/data/TrafficDescriptor.h>
+#include <aidl/android/hardware/radio/data/UrspRule.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_5::DataProfileInfo toHidl(const ::aidl::android::hardware::radio::data::DataProfileInfo& info);
+
+V1_5::LinkAddress toHidl(const ::aidl::android::hardware::radio::data::LinkAddress& addr);
+
+::aidl::android::hardware::radio::data::SliceInfo toAidl(const V1_6::SliceInfo& info);
+V1_6::SliceInfo toHidl(const ::aidl::android::hardware::radio::data::SliceInfo& info);
+
+::aidl::android::hardware::radio::data::TrafficDescriptor toAidl(const V1_6::TrafficDescriptor& td);
+V1_6::TrafficDescriptor toHidl(const ::aidl::android::hardware::radio::data::TrafficDescriptor& td);
+
+V1_1::KeepaliveRequest toHidl(const ::aidl::android::hardware::radio::data::KeepaliveRequest& keep);
+
+::aidl::android::hardware::radio::data::OsAppId toAidl(const V1_6::OsAppId& appId);
+V1_6::OsAppId toHidl(const ::aidl::android::hardware::radio::data::OsAppId& appId);
+
+::aidl::android::hardware::radio::data::SetupDataCallResult //
+toAidl(const V1_5::SetupDataCallResult& res);
+::aidl::android::hardware::radio::data::SetupDataCallResult //
+toAidl(const V1_6::SetupDataCallResult& res);
+
+::aidl::android::hardware::radio::data::LinkAddress toAidl(const V1_5::LinkAddress& addr);
+
+::aidl::android::hardware::radio::data::QosSession toAidl(const V1_6::QosSession& session);
+
+::aidl::android::hardware::radio::data::QosFilter toAidl(const V1_6::QosFilter& filter);
+
+::aidl::android::hardware::radio::data::KeepaliveStatus toAidl(const V1_1::KeepaliveStatus& status);
+
+::aidl::android::hardware::radio::data::PcoDataInfo toAidl(const V1_0::PcoDataInfo& info);
+
+::aidl::android::hardware::radio::data::SlicingConfig toAidl(const V1_6::SlicingConfig& cfg);
+
+::aidl::android::hardware::radio::data::UrspRule toAidl(const V1_6::UrspRule& rule);
+
+::aidl::android::hardware::radio::data::RouteSelectionDescriptor //
+toAidl(const V1_6::RouteSelectionDescriptor& descr);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/debug.h b/radio/aidl/compat/libradiocompat/debug.h
new file mode 100644
index 0000000..cb773bf
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/debug.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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>
+
+namespace android::hardware::radio::compat {
+
+namespace debug {
+
+static constexpr bool kSuperVerbose = true;
+
+#define LOG_CALL \
+ if constexpr (debug::kSuperVerbose) LOG(VERBOSE) << (RADIO_MODULE ".") << __func__ << ' '
+
+} // namespace debug
+
+inline std::ostream& operator<<(std::ostream& os, const V1_0::RadioIndicationType& type) {
+ return os << static_cast<int>(type);
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
new file mode 100644
index 0000000..f1a7b49
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DriverContext.h"
+#include "RadioIndication.h"
+#include "RadioResponse.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/radio/1.6/IRadio.h>
+
+#include <thread>
+
+namespace android::hardware::radio::compat {
+
+class CallbackManager {
+ sp<V1_5::IRadio> mHidlHal;
+ sp<RadioResponse> mRadioResponse;
+ sp<RadioIndication> mRadioIndication;
+
+ std::thread mDelayedSetterThread;
+ std::mutex mDelayedSetterGuard;
+ std::optional<std::chrono::time_point<std::chrono::steady_clock>> mDelayedSetterDeadline
+ GUARDED_BY(mDelayedSetterGuard);
+ std::condition_variable mDelayedSetterCv GUARDED_BY(mDelayedSetterGuard);
+ bool mDestroy GUARDED_BY(mDelayedSetterGuard) = false;
+
+ void setResponseFunctionsDelayed();
+ void delayedSetterThread();
+
+ public:
+ CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal);
+ ~CallbackManager();
+
+ RadioResponse& response() const;
+
+ template <typename ResponseType, typename IndicationType>
+ void setResponseFunctions(const std::shared_ptr<ResponseType>& response,
+ const std::shared_ptr<IndicationType>& indication) {
+ CHECK(response);
+ CHECK(indication);
+
+ mRadioResponse->setResponseFunction(response);
+ mRadioIndication->setResponseFunction(indication);
+ setResponseFunctionsDelayed();
+ }
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
new file mode 100644
index 0000000..6833aca
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/data/DataProfileInfo.h>
+
+#include <map>
+
+namespace android::hardware::radio::compat {
+
+class DriverContext {
+ std::map<std::string, ::aidl::android::hardware::radio::data::DataProfileInfo> mDataProfiles;
+
+ public:
+ void addDataProfile(const ::aidl::android::hardware::radio::data::DataProfileInfo& profile);
+ ::aidl::android::hardware::radio::data::DataProfileInfo getDataProfile(const std::string& apn);
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
new file mode 100644
index 0000000..0b6ee11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <android/binder_interface_utils.h>
+#include <utils/Mutex.h>
+
+namespace android::hardware::radio::compat {
+
+template <typename Interface, typename DefaultImplementation, bool isIndication = false>
+class GuaranteedCallback {
+ mutable std::mutex mCallbackGuard;
+ std::shared_ptr<Interface> mCallback GUARDED_BY(mCallbackGuard);
+
+ public:
+ GuaranteedCallback<Interface, DefaultImplementation, isIndication>& operator=(
+ const std::shared_ptr<Interface>& callback) {
+ CHECK(callback);
+ const std::lock_guard<std::mutex> lock(mCallbackGuard);
+ mCallback = callback;
+ return *this;
+ }
+
+ std::shared_ptr<Interface> get() {
+ if (mCallback) return mCallback;
+ const std::lock_guard<std::mutex> lock(mCallbackGuard);
+ if (mCallback) return mCallback;
+
+ LOG(isIndication ? WARNING : ERROR) << "Callback is not set";
+ return mCallback = ndk::SharedRefBase::make<DefaultImplementation>();
+ }
+
+ operator bool() const { return mCallback != nullptr; }
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
new file mode 100644
index 0000000..eb22fff
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "CallbackManager.h"
+#include "DriverContext.h"
+
+#include <android/hardware/radio/1.6/IRadio.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioCompatBase {
+ protected:
+ std::shared_ptr<DriverContext> mContext;
+
+ sp<V1_5::IRadio> mHal1_5;
+ sp<V1_6::IRadio> mHal1_6;
+
+ std::shared_ptr<CallbackManager> mCallbackManager;
+
+ public:
+ RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+ std::shared_ptr<CallbackManager> cbMgr);
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
new file mode 100644
index 0000000..bbfff61
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioConfigIndication.h"
+#include "RadioConfigResponse.h"
+
+#include <aidl/android/hardware/radio/config/BnRadioConfig.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+
+namespace android::hardware::radio::compat {
+
+/**
+ * HAL translator from HIDL IRadioConfig to AIDL IRadioConfig.
+ *
+ * This class wraps existing HIDL implementation (either a binder stub or real
+ * class implementing the HAL) and implements AIDL HAL. It's up to the caller to
+ * fetch source implementation and publish resulting HAL instance.
+ */
+class RadioConfig : public aidl::android::hardware::radio::config::BnRadioConfig {
+ const sp<config::V1_1::IRadioConfig> mHal1_1;
+ const sp<config::V1_3::IRadioConfig> mHal1_3;
+
+ const sp<RadioConfigResponse> mRadioConfigResponse;
+ const sp<RadioConfigIndication> mRadioConfigIndication;
+
+ std::shared_ptr<::aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
+
+ ::ndk::ScopedAStatus getHalDeviceCapabilities(int32_t serial) override;
+ ::ndk::ScopedAStatus getNumOfLiveModems(int32_t serial) override;
+ ::ndk::ScopedAStatus getPhoneCapability(int32_t serial) override;
+ ::ndk::ScopedAStatus getSimSlotsStatus(int32_t serial) override;
+ ::ndk::ScopedAStatus setNumOfLiveModems(int32_t serial, int8_t numOfLiveModems) override;
+ ::ndk::ScopedAStatus setPreferredDataModem(int32_t serial, int8_t modemId) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse>&
+ radioConfigResponse,
+ const std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication>&
+ radioConfigIndication) override;
+ ::ndk::ScopedAStatus setSimSlotsMapping(
+ int32_t serial,
+ const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap)
+ override;
+
+ public:
+ /**
+ * Constructs AIDL IRadioConfig instance wrapping existing HIDL IRadioConfig instance.
+ *
+ * \param hidlHal existing HIDL IRadioConfig HAL instance
+ */
+ RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal);
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
new file mode 100644
index 0000000..d256a87
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigIndication : public config::V1_2::IRadioConfigIndication {
+ GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigIndication,
+ aidl::android::hardware::radio::config::IRadioConfigIndicationDefault, true>
+ mCallback;
+
+ Return<void> simSlotsStatusChanged(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+ Return<void> simSlotsStatusChanged_1_2(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+
+ public:
+ void setResponseFunction(
+ std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> cb);
+
+ std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> indicate();
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
new file mode 100644
index 0000000..dc86da2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigResponse : public config::V1_3::IRadioConfigResponse {
+ GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigResponse,
+ aidl::android::hardware::radio::config::IRadioConfigResponseDefault>
+ mCallback;
+
+ Return<void> getSimSlotsStatusResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+ Return<void> setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getPhoneCapabilityResponse(
+ const V1_0::RadioResponseInfo& info,
+ const config::V1_1::PhoneCapability& phoneCapability) override;
+ Return<void> setPreferredDataModemResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setModemsConfigResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getModemsConfigResponse(const V1_0::RadioResponseInfo& info,
+ const config::V1_1::ModemsConfig& modemsConfig) override;
+ Return<void> getSimSlotsStatusResponse_1_2(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+ Return<void> getHalDeviceCapabilitiesResponse(const V1_6::RadioResponseInfo& info,
+ bool modemReducedFeatureSet1) override;
+
+ public:
+ void setResponseFunction(
+ std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> callback);
+
+ std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
new file mode 100644
index 0000000..c2c0de3
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/data/BnRadioData.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioData : public RadioCompatBase, public aidl::android::hardware::radio::data::BnRadioData {
+ std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> respond();
+
+ ::ndk::ScopedAStatus allocatePduSessionId(int32_t serial) override;
+ ::ndk::ScopedAStatus cancelHandover(int32_t serial, int32_t callId) override;
+ ::ndk::ScopedAStatus deactivateDataCall(
+ int32_t serial, int32_t cid,
+ ::aidl::android::hardware::radio::data::DataRequestReason reason) override;
+ ::ndk::ScopedAStatus getDataCallList(int32_t serial) override;
+ ::ndk::ScopedAStatus getSlicingConfig(int32_t serial) override;
+ ::ndk::ScopedAStatus releasePduSessionId(int32_t serial, int32_t id) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus setDataAllowed(int32_t serial, bool allow) override;
+ ::ndk::ScopedAStatus setDataProfile(
+ int32_t serial,
+ const std::vector<::aidl::android::hardware::radio::data::DataProfileInfo>& profiles)
+ override;
+ ::ndk::ScopedAStatus setDataThrottling(
+ int32_t serial,
+ ::aidl::android::hardware::radio::data::DataThrottlingAction dataThrottlingAction,
+ int64_t completionDurationMillis) override;
+ ::ndk::ScopedAStatus setInitialAttachApn(
+ int32_t serial,
+ const std::optional<::aidl::android::hardware::radio::data::DataProfileInfo>& dpInfo)
+ override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse>&
+ radioDataResponse,
+ const std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication>&
+ radioDataIndication) override;
+ ::ndk::ScopedAStatus setupDataCall(
+ int32_t serial, ::aidl::android::hardware::radio::AccessNetwork accessNetwork,
+ const ::aidl::android::hardware::radio::data::DataProfileInfo& dataProfileInfo,
+ bool roamingAllowed, ::aidl::android::hardware::radio::data::DataRequestReason reason,
+ const std::vector<::aidl::android::hardware::radio::data::LinkAddress>& addresses,
+ const std::vector<std::string>& dnses, int32_t pduSessionId,
+ const std::optional<::aidl::android::hardware::radio::data::SliceInfo>& sliceInfo,
+ bool matchAllRuleAllowed) override;
+ ::ndk::ScopedAStatus startHandover(int32_t serial, int32_t callId) override;
+ ::ndk::ScopedAStatus startKeepalive(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::data::KeepaliveRequest& keepalive) override;
+ ::ndk::ScopedAStatus stopKeepalive(int32_t serial, int32_t sessionHandle) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
new file mode 100644
index 0000000..6cfd59c
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DriverContext.h"
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemIndication.h>
+#include <aidl/android/hardware/radio/network/IRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/sim/IRadioSimIndication.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoiceIndication.h>
+#include <android/hardware/radio/1.6/IRadioIndication.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioIndication : public V1_6::IRadioIndication {
+ std::shared_ptr<DriverContext> mContext;
+
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::data::IRadioDataIndication,
+ ::aidl::android::hardware::radio::data::IRadioDataIndicationDefault, true>
+ mDataCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication,
+ ::aidl::android::hardware::radio::messaging::IRadioMessagingIndicationDefault, true>
+ mMessagingCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::modem::IRadioModemIndication,
+ ::aidl::android::hardware::radio::modem::IRadioModemIndicationDefault, true>
+ mModemCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::network::IRadioNetworkIndication,
+ ::aidl::android::hardware::radio::network::IRadioNetworkIndicationDefault, true>
+ mNetworkCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::sim::IRadioSimIndication,
+ ::aidl::android::hardware::radio::sim::IRadioSimIndicationDefault, true>
+ mSimCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::voice::IRadioVoiceIndication,
+ ::aidl::android::hardware::radio::voice::IRadioVoiceIndicationDefault, true>
+ mVoiceCb;
+
+ // IRadioIndication @ 1.0
+ Return<void> radioStateChanged(V1_0::RadioIndicationType type,
+ V1_0::RadioState radioState) override;
+ Return<void> callStateChanged(V1_0::RadioIndicationType type) override;
+ Return<void> networkStateChanged(V1_0::RadioIndicationType type) override;
+ Return<void> newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) override;
+ Return<void> newSmsStatusReport(V1_0::RadioIndicationType type,
+ const hidl_vec<uint8_t>& pdu) override;
+ Return<void> newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) override;
+ Return<void> onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
+ const hidl_string& msg) override;
+ Return<void> nitzTimeReceived(V1_0::RadioIndicationType type, const hidl_string& nitzTime,
+ uint64_t receivedTime) override;
+ Return<void> currentSignalStrength(V1_0::RadioIndicationType type,
+ const V1_0::SignalStrength& signalStrength) override;
+ Return<void> dataCallListChanged(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::SetupDataCallResult>& dcList) override;
+ Return<void> suppSvcNotify(V1_0::RadioIndicationType type,
+ const V1_0::SuppSvcNotification& suppSvc) override;
+ Return<void> stkSessionEnd(V1_0::RadioIndicationType type) override;
+ Return<void> stkProactiveCommand(V1_0::RadioIndicationType type,
+ const hidl_string& cmd) override;
+ Return<void> stkEventNotify(V1_0::RadioIndicationType type, const hidl_string& cmd) override;
+ Return<void> stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) override;
+ Return<void> simSmsStorageFull(V1_0::RadioIndicationType type) override;
+ Return<void> simRefresh(V1_0::RadioIndicationType type,
+ const V1_0::SimRefreshResult& refreshResult) override;
+ Return<void> callRing(V1_0::RadioIndicationType type, bool isGsm,
+ const V1_0::CdmaSignalInfoRecord& record) override;
+ Return<void> simStatusChanged(V1_0::RadioIndicationType type) override;
+ Return<void> cdmaNewSms(V1_0::RadioIndicationType type,
+ const V1_0::CdmaSmsMessage& msg) override;
+ Return<void> newBroadcastSms(V1_0::RadioIndicationType type,
+ const hidl_vec<uint8_t>& data) override;
+ Return<void> cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) override;
+ Return<void> restrictedStateChanged(V1_0::RadioIndicationType type,
+ V1_0::PhoneRestrictedState state) override;
+ Return<void> enterEmergencyCallbackMode(V1_0::RadioIndicationType type) override;
+ Return<void> cdmaCallWaiting(V1_0::RadioIndicationType type,
+ const V1_0::CdmaCallWaiting& callWaitingRecord) override;
+ Return<void> cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
+ V1_0::CdmaOtaProvisionStatus status) override;
+ Return<void> cdmaInfoRec(V1_0::RadioIndicationType type,
+ const V1_0::CdmaInformationRecords& records) override;
+ Return<void> indicateRingbackTone(V1_0::RadioIndicationType type, bool start) override;
+ Return<void> resendIncallMute(V1_0::RadioIndicationType type) override;
+ Return<void> cdmaSubscriptionSourceChanged(V1_0::RadioIndicationType type,
+ V1_0::CdmaSubscriptionSource cdmaSource) override;
+ Return<void> cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) override;
+ Return<void> exitEmergencyCallbackMode(V1_0::RadioIndicationType type) override;
+ Return<void> rilConnected(V1_0::RadioIndicationType type) override;
+ Return<void> voiceRadioTechChanged(V1_0::RadioIndicationType type,
+ V1_0::RadioTechnology rat) override;
+ Return<void> cellInfoList(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::CellInfo>& records) override;
+ Return<void> imsNetworkStateChanged(V1_0::RadioIndicationType type) override;
+ Return<void> subscriptionStatusChanged(V1_0::RadioIndicationType type, bool activate) override;
+ Return<void> srvccStateNotify(V1_0::RadioIndicationType type, V1_0::SrvccState state) override;
+ Return<void> hardwareConfigChanged(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::HardwareConfig>& configs) override;
+ Return<void> radioCapabilityIndication(V1_0::RadioIndicationType type,
+ const V1_0::RadioCapability& rc) override;
+ Return<void> onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
+ const V1_0::StkCcUnsolSsResult& ss) override;
+ Return<void> stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
+ const hidl_string& alpha) override;
+ Return<void> lceData(V1_0::RadioIndicationType type, const V1_0::LceDataInfo& lce) override;
+ Return<void> pcoData(V1_0::RadioIndicationType type, const V1_0::PcoDataInfo& pco) override;
+ Return<void> modemReset(V1_0::RadioIndicationType type, const hidl_string& reason) override;
+
+ // IRadioIndication @ 1.1
+ Return<void> carrierInfoForImsiEncryption(V1_0::RadioIndicationType info) override;
+ Return<void> networkScanResult(V1_0::RadioIndicationType type,
+ const V1_1::NetworkScanResult& result) override;
+ Return<void> keepaliveStatus(V1_0::RadioIndicationType type,
+ const V1_1::KeepaliveStatus& status) override;
+
+ // IRadioIndication @ 1.2
+ Return<void> networkScanResult_1_2(V1_0::RadioIndicationType type,
+ const V1_2::NetworkScanResult& result) override;
+ Return<void> cellInfoList_1_2(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_2::CellInfo>& records) override;
+ Return<void> currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
+ const V1_2::LinkCapacityEstimate& lce) override;
+ Return<void> currentPhysicalChannelConfigs(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_2::PhysicalChannelConfig>& configs) override;
+ Return<void> currentSignalStrength_1_2(V1_0::RadioIndicationType type,
+ const V1_2::SignalStrength& signalStrength) override;
+
+ // IRadioIndication @ 1.4
+ Return<void> currentEmergencyNumberList(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::EmergencyNumber>& emergencyNumberList) override;
+ Return<void> cellInfoList_1_4(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::CellInfo>& records) override;
+ Return<void> networkScanResult_1_4(V1_0::RadioIndicationType type,
+ const V1_4::NetworkScanResult& result) override;
+ Return<void> currentPhysicalChannelConfigs_1_4(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::PhysicalChannelConfig>& configs) override;
+ Return<void> dataCallListChanged_1_4(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::SetupDataCallResult>& dcList) override;
+ Return<void> currentSignalStrength_1_4(V1_0::RadioIndicationType type,
+ const V1_4::SignalStrength& signalStrength) override;
+
+ // IRadioIndication @ 1.5
+ Return<void> uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
+ bool enabled) override;
+ Return<void> registrationFailed( //
+ V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+ const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
+ int32_t additionalCauseCode) override;
+ Return<void> barringInfoChanged( //
+ V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+ const hidl_vec<V1_5::BarringInfo>& barringInfos) override;
+ Return<void> cellInfoList_1_5(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_5::CellInfo>& records) override;
+ Return<void> networkScanResult_1_5(V1_0::RadioIndicationType type,
+ const V1_5::NetworkScanResult& result) override;
+ Return<void> dataCallListChanged_1_5(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_5::SetupDataCallResult>& dcList) override;
+
+ // IRadioIndication @ 1.6
+ Return<void> dataCallListChanged_1_6(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_6::SetupDataCallResult>& dcList) override;
+ Return<void> unthrottleApn(V1_0::RadioIndicationType type, const hidl_string& apn) override;
+ Return<void> slicingConfigChanged(V1_0::RadioIndicationType type,
+ const V1_6::SlicingConfig& slicingConfig);
+ Return<void> currentLinkCapacityEstimate_1_6(V1_0::RadioIndicationType type,
+ const V1_6::LinkCapacityEstimate& lce) override;
+ Return<void> currentSignalStrength_1_6(V1_0::RadioIndicationType type,
+ const V1_6::SignalStrength& signalStrength) override;
+ Return<void> cellInfoList_1_6(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_6::CellInfo>& records) override;
+ Return<void> networkScanResult_1_6(V1_0::RadioIndicationType type,
+ const V1_6::NetworkScanResult& result) override;
+ Return<void> currentPhysicalChannelConfigs_1_6(
+ V1_0::RadioIndicationType type,
+ const hidl_vec<V1_6::PhysicalChannelConfig>& configs) override;
+ Return<void> simPhonebookChanged(V1_0::RadioIndicationType type) override;
+ Return<void> simPhonebookRecordsReceived(
+ V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
+ const hidl_vec<V1_6::PhonebookRecordInfo>& records) override;
+
+ public:
+ RadioIndication(std::shared_ptr<DriverContext> context);
+
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+ radioMessagingIndication);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modmCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> ni);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
+
+ std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
+ std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+ messagingCb();
+ std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modemCb();
+ std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> networkCb();
+ std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb();
+ std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voiceCb();
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
new file mode 100644
index 0000000..047f836
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/messaging/BnRadioMessaging.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioMessaging : public RadioCompatBase,
+ public aidl::android::hardware::radio::messaging::BnRadioMessaging {
+ std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse> respond();
+
+ ::ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
+ const std::string& ackPdu) override;
+ ::ndk::ScopedAStatus acknowledgeLastIncomingCdmaSms(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::CdmaSmsAck& smsAck) override;
+ ::ndk::ScopedAStatus acknowledgeLastIncomingGsmSms(
+ int32_t serial, bool success,
+ ::aidl::android::hardware::radio::messaging::SmsAcknowledgeFailCause cause) override;
+ ::ndk::ScopedAStatus deleteSmsOnRuim(int32_t serial, int32_t index) override;
+ ::ndk::ScopedAStatus deleteSmsOnSim(int32_t serial, int32_t index) override;
+ ::ndk::ScopedAStatus getCdmaBroadcastConfig(int32_t serial) override;
+ ::ndk::ScopedAStatus getGsmBroadcastConfig(int32_t serial) override;
+ ::ndk::ScopedAStatus getSmscAddress(int32_t serial) override;
+ ::ndk::ScopedAStatus reportSmsMemoryStatus(int32_t serial, bool available) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus sendCdmaSms(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& sms) override;
+ ::ndk::ScopedAStatus sendCdmaSmsExpectMore(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& sms) override;
+ ::ndk::ScopedAStatus sendImsSms(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::ImsSmsMessage& message) override;
+ ::ndk::ScopedAStatus sendSms(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& message) override;
+ ::ndk::ScopedAStatus sendSmsExpectMore(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& message) override;
+ ::ndk::ScopedAStatus setCdmaBroadcastActivation(int32_t serial, bool activate) override;
+ ::ndk::ScopedAStatus setCdmaBroadcastConfig(
+ int32_t serial,
+ const std::vector<
+ ::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo>&
+ configInfo) override;
+ ::ndk::ScopedAStatus setGsmBroadcastActivation(int32_t serial, bool activate) override;
+ ::ndk::ScopedAStatus setGsmBroadcastConfig(
+ int32_t serial,
+ const std::vector<
+ ::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo>&
+ configInfo) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<
+ ::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>&
+ radioMessagingResponse,
+ const std::shared_ptr<
+ ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>&
+ radioMessagingIndication) override;
+ ::ndk::ScopedAStatus setSmscAddress(int32_t serial, const std::string& smsc) override;
+ ::ndk::ScopedAStatus writeSmsToRuim(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::CdmaSmsWriteArgs& cdmaSms) override;
+ ::ndk::ScopedAStatus writeSmsToSim(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::messaging::SmsWriteArgs& smsWriteArgs) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
new file mode 100644
index 0000000..fdca124
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/modem/BnRadioModem.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioModem : public RadioCompatBase,
+ public aidl::android::hardware::radio::modem::BnRadioModem {
+ std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> respond();
+
+ ::ndk::ScopedAStatus enableModem(int32_t serial, bool on) override;
+ ::ndk::ScopedAStatus getBasebandVersion(int32_t serial) override;
+ ::ndk::ScopedAStatus getDeviceIdentity(int32_t serial) override;
+ ::ndk::ScopedAStatus getHardwareConfig(int32_t serial) override;
+ ::ndk::ScopedAStatus getModemActivityInfo(int32_t serial) override;
+ ::ndk::ScopedAStatus getModemStackStatus(int32_t serial) override;
+ ::ndk::ScopedAStatus getRadioCapability(int32_t serial) override;
+ ::ndk::ScopedAStatus nvReadItem(
+ int32_t serial, ::aidl::android::hardware::radio::modem::NvItem itemId) override;
+ ::ndk::ScopedAStatus nvResetConfig(
+ int32_t serial, ::aidl::android::hardware::radio::modem::ResetNvType type) override;
+ ::ndk::ScopedAStatus nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) override;
+ ::ndk::ScopedAStatus nvWriteItem(
+ int32_t serial, const ::aidl::android::hardware::radio::modem::NvWriteItem& i) override;
+ ::ndk::ScopedAStatus requestShutdown(int32_t serial) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus sendDeviceState(
+ int32_t serial, ::aidl::android::hardware::radio::modem::DeviceStateType stateType,
+ bool state) override;
+ ::ndk::ScopedAStatus setRadioCapability(
+ int32_t s, const ::aidl::android::hardware::radio::modem::RadioCapability& rc) override;
+ ::ndk::ScopedAStatus setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+ bool preferredForEmergencyCall) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse>&
+ radioModemResponse,
+ const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication>&
+ radioModemIndication) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
new file mode 100644
index 0000000..1731b78
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/network/BnRadioNetwork.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioNetwork : public RadioCompatBase,
+ public aidl::android::hardware::radio::network::BnRadioNetwork {
+ std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
+
+ ::ndk::ScopedAStatus getAllowedNetworkTypesBitmap(int32_t serial) override;
+ ::ndk::ScopedAStatus getAvailableBandModes(int32_t serial) override;
+ ::ndk::ScopedAStatus getAvailableNetworks(int32_t serial) override;
+ ::ndk::ScopedAStatus getBarringInfo(int32_t serial) override;
+ ::ndk::ScopedAStatus getCdmaRoamingPreference(int32_t serial) override;
+ ::ndk::ScopedAStatus getCellInfoList(int32_t serial) override;
+ ::ndk::ScopedAStatus getDataRegistrationState(int32_t serial) override;
+ ::ndk::ScopedAStatus getImsRegistrationState(int32_t serial) override;
+ ::ndk::ScopedAStatus getNetworkSelectionMode(int32_t serial) override;
+ ::ndk::ScopedAStatus getOperator(int32_t serial) override;
+ ::ndk::ScopedAStatus getSignalStrength(int32_t serial) override;
+ ::ndk::ScopedAStatus getSystemSelectionChannels(int32_t serial) override;
+ ::ndk::ScopedAStatus getVoiceRadioTechnology(int32_t serial) override;
+ ::ndk::ScopedAStatus getVoiceRegistrationState(int32_t serial) override;
+ ::ndk::ScopedAStatus isNrDualConnectivityEnabled(int32_t serial) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus setAllowedNetworkTypesBitmap(int32_t serial,
+ int32_t networkTypeBitmap) override;
+ ::ndk::ScopedAStatus setBandMode(
+ int32_t serial, ::aidl::android::hardware::radio::network::RadioBandMode mode) override;
+ ::ndk::ScopedAStatus setBarringPassword(int32_t serial, const std::string& facility,
+ const std::string& oldPassword,
+ const std::string& newPassword) override;
+ ::ndk::ScopedAStatus setCdmaRoamingPreference(
+ int32_t serial,
+ ::aidl::android::hardware::radio::network::CdmaRoamingType type) override;
+ ::ndk::ScopedAStatus setCellInfoListRate(int32_t serial, int32_t rate) override;
+ ::ndk::ScopedAStatus setIndicationFilter(int32_t serial, int32_t indicationFilter) override;
+ ::ndk::ScopedAStatus setLinkCapacityReportingCriteria(
+ int32_t serial, int32_t hysteresisMs, int32_t hysteresisDlKbps,
+ int32_t hysteresisUlKbps, const std::vector<int32_t>& thresholdsDownlinkKbps,
+ const std::vector<int32_t>& thresholdsUplinkKbps,
+ ::aidl::android::hardware::radio::AccessNetwork accessNetwork) override;
+ ::ndk::ScopedAStatus setLocationUpdates(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus setNetworkSelectionModeAutomatic(int32_t serial) override;
+ ::ndk::ScopedAStatus setNetworkSelectionModeManual(
+ int32_t serial, const std::string& operatorNumeric,
+ ::aidl::android::hardware::radio::AccessNetwork ran) override;
+ ::ndk::ScopedAStatus setNrDualConnectivityState(
+ int32_t serial,
+ ::aidl::android::hardware::radio::network::NrDualConnectivityState nrSt) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse>&
+ radioNetworkResponse,
+ const std::shared_ptr<
+ ::aidl::android::hardware::radio::network::IRadioNetworkIndication>&
+ radioNetworkIndication) override;
+ ::ndk::ScopedAStatus setSignalStrengthReportingCriteria(
+ int32_t serial,
+ const std::vector<::aidl::android::hardware::radio::network::SignalThresholdInfo>&
+ signalThresholdInfos) override;
+ ::ndk::ScopedAStatus setSuppServiceNotifications(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus setSystemSelectionChannels(
+ int32_t serial, bool specifyChannels,
+ const std::vector<::aidl::android::hardware::radio::network::RadioAccessSpecifier>&
+ specifiers) override;
+ ::ndk::ScopedAStatus startNetworkScan(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::network::NetworkScanRequest& request) override;
+ ::ndk::ScopedAStatus stopNetworkScan(int32_t serial) override;
+ ::ndk::ScopedAStatus supplyNetworkDepersonalization(int32_t serial,
+ const std::string& netPin) override;
+ ::ndk::ScopedAStatus setUsageSetting(
+ int32_t serial,
+ ::aidl::android::hardware::radio::network::UsageSetting usageSetting) override;
+ ::ndk::ScopedAStatus getUsageSetting(int32_t serial) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
new file mode 100644
index 0000000..1f82dd1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DriverContext.h"
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemResponse.h>
+#include <aidl/android/hardware/radio/network/IRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/sim/IRadioSimResponse.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoiceResponse.h>
+#include <android/hardware/radio/1.6/IRadioResponse.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioResponse : public V1_6::IRadioResponse {
+ std::shared_ptr<DriverContext> mContext;
+
+ GuaranteedCallback<::aidl::android::hardware::radio::data::IRadioDataResponse,
+ ::aidl::android::hardware::radio::data::IRadioDataResponseDefault>
+ mDataCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse,
+ ::aidl::android::hardware::radio::messaging::IRadioMessagingResponseDefault>
+ mMessagingCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::modem::IRadioModemResponse,
+ ::aidl::android::hardware::radio::modem::IRadioModemResponseDefault>
+ mModemCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::network::IRadioNetworkResponse,
+ ::aidl::android::hardware::radio::network::IRadioNetworkResponseDefault>
+ mNetworkCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::sim::IRadioSimResponse,
+ ::aidl::android::hardware::radio::sim::IRadioSimResponseDefault>
+ mSimCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::voice::IRadioVoiceResponse,
+ ::aidl::android::hardware::radio::voice::IRadioVoiceResponseDefault>
+ mVoiceCb;
+
+ // IRadioResponse @ 1.0
+ Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::CardStatus& cardStatus) override;
+ Return<void> supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> supplyNetworkDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+ Return<void> getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::Call>& calls) override;
+ Return<void> dialResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& imsi) override;
+ Return<void> hangupConnectionResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> hangupForegroundResumeBackgroundResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> switchWaitingOrHoldingAndActiveResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> conferenceResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> rejectCallResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getLastCallFailCauseResponse(
+ const V1_0::RadioResponseInfo& info,
+ const V1_0::LastCallFailCauseInfo& failCauseinfo) override;
+ Return<void> getSignalStrengthResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SignalStrength& sigStrength) override;
+ Return<void> getVoiceRegistrationStateResponse(
+ const V1_0::RadioResponseInfo& info,
+ const V1_0::VoiceRegStateResult& voiceRegResponse) override;
+ Return<void> getDataRegistrationStateResponse(
+ const V1_0::RadioResponseInfo& info,
+ const V1_0::DataRegStateResult& dataRegResponse) override;
+ Return<void> getOperatorResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& longName, const hidl_string& shortName,
+ const hidl_string& numeric) override;
+ Return<void> setRadioPowerResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> setupDataCallResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SetupDataCallResult& dcResponse) override;
+ Return<void> iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& iccIo) override;
+ Return<void> sendUssdResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
+ int32_t m) override;
+ Return<void> setClirResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCallForwardStatusResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::CallForwardInfo>& callForwardInfos) override;
+ Return<void> setCallForwardResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
+ int32_t serviceClass) override;
+ Return<void> setCallWaitingResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> acknowledgeLastIncomingGsmSmsResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> acceptCallResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t response) override;
+ Return<void> setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t retry) override;
+ Return<void> setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
+ bool manual) override;
+ Return<void> setNetworkSelectionModeAutomaticResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> setNetworkSelectionModeManualResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> getAvailableNetworksResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::OperatorInfo>& networkInfos) override;
+ Return<void> startDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> stopDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& version) override;
+ Return<void> separateConnectionResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setMuteResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) override;
+ Return<void> getClipResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::ClipStatus status) override;
+ Return<void> getDataCallListResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::SetupDataCallResult>& dcResponse) override;
+ Return<void> setSuppServiceNotificationsResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> writeSmsToSimResponse(const V1_0::RadioResponseInfo& info, int32_t index) override;
+ Return<void> deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setBandModeResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getAvailableBandModesResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::RadioBandMode>& bandModes) override;
+ Return<void> sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& commandResponse) override;
+ Return<void> sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> handleStkCallSetupRequestFromSimResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::PreferredNetworkType nwType) override;
+ Return<void> getNeighboringCidsResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::NeighboringCell>& cells) override;
+ Return<void> setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::CdmaRoamingType type) override;
+ Return<void> setTTYModeResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getTTYModeResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::TtyMode mode) override;
+ Return<void> setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
+ bool enable) override;
+ Return<void> sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> acknowledgeLastIncomingCdmaSmsResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> getGsmBroadcastConfigResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& configs) override;
+ Return<void> setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCdmaBroadcastConfigResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) override;
+ Return<void> setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setCdmaBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCDMASubscriptionResponse( //
+ const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
+ const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) override;
+ Return<void> writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
+ uint32_t index) override;
+ Return<void> deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getDeviceIdentityResponse( //
+ const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
+ const hidl_string& esn, const hidl_string& meid) override;
+ Return<void> exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& smsc) override;
+ Return<void> setSmscAddressResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::CdmaSubscriptionSource source) override;
+ Return<void> requestIsimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& response) override;
+ Return<void> acknowledgeIncomingGsmSmsWithPduResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& iccIo) override;
+ Return<void> getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::RadioTechnology rat) override;
+ Return<void> getCellInfoListResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::CellInfo>& cellInfo) override;
+ Return<void> setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getImsRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+ bool isRegistered,
+ V1_0::RadioTechnologyFamily ratFamily) override;
+ Return<void> sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& result) override;
+ Return<void> iccOpenLogicalChannelResponse(const V1_0::RadioResponseInfo& info,
+ int32_t channelId,
+ const hidl_vec<int8_t>& selectResponse) override;
+ Return<void> iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> iccTransmitApduLogicalChannelResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& result) override;
+ Return<void> nvReadItemResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& result) override;
+ Return<void> nvWriteItemResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> nvResetConfigResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setDataAllowedResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getHardwareConfigResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::HardwareConfig>& config) override;
+ Return<void> requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& result) override;
+ Return<void> setDataProfileResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> requestShutdownResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::RadioCapability& rc) override;
+ Return<void> setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::RadioCapability& rc) override;
+ Return<void> startLceServiceResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceStatusInfo& statusInfo) override;
+ Return<void> stopLceServiceResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceStatusInfo& statusInfo) override;
+ Return<void> pullLceDataResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceDataInfo& lceInfo) override;
+ Return<void> getModemActivityInfoResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::ActivityStatsInfo& activityInfo) override;
+ Return<void> setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
+ int32_t numAllowed) override;
+ Return<void> getAllowedCarriersResponse(const V1_0::RadioResponseInfo& info, bool allAllowed,
+ const V1_0::CarrierRestrictions& carriers) override;
+ Return<void> sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> acknowledgeRequest(int32_t serial) override;
+
+ // IRadioResponse @ 1.1
+ Return<void> setCarrierInfoForImsiEncryptionResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) override;
+ Return<void> startNetworkScanResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
+ const V1_1::KeepaliveStatus& status) override;
+ Return<void> stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) override;
+
+ // IRadioResponse @ 1.2
+ Return<void> getCellInfoListResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_2::CellInfo>& cellInfo) override;
+ Return<void> getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const V1_2::CardStatus& cardStatus) override;
+ Return<void> setSignalStrengthReportingCriteriaResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> setLinkCapacityReportingCriteriaResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_2::Call>& calls) override;
+ Return<void> getSignalStrengthResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const V1_2::SignalStrength& signalStrength) override;
+ Return<void> getVoiceRegistrationStateResponse_1_2(
+ const V1_0::RadioResponseInfo& info,
+ const V1_2::VoiceRegStateResult& voiceRegResponse) override;
+ Return<void> getDataRegistrationStateResponse_1_2(
+ const V1_0::RadioResponseInfo& info,
+ const V1_2::DataRegStateResult& dataRegResponse) override;
+
+ // IRadioResponse @ 1.3
+ Return<void> setSystemSelectionChannelsResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> enableModemResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
+ bool isEnabled) override;
+
+ // IRadioResponse @ 1.4
+ Return<void> emergencyDialResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getCellInfoListResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_4::CellInfo>& cellInfo) override;
+ Return<void> getDataRegistrationStateResponse_1_4(
+ const V1_0::RadioResponseInfo& info,
+ const V1_4::DataRegStateResult& dataRegResponse) override;
+ Return<void> getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const V1_4::CardStatus& cardStatus) override;
+ Return<void> getPreferredNetworkTypeBitmapResponse(
+ const V1_0::RadioResponseInfo& info,
+ hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) override;
+ Return<void> setPreferredNetworkTypeBitmapResponse(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> getDataCallListResponse_1_4(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_4::SetupDataCallResult>& dcResponse) override;
+ Return<void> setupDataCallResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const V1_4::SetupDataCallResult& dcResponse) override;
+ Return<void> setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getAllowedCarriersResponse_1_4(
+ const V1_0::RadioResponseInfo& info,
+ const V1_4::CarrierRestrictionsWithPriority& carriers,
+ V1_4::SimLockMultiSimPolicy multiSimPolicy) override;
+ Return<void> getSignalStrengthResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const V1_4::SignalStrength& signalStrength) override;
+
+ // IRadioResponse @ 1.5
+ Return<void> setSignalStrengthReportingCriteriaResponse_1_5(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> setLinkCapacityReportingCriteriaResponse_1_5(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) override;
+ Return<void> areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
+ bool enabled) override;
+ Return<void> setSystemSelectionChannelsResponse_1_5(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const V1_5::SetupDataCallResult& dcResponse) override;
+ Return<void> getDataCallListResponse_1_5(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) override;
+ Return<void> setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+ Return<void> setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+ Return<void> getBarringInfoResponse(const V1_0::RadioResponseInfo& info,
+ const V1_5::CellIdentity& cellIdentity,
+ const hidl_vec<V1_5::BarringInfo>& barringInfos) override;
+ Return<void> getVoiceRegistrationStateResponse_1_5(
+ const V1_0::RadioResponseInfo& info,
+ const V1_5::RegStateResult& voiceRegResponse) override;
+ Return<void> getDataRegistrationStateResponse_1_5(
+ const V1_0::RadioResponseInfo& info,
+ const V1_5::RegStateResult& dataRegResponse) override;
+ Return<void> getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_5::CellInfo>& cellInfo) override;
+ Return<void> setNetworkSelectionModeManualResponse_1_5(
+ const V1_0::RadioResponseInfo& info) override;
+ Return<void> sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> supplySimDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+ V1_5::PersoSubstate persoType,
+ int32_t remainingRetries) override;
+ Return<void> getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const V1_5::CardStatus& cardStatus) override;
+
+ // IRadioResponse @ 1.6
+ Return<void> setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) override;
+ Return<void> setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_6::SetupDataCallResult& dcResponse) override;
+ Return<void> getDataCallListResponse_1_6(
+ const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) override;
+ Return<void> sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) override;
+ Return<void> setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) override;
+ Return<void> setNrDualConnectivityStateResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
+ bool isEnabled) override;
+ Return<void> allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
+ int32_t id) override;
+ Return<void> releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> startHandoverResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> cancelHandoverResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> getAllowedNetworkTypesBitmapResponse(
+ const V1_6::RadioResponseInfo& info,
+ hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) override;
+ Return<void> setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> getSystemSelectionChannelsResponse(
+ const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) override;
+ Return<void> getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::CellInfo>& cellInfo) override;
+ Return<void> getSignalStrengthResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_6::SignalStrength& signalStrength) override;
+ Return<void> getVoiceRegistrationStateResponse_1_6(
+ const V1_6::RadioResponseInfo& info,
+ const V1_6::RegStateResult& voiceRegResponse) override;
+ Return<void> getDataRegistrationStateResponse_1_6(
+ const V1_6::RadioResponseInfo& info,
+ const V1_6::RegStateResult& dataRegResponse) override;
+ Return<void> getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::Call>& calls) override;
+ Return<void> getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
+ const V1_6::SlicingConfig& slicingConfig) override;
+ Return<void> getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) override;
+ Return<void> getSimPhonebookCapacityResponse(const V1_6::RadioResponseInfo& info,
+ const V1_6::PhonebookCapacity& capacity) override;
+ Return<void> updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
+ int32_t updatedRecordIndex) override;
+
+ public:
+ RadioResponse(std::shared_ptr<DriverContext> context);
+
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+ radioMessagingResponse);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> nwCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
+
+ std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
+ std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+ messagingCb();
+ std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb();
+ std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> networkCb();
+ std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb();
+ std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb();
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
new file mode 100644
index 0000000..84bb68b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/sim/BnRadioSim.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioSim : public RadioCompatBase, public aidl::android::hardware::radio::sim::BnRadioSim {
+ std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> respond();
+
+ ::ndk::ScopedAStatus areUiccApplicationsEnabled(int32_t serial) override;
+ ::ndk::ScopedAStatus changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
+ const std::string& newPin2,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus changeIccPinForApp(int32_t serial, const std::string& oldPin,
+ const std::string& newPin,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus enableUiccApplications(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus getAllowedCarriers(int32_t serial) override;
+ ::ndk::ScopedAStatus getCdmaSubscription(int32_t serial) override;
+ ::ndk::ScopedAStatus getCdmaSubscriptionSource(int32_t serial) override;
+ ::ndk::ScopedAStatus getFacilityLockForApp(int32_t serial, const std::string& facility,
+ const std::string& password, int32_t serviceClass,
+ const std::string& appId) override;
+ ::ndk::ScopedAStatus getIccCardStatus(int32_t serial) override;
+ ::ndk::ScopedAStatus getImsiForApp(int32_t serial, const std::string& aid) override;
+ ::ndk::ScopedAStatus getSimPhonebookCapacity(int32_t serial) override;
+ ::ndk::ScopedAStatus getSimPhonebookRecords(int32_t serial) override;
+ ::ndk::ScopedAStatus iccCloseLogicalChannel(int32_t serial, int32_t channelId) override;
+ ::ndk::ScopedAStatus iccIoForApp(
+ int32_t serial, const ::aidl::android::hardware::radio::sim::IccIo& iccIo) override;
+ ::ndk::ScopedAStatus iccOpenLogicalChannel(int32_t serial, const std::string& aid,
+ int32_t p2) override;
+ ::ndk::ScopedAStatus iccTransmitApduBasicChannel(
+ int32_t serial, const ::aidl::android::hardware::radio::sim::SimApdu& message) override;
+ ::ndk::ScopedAStatus iccTransmitApduLogicalChannel(
+ int32_t serial, const ::aidl::android::hardware::radio::sim::SimApdu& message) override;
+ ::ndk::ScopedAStatus reportStkServiceIsRunning(int32_t serial) override;
+ ::ndk::ScopedAStatus requestIccSimAuthentication(int32_t serial, int32_t authContext,
+ const std::string& authData,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus sendEnvelope(int32_t serial, const std::string& command) override;
+ ::ndk::ScopedAStatus sendEnvelopeWithStatus(int32_t serial,
+ const std::string& contents) override;
+ ::ndk::ScopedAStatus sendTerminalResponseToSim(int32_t serial,
+ const std::string& commandResponse) override;
+ ::ndk::ScopedAStatus setAllowedCarriers(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::sim::CarrierRestrictions& carriers,
+ ::aidl::android::hardware::radio::sim::SimLockMultiSimPolicy multiSimPolicy) override;
+ ::ndk::ScopedAStatus setCarrierInfoForImsiEncryption(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& imsiEncryptionInfo)
+ override;
+ ::ndk::ScopedAStatus setCdmaSubscriptionSource(
+ int32_t serial,
+ ::aidl::android::hardware::radio::sim::CdmaSubscriptionSource cdmaSub) override;
+ ::ndk::ScopedAStatus setFacilityLockForApp( //
+ int32_t serial, const std::string& facility, bool lockState, const std::string& passwd,
+ int32_t serviceClass, const std::string& appId) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse>&
+ radioSimResponse,
+ const std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication>&
+ radioSimIndication) override;
+ ::ndk::ScopedAStatus setSimCardPower(
+ int32_t serial, ::aidl::android::hardware::radio::sim::CardPowerState powerUp) override;
+ ::ndk::ScopedAStatus setUiccSubscription(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::sim::SelectUiccSub& uiccSub) override;
+ ::ndk::ScopedAStatus supplyIccPin2ForApp(int32_t serial, const std::string& pin2,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus supplyIccPinForApp(int32_t serial, const std::string& pin,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus supplyIccPuk2ForApp(int32_t serial, const std::string& puk2,
+ const std::string& pin2,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus supplyIccPukForApp(int32_t serial, const std::string& puk,
+ const std::string& pin,
+ const std::string& aid) override;
+ ::ndk::ScopedAStatus supplySimDepersonalization(
+ int32_t serial, ::aidl::android::hardware::radio::sim::PersoSubstate persoType,
+ const std::string& controlKey) override;
+ ::ndk::ScopedAStatus updateSimPhonebookRecords(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::sim::PhonebookRecordInfo& recordInfo) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
new file mode 100644
index 0000000..0f1d5fd
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/voice/BnRadioVoice.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioVoice : public RadioCompatBase,
+ public aidl::android::hardware::radio::voice::BnRadioVoice {
+ std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> respond();
+
+ ::ndk::ScopedAStatus acceptCall(int32_t serial) override;
+ ::ndk::ScopedAStatus cancelPendingUssd(int32_t serial) override;
+ ::ndk::ScopedAStatus conference(int32_t serial) override;
+ ::ndk::ScopedAStatus dial(
+ int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo) override;
+ ::ndk::ScopedAStatus emergencyDial(
+ int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo,
+ int32_t categories, const std::vector<std::string>& urns,
+ ::aidl::android::hardware::radio::voice::EmergencyCallRouting routing,
+ bool hasKnownUserIntentEmergency, bool isTesting) override;
+ ::ndk::ScopedAStatus exitEmergencyCallbackMode(int32_t serial) override;
+ ::ndk::ScopedAStatus explicitCallTransfer(int32_t serial) override;
+ ::ndk::ScopedAStatus getCallForwardStatus(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::voice::CallForwardInfo& callInfo) override;
+ ::ndk::ScopedAStatus getCallWaiting(int32_t serial, int32_t serviceClass) override;
+ ::ndk::ScopedAStatus getClip(int32_t serial) override;
+ ::ndk::ScopedAStatus getClir(int32_t serial) override;
+ ::ndk::ScopedAStatus getCurrentCalls(int32_t serial) override;
+ ::ndk::ScopedAStatus getLastCallFailCause(int32_t serial) override;
+ ::ndk::ScopedAStatus getMute(int32_t serial) override;
+ ::ndk::ScopedAStatus getPreferredVoicePrivacy(int32_t serial) override;
+ ::ndk::ScopedAStatus getTtyMode(int32_t serial) override;
+ ::ndk::ScopedAStatus handleStkCallSetupRequestFromSim(int32_t serial, bool accept) override;
+ ::ndk::ScopedAStatus hangup(int32_t serial, int32_t gsmIndex) override;
+ ::ndk::ScopedAStatus hangupForegroundResumeBackground(int32_t serial) override;
+ ::ndk::ScopedAStatus hangupWaitingOrBackground(int32_t serial) override;
+ ::ndk::ScopedAStatus isVoNrEnabled(int32_t serial) override;
+ ::ndk::ScopedAStatus rejectCall(int32_t serial) override;
+ ::ndk::ScopedAStatus responseAcknowledgement() override;
+ ::ndk::ScopedAStatus sendBurstDtmf(int32_t serial, const std::string& dtmf, int32_t on,
+ int32_t off) override;
+ ::ndk::ScopedAStatus sendCdmaFeatureCode(int32_t serial, const std::string& fcode) override;
+ ::ndk::ScopedAStatus sendDtmf(int32_t serial, const std::string& s) override;
+ ::ndk::ScopedAStatus sendUssd(int32_t serial, const std::string& ussd) override;
+ ::ndk::ScopedAStatus separateConnection(int32_t serial, int32_t gsmIndex) override;
+ ::ndk::ScopedAStatus setCallForward(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::voice::CallForwardInfo& callInfo) override;
+ ::ndk::ScopedAStatus setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) override;
+ ::ndk::ScopedAStatus setClir(int32_t serial, int32_t status) override;
+ ::ndk::ScopedAStatus setMute(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus setPreferredVoicePrivacy(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse>&
+ radioVoiceResponse,
+ const std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication>&
+ radioVoiceIndication) override;
+ ::ndk::ScopedAStatus setTtyMode(int32_t serial,
+ ::aidl::android::hardware::radio::voice::TtyMode mode) override;
+ ::ndk::ScopedAStatus setVoNrEnabled(int32_t serial, bool enable) override;
+ ::ndk::ScopedAStatus startDtmf(int32_t serial, const std::string& s) override;
+ ::ndk::ScopedAStatus stopDtmf(int32_t serial) override;
+ ::ndk::ScopedAStatus switchWaitingOrHoldingAndActive(int32_t serial) override;
+
+ public:
+ using RadioCompatBase::RadioCompatBase;
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
new file mode 100644
index 0000000..eb87828
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#define RADIO_MODULE "MessagingIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingIndication> rmiCb) {
+ mMessagingCb = rmiCb;
+}
+
+std::shared_ptr<aidl::IRadioMessagingIndication> RadioIndication::messagingCb() {
+ return mMessagingCb.get();
+}
+
+Return<void> RadioIndication::cdmaNewSms(V1_0::RadioIndicationType type,
+ const V1_0::CdmaSmsMessage& msg) {
+ LOG_CALL << type;
+ messagingCb()->cdmaNewSms(toAidl(type), toAidl(msg));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ messagingCb()->cdmaRuimSmsStorageFull(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::newBroadcastSms(V1_0::RadioIndicationType type,
+ const hidl_vec<uint8_t>& data) {
+ LOG_CALL << type;
+ messagingCb()->newBroadcastSms(toAidl(type), data);
+ return {};
+}
+
+Return<void> RadioIndication::newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) {
+ LOG_CALL << type;
+ messagingCb()->newSms(toAidl(type), pdu);
+ return {};
+}
+
+Return<void> RadioIndication::newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) {
+ LOG_CALL << type;
+ messagingCb()->newSmsOnSim(toAidl(type), recordNumber);
+ return {};
+}
+
+Return<void> RadioIndication::newSmsStatusReport(V1_0::RadioIndicationType type,
+ const hidl_vec<uint8_t>& pdu) {
+ LOG_CALL << type;
+ messagingCb()->newSmsStatusReport(toAidl(type), pdu);
+ return {};
+}
+
+Return<void> RadioIndication::simSmsStorageFull(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ messagingCb()->simSmsStorageFull(toAidl(type));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
new file mode 100644
index 0000000..56d49f1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioMessaging.h>
+
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Messaging"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioMessaging::respond() {
+ return mCallbackManager->response().messagingCb();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeIncomingGsmSmsWithPdu( //
+ int32_t serial, bool success, const std::string& ackPdu) {
+ LOG_CALL << serial << ' ' << success << ' ' << ackPdu;
+ mHal1_5->acknowledgeIncomingGsmSmsWithPdu(serial, success, ackPdu);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeLastIncomingCdmaSms( //
+ int32_t serial, const aidl::CdmaSmsAck& smsAck) {
+ LOG_CALL << serial;
+ mHal1_5->acknowledgeLastIncomingCdmaSms(serial, toHidl(smsAck));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeLastIncomingGsmSms( //
+ int32_t serial, bool success, aidl::SmsAcknowledgeFailCause cause) {
+ LOG_CALL << serial << ' ' << success;
+ mHal1_5->acknowledgeLastIncomingGsmSms(serial, success, V1_0::SmsAcknowledgeFailCause(cause));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::deleteSmsOnRuim(int32_t serial, int32_t index) {
+ LOG_CALL << serial << ' ' << index;
+ mHal1_5->deleteSmsOnRuim(serial, index);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::deleteSmsOnSim(int32_t serial, int32_t index) {
+ LOG_CALL << serial << ' ' << index;
+ mHal1_5->deleteSmsOnSim(serial, index);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::getCdmaBroadcastConfig(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getCdmaBroadcastConfig(serial);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::getGsmBroadcastConfig(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getGsmBroadcastConfig(serial);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::getSmscAddress(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getSmscAddress(serial);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::reportSmsMemoryStatus(int32_t serial, bool available) {
+ LOG_CALL << serial << ' ' << available;
+ mHal1_5->reportSmsMemoryStatus(serial, available);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::sendCdmaSms(int32_t serial, const aidl::CdmaSmsMessage& sms) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->sendCdmaSms_1_6(serial, toHidl(sms));
+ } else {
+ mHal1_5->sendCdmaSms(serial, toHidl(sms));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::sendCdmaSmsExpectMore(int32_t serial, const aidl::CdmaSmsMessage& m) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->sendCdmaSmsExpectMore_1_6(serial, toHidl(m));
+ } else {
+ mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::sendImsSms(int32_t serial, const aidl::ImsSmsMessage& message) {
+ LOG_CALL << serial;
+ mHal1_5->sendImsSms(serial, toHidl(message));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::sendSms(int32_t serial, const aidl::GsmSmsMessage& message) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->sendSms_1_6(serial, toHidl(message));
+ } else {
+ mHal1_5->sendSms(serial, toHidl(message));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::sendSmsExpectMore(int32_t serial, const aidl::GsmSmsMessage& msg) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->sendSmsExpectMore_1_6(serial, toHidl(msg));
+ } else {
+ mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setCdmaBroadcastActivation(int32_t serial, bool activate) {
+ LOG_CALL << serial << ' ' << activate;
+ mHal1_5->setCdmaBroadcastActivation(serial, activate);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setCdmaBroadcastConfig(
+ int32_t serial, const std::vector<aidl::CdmaBroadcastSmsConfigInfo>& cfgInfo) {
+ LOG_CALL << serial;
+ mHal1_5->setCdmaBroadcastConfig(serial, toHidl(cfgInfo));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setGsmBroadcastActivation(int32_t serial, bool activate) {
+ LOG_CALL << serial << ' ' << activate;
+ mHal1_5->setGsmBroadcastActivation(serial, activate);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setGsmBroadcastConfig(
+ int32_t serial, const std::vector<aidl::GsmBroadcastSmsConfigInfo>& configInfo) {
+ LOG_CALL << serial;
+ mHal1_5->setGsmBroadcastConfig(serial, toHidl(configInfo));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioMessagingResponse>& response,
+ const std::shared_ptr<aidl::IRadioMessagingIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::setSmscAddress(int32_t serial, const std::string& smsc) {
+ LOG_CALL << serial << ' ' << smsc;
+ mHal1_5->setSmscAddress(serial, smsc);
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::writeSmsToRuim(int32_t serial, const aidl::CdmaSmsWriteArgs& sms) {
+ LOG_CALL << serial;
+ mHal1_5->writeSmsToRuim(serial, toHidl(sms));
+ return ok();
+}
+
+ScopedAStatus RadioMessaging::writeSmsToSim(int32_t serial, const aidl::SmsWriteArgs& smsWrArgs) {
+ LOG_CALL << serial;
+ mHal1_5->writeSmsToSim(serial, toHidl(smsWrArgs));
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
new file mode 100644
index 0000000..7a9273f
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "MessagingResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingResponse> rmrCb) {
+ mMessagingCb = rmrCb;
+}
+
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioResponse::messagingCb() {
+ return mMessagingCb.get();
+}
+
+Return<void> RadioResponse::acknowledgeIncomingGsmSmsWithPduResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::acknowledgeLastIncomingCdmaSmsResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::acknowledgeLastIncomingGsmSmsResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->deleteSmsOnRuimResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->deleteSmsOnSimResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::getCdmaBroadcastConfigResponse(
+ const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) {
+ LOG_CALL << info.serial;
+ messagingCb()->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
+ return {};
+}
+
+Return<void> RadioResponse::getGsmBroadcastConfigResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& cfg) {
+ LOG_CALL << info.serial;
+ messagingCb()->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
+ return {};
+}
+
+Return<void> RadioResponse::getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& smsc) {
+ LOG_CALL << info.serial;
+ messagingCb()->getSmscAddressResponse(toAidl(info), smsc);
+ return {};
+}
+
+Return<void> RadioResponse::reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->reportSmsMemoryStatusResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendImsSmsResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendSmsResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const V1_0::SendSmsResult& sms) {
+ LOG_CALL << info.serial;
+ messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
+ return {};
+}
+
+Return<void> RadioResponse::setCdmaBroadcastActivationResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->setCdmaBroadcastActivationResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->setCdmaBroadcastConfigResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->setGsmBroadcastActivationResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->setGsmBroadcastConfigResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSmscAddressResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ messagingCb()->setSmscAddressResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
+ uint32_t index) {
+ LOG_CALL << info.serial << ' ' << index;
+ messagingCb()->writeSmsToRuimResponse(toAidl(info), index);
+ return {};
+}
+
+Return<void> RadioResponse::writeSmsToSimResponse(const V1_0::RadioResponseInfo& info,
+ int32_t index) {
+ LOG_CALL << info.serial << ' ' << index;
+ messagingCb()->writeSmsToSimResponse(toAidl(info), index);
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/structs.cpp b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
new file mode 100644
index 0000000..9019680
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "collections.h"
+
+#include <aidl/android/hardware/radio/messaging/CdmaSmsAddress.h>
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+V1_0::CdmaSmsAck toHidl(const aidl::CdmaSmsAck& smsAck) {
+ return {
+ .errorClass = (smsAck.errorClass ? V1_0::CdmaSmsErrorClass::ERROR
+ : V1_0::CdmaSmsErrorClass::NO_ERROR),
+ .smsCauseCode = smsAck.smsCauseCode,
+ };
+}
+
+static aidl::CdmaSmsAddress toAidl(const V1_0::CdmaSmsAddress& addr) {
+ return {
+ .digitMode = static_cast<int32_t>(addr.digitMode),
+ .isNumberModeDataNetwork = addr.numberMode == V1_0::CdmaSmsNumberMode::DATA_NETWORK,
+ .numberType = static_cast<int32_t>(addr.numberType),
+ .numberPlan = static_cast<int32_t>(addr.numberPlan),
+ .digits = addr.digits,
+ };
+}
+
+static V1_0::CdmaSmsAddress toHidl(const aidl::CdmaSmsAddress& addr) {
+ return {
+ .digitMode = V1_0::CdmaSmsDigitMode{addr.digitMode},
+ .numberMode = addr.isNumberModeDataNetwork ? V1_0::CdmaSmsNumberMode::DATA_NETWORK
+ : V1_0::CdmaSmsNumberMode::NOT_DATA_NETWORK,
+ .numberType = V1_0::CdmaSmsNumberType{addr.numberType},
+ .numberPlan = V1_0::CdmaSmsNumberPlan{addr.numberPlan},
+ .digits = addr.digits,
+ };
+}
+
+static aidl::CdmaSmsSubaddress toAidl(const V1_0::CdmaSmsSubaddress& addr) {
+ return {
+ .subaddressType = static_cast<int32_t>(addr.subaddressType),
+ .odd = addr.odd,
+ .digits = addr.digits,
+ };
+}
+
+static V1_0::CdmaSmsSubaddress toHidl(const aidl::CdmaSmsSubaddress& addr) {
+ return {
+ .subaddressType = V1_0::CdmaSmsSubaddressType{addr.subaddressType},
+ .odd = addr.odd,
+ .digits = addr.digits,
+ };
+}
+
+::aidl::android::hardware::radio::messaging::CdmaSmsMessage toAidl(const V1_0::CdmaSmsMessage& m) {
+ return {
+ .teleserviceId = m.teleserviceId,
+ .isServicePresent = m.isServicePresent,
+ .serviceCategory = m.serviceCategory,
+ .address = toAidl(m.address),
+ .subAddress = toAidl(m.subAddress),
+ .bearerData = m.bearerData,
+ };
+}
+
+V1_0::CdmaSmsMessage toHidl(const aidl::CdmaSmsMessage& msg) {
+ return {
+ .teleserviceId = msg.teleserviceId,
+ .isServicePresent = msg.isServicePresent,
+ .serviceCategory = msg.serviceCategory,
+ .address = toHidl(msg.address),
+ .subAddress = toHidl(msg.subAddress),
+ .bearerData = msg.bearerData,
+ };
+}
+
+V1_0::ImsSmsMessage toHidl(const aidl::ImsSmsMessage& msg) {
+ return {
+ .tech = V1_0::RadioTechnologyFamily{msg.tech},
+ .retry = msg.retry,
+ .messageRef = msg.messageRef,
+ .cdmaMessage = toHidl(msg.cdmaMessage),
+ .gsmMessage = toHidl(msg.gsmMessage),
+ };
+}
+
+V1_0::GsmSmsMessage toHidl(const aidl::GsmSmsMessage& msg) {
+ return {
+ .smscPdu = msg.smscPdu,
+ .pdu = msg.pdu,
+ };
+}
+
+aidl::CdmaBroadcastSmsConfigInfo toAidl(const V1_0::CdmaBroadcastSmsConfigInfo& info) {
+ return {
+ .serviceCategory = info.serviceCategory,
+ .language = info.language,
+ .selected = info.selected,
+ };
+}
+
+V1_0::CdmaBroadcastSmsConfigInfo toHidl(const aidl::CdmaBroadcastSmsConfigInfo& info) {
+ return {
+ .serviceCategory = info.serviceCategory,
+ .language = info.language,
+ .selected = info.selected,
+ };
+}
+
+aidl::GsmBroadcastSmsConfigInfo toAidl(const V1_0::GsmBroadcastSmsConfigInfo& info) {
+ return {
+ .fromServiceId = info.fromServiceId,
+ .toServiceId = info.toServiceId,
+ .fromCodeScheme = info.fromCodeScheme,
+ .toCodeScheme = info.toCodeScheme,
+ .selected = info.selected,
+ };
+}
+
+V1_0::GsmBroadcastSmsConfigInfo toHidl(const aidl::GsmBroadcastSmsConfigInfo& info) {
+ return {
+ .fromServiceId = info.fromServiceId,
+ .toServiceId = info.toServiceId,
+ .fromCodeScheme = info.fromCodeScheme,
+ .toCodeScheme = info.toCodeScheme,
+ .selected = info.selected,
+ };
+}
+
+V1_0::CdmaSmsWriteArgs toHidl(const aidl::CdmaSmsWriteArgs& args) {
+ return {
+ .status = V1_0::CdmaSmsWriteArgsStatus{args.status},
+ .message = toHidl(args.message),
+ };
+}
+
+V1_0::SmsWriteArgs toHidl(const aidl::SmsWriteArgs& args) {
+ return {
+ .status = V1_0::SmsWriteArgsStatus{args.status},
+ .pdu = args.pdu,
+ .smsc = args.smsc,
+ };
+}
+
+::aidl::android::hardware::radio::messaging::SendSmsResult toAidl(
+ const V1_0::SendSmsResult& result) {
+ return {
+ .messageRef = result.messageRef,
+ .ackPDU = result.ackPDU,
+ .errorCode = result.errorCode,
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/structs.h b/radio/aidl/compat/libradiocompat/messaging/structs.h
new file mode 100644
index 0000000..afb4941
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/structs.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsAck.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.h>
+#include <aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.h>
+#include <aidl/android/hardware/radio/messaging/GsmSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/ImsSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/SendSmsResult.h>
+#include <aidl/android/hardware/radio/messaging/SmsWriteArgs.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::CdmaSmsAck toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsAck& ack);
+
+::aidl::android::hardware::radio::messaging::CdmaSmsMessage toAidl(const V1_0::CdmaSmsMessage& msg);
+V1_0::CdmaSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& msg);
+
+V1_0::ImsSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::ImsSmsMessage& msg);
+
+V1_0::GsmSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& msg);
+
+::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo //
+toAidl(const V1_0::CdmaBroadcastSmsConfigInfo& info);
+V1_0::CdmaBroadcastSmsConfigInfo //
+toHidl(const ::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo& info);
+
+::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo //
+toAidl(const V1_0::GsmBroadcastSmsConfigInfo& info);
+V1_0::GsmBroadcastSmsConfigInfo //
+toHidl(const ::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo& info);
+
+V1_0::CdmaSmsWriteArgs //
+toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsWriteArgs& args);
+
+V1_0::SmsWriteArgs toHidl(const ::aidl::android::hardware::radio::messaging::SmsWriteArgs& args);
+
+::aidl::android::hardware::radio::messaging::SendSmsResult toAidl(const V1_0::SendSmsResult& res);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
new file mode 100644
index 0000000..851c93b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioModemIndication> modemCb) {
+ mModemCb = modemCb;
+}
+
+std::shared_ptr<aidl::IRadioModemIndication> RadioIndication::modemCb() {
+ return mModemCb.get();
+}
+
+Return<void> RadioIndication::hardwareConfigChanged(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::HardwareConfig>& configs) {
+ LOG_CALL << type;
+ modemCb()->hardwareConfigChanged(toAidl(type), toAidl(configs));
+ return {};
+}
+
+Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type, const hidl_string& reasn) {
+ LOG_CALL << type;
+ modemCb()->modemReset(toAidl(type), reasn);
+ return {};
+}
+
+Return<void> RadioIndication::radioCapabilityIndication(V1_0::RadioIndicationType type,
+ const V1_0::RadioCapability& rc) {
+ LOG_CALL << type;
+ modemCb()->radioCapabilityIndication(toAidl(type), toAidl(rc));
+ return {};
+}
+
+Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType t, V1_0::RadioState st) {
+ LOG_CALL << t;
+ modemCb()->radioStateChanged(toAidl(t), aidl::RadioState(st));
+ return {};
+}
+
+Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ modemCb()->rilConnected(toAidl(type));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
new file mode 100644
index 0000000..d28b940
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioModem.h>
+
+#include "debug.h"
+#include "structs.h"
+
+#define RADIO_MODULE "Modem"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioModemResponse> RadioModem::respond() {
+ return mCallbackManager->response().modemCb();
+}
+
+ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
+ LOG_CALL << serial;
+ mHal1_5->enableModem(serial, on);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getBasebandVersion(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getBasebandVersion(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getDeviceIdentity(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getDeviceIdentity(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getHardwareConfig(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getHardwareConfig(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getModemActivityInfo(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getModemActivityInfo(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getModemStackStatus(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getModemStackStatus(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::getRadioCapability(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getRadioCapability(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvReadItem(int32_t serial, aidl::NvItem itemId) {
+ LOG_CALL << serial;
+ mHal1_5->nvReadItem(serial, V1_0::NvItem(itemId));
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvResetConfig(int32_t serial, aidl::ResetNvType resetType) {
+ LOG_CALL << serial;
+ mHal1_5->nvResetConfig(serial, V1_0::ResetNvType(resetType));
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) {
+ LOG_CALL << serial;
+ mHal1_5->nvWriteCdmaPrl(serial, prl);
+ return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteItem(int32_t serial, const aidl::NvWriteItem& item) {
+ LOG_CALL << serial;
+ mHal1_5->nvWriteItem(serial, toHidl(item));
+ return ok();
+}
+
+ScopedAStatus RadioModem::requestShutdown(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->requestShutdown(serial);
+ return ok();
+}
+
+ScopedAStatus RadioModem::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioModem::sendDeviceState(int32_t serial, aidl::DeviceStateType type, bool state) {
+ LOG_CALL << serial;
+ mHal1_5->sendDeviceState(serial, V1_0::DeviceStateType(type), state);
+ return ok();
+}
+
+ScopedAStatus RadioModem::setRadioCapability(int32_t serial, const aidl::RadioCapability& rc) {
+ LOG_CALL << serial;
+ mHal1_5->setRadioCapability(serial, toHidl(rc));
+ return ok();
+}
+
+ScopedAStatus RadioModem::setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+ bool preferredForEmergencyCall) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->setRadioPower_1_6(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+ } else {
+ mHal1_5->setRadioPower_1_5(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioModem::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioModemResponse>& response,
+ const std::shared_ptr<aidl::IRadioModemIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
new file mode 100644
index 0000000..6e1a962
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioModemResponse> modemCb) {
+ mModemCb = modemCb;
+}
+
+std::shared_ptr<aidl::IRadioModemResponse> RadioResponse::modemCb() {
+ return mModemCb.get();
+}
+
+Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->enableModemResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& version) {
+ LOG_CALL << info.serial;
+ modemCb()->getBasebandVersionResponse(toAidl(info), version);
+ return {};
+}
+
+Return<void> RadioResponse::getDeviceIdentityResponse( //
+ const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
+ const hidl_string& esn, const hidl_string& meid) {
+ LOG_CALL << info.serial;
+ modemCb()->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
+ return {};
+}
+
+Return<void> RadioResponse::getHardwareConfigResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
+ LOG_CALL << info.serial;
+ modemCb()->getHardwareConfigResponse(toAidl(info), toAidl(config));
+ return {};
+}
+
+Return<void> RadioResponse::getModemActivityInfoResponse(
+ const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
+ LOG_CALL << info.serial;
+ modemCb()->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
+ return {};
+}
+
+Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
+ bool isEnabled) {
+ LOG_CALL << info.serial;
+ modemCb()->getModemStackStatusResponse(toAidl(info), isEnabled);
+ return {};
+}
+
+Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::RadioCapability& rc) {
+ LOG_CALL << info.serial;
+ modemCb()->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
+ return {};
+}
+
+Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& result) {
+ LOG_CALL << info.serial;
+ modemCb()->nvReadItemResponse(toAidl(info), result);
+ return {};
+}
+
+Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->nvResetConfigResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->nvWriteCdmaPrlResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->nvWriteItemResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->requestShutdownResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->sendDeviceStateResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::RadioCapability& rc) {
+ LOG_CALL << info.serial;
+ modemCb()->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
+ return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->setRadioPowerResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->setRadioPowerResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ modemCb()->setRadioPowerResponse(toAidl(info));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
new file mode 100644
index 0000000..69e651b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+V1_0::NvWriteItem toHidl(const aidl::NvWriteItem& item) {
+ return {
+ .itemId = V1_0::NvItem{item.itemId},
+ .value = item.value,
+ };
+}
+
+aidl::RadioCapability toAidl(const V1_0::RadioCapability& capa) {
+ return {
+ .session = capa.session,
+ .phase = static_cast<int32_t>(capa.phase),
+ .raf = static_cast<int32_t>(capa.raf),
+ .logicalModemUuid = capa.logicalModemUuid,
+ .status = static_cast<int32_t>(capa.status),
+ };
+}
+
+V1_0::RadioCapability toHidl(const aidl::RadioCapability& capa) {
+ return {
+ .session = capa.session,
+ .phase = V1_0::RadioCapabilityPhase{capa.phase},
+ .raf = toHidlBitfield<V1_0::RadioAccessFamily>(capa.raf),
+ .logicalModemUuid = capa.logicalModemUuid,
+ .status = V1_0::RadioCapabilityStatus{capa.status},
+ };
+}
+
+aidl::HardwareConfig toAidl(const V1_0::HardwareConfig& config) {
+ return {
+ .type = static_cast<int32_t>(config.type),
+ .uuid = config.uuid,
+ .state = static_cast<int32_t>(config.state),
+ .modem = toAidl(config.modem),
+ .sim = toAidl(config.sim),
+ };
+}
+
+aidl::HardwareConfigModem toAidl(const V1_0::HardwareConfigModem& modem) {
+ return {
+ .rilModel = modem.rilModel,
+ .rat = RadioTechnology(modem.rat),
+ .maxVoiceCalls = modem.maxVoice,
+ .maxDataCalls = modem.maxData,
+ .maxStandby = modem.maxStandby,
+ };
+}
+
+aidl::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& sim) {
+ return {
+ .modemUuid = sim.modemUuid,
+ };
+}
+
+aidl::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& info) {
+ const aidl::ActivityStatsTechSpecificInfo techSpecificInfo = {
+ .rat = AccessNetwork(AccessNetwork::UNKNOWN),
+ .frequencyRange = static_cast<int32_t>(
+ aidl::ActivityStatsTechSpecificInfo::FREQUENCY_RANGE_UNKNOWN),
+ .txmModetimeMs = toAidl(info.txmModetimeMs),
+ .rxModeTimeMs = static_cast<int32_t>(info.rxModeTimeMs),
+ };
+
+ return {
+ .sleepModeTimeMs = static_cast<int32_t>(info.sleepModeTimeMs),
+ .idleModeTimeMs = static_cast<int32_t>(info.idleModeTimeMs),
+ .techSpecificInfo = {techSpecificInfo},
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.h b/radio/aidl/compat/libradiocompat/modem/structs.h
new file mode 100644
index 0000000..af714c7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/ActivityStatsInfo.h>
+#include <aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfig.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigModem.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigSim.h>
+#include <aidl/android/hardware/radio/modem/NvWriteItem.h>
+#include <aidl/android/hardware/radio/modem/RadioCapability.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::NvWriteItem toHidl(const ::aidl::android::hardware::radio::modem::NvWriteItem& item);
+
+::aidl::android::hardware::radio::modem::RadioCapability toAidl(const V1_0::RadioCapability& capa);
+V1_0::RadioCapability toHidl(const ::aidl::android::hardware::radio::modem::RadioCapability& capa);
+
+::aidl::android::hardware::radio::modem::HardwareConfig toAidl(const V1_0::HardwareConfig& config);
+
+::aidl::android::hardware::radio::modem::HardwareConfigModem //
+toAidl(const V1_0::HardwareConfigModem& modem);
+
+::aidl::android::hardware::radio::modem::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& s);
+
+::aidl::android::hardware::radio::modem::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& i);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
new file mode 100644
index 0000000..4eb99f7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "NetworkIndication"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::network;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkIndication> netCb) {
+ mNetworkCb = netCb;
+}
+
+std::shared_ptr<aidl::IRadioNetworkIndication> RadioIndication::networkCb() {
+ return mNetworkCb.get();
+}
+
+Return<void> RadioIndication::barringInfoChanged(V1_0::RadioIndicationType type,
+ const V1_5::CellIdentity& cellIdentity,
+ const hidl_vec<V1_5::BarringInfo>& barringInfos) {
+ LOG_CALL << type;
+ networkCb()->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) {
+ LOG_CALL << type;
+ networkCb()->cdmaPrlChanged(toAidl(type), version);
+ return {};
+}
+
+Return<void> RadioIndication::cellInfoList(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_0::CellInfo>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_2(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_2::CellInfo>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_4(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_4::CellInfo>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_5(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_5::CellInfo>& records) {
+ LOG_CALL << type;
+ networkCb()->cellInfoList(toAidl(type), toAidl(records));
+ return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_6(V1_0::RadioIndicationType type,
+ const hidl_vec<V1_6::CellInfo>& records) {
+ LOG_CALL << type;
+ networkCb()->cellInfoList(toAidl(type), toAidl(records));
+ return {};
+}
+
+Return<void> RadioIndication::currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
+ const V1_2::LinkCapacityEstimate& lce) {
+ LOG_CALL << type;
+ networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+ return {};
+}
+
+Return<void> RadioIndication::currentLinkCapacityEstimate_1_6(
+ V1_0::RadioIndicationType type, const V1_6::LinkCapacityEstimate& lce) {
+ LOG_CALL << type;
+ networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+ return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_2::PhysicalChannelConfig>&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs_1_4(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_4::PhysicalChannelConfig>& configs) {
+ LOG_CALL << type;
+ networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+ return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs_1_6(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_6::PhysicalChannelConfig>& configs) {
+ LOG_CALL << type;
+ networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+ return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength(V1_0::RadioIndicationType type,
+ const V1_0::SignalStrength&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_2(V1_0::RadioIndicationType type,
+ const V1_2::SignalStrength&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_4(
+ V1_0::RadioIndicationType type, const V1_4::SignalStrength& signalStrength) {
+ LOG_CALL << type;
+ networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+ return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_6(
+ V1_0::RadioIndicationType type, const V1_6::SignalStrength& signalStrength) {
+ LOG_CALL << type;
+ networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+ return {};
+}
+
+Return<void> RadioIndication::imsNetworkStateChanged(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ networkCb()->imsNetworkStateChanged(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::networkScanResult(V1_0::RadioIndicationType type,
+ const V1_1::NetworkScanResult&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_2(V1_0::RadioIndicationType type,
+ const V1_2::NetworkScanResult&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_4(V1_0::RadioIndicationType type,
+ const V1_4::NetworkScanResult&) {
+ LOG_CALL << type;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_5(V1_0::RadioIndicationType type,
+ const V1_5::NetworkScanResult& result) {
+ LOG_CALL << type;
+ networkCb()->networkScanResult(toAidl(type), toAidl(result));
+ return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_6(V1_0::RadioIndicationType type,
+ const V1_6::NetworkScanResult& result) {
+ LOG_CALL << type;
+ networkCb()->networkScanResult(toAidl(type), toAidl(result));
+ return {};
+}
+
+Return<void> RadioIndication::networkStateChanged(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ networkCb()->networkStateChanged(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::nitzTimeReceived(V1_0::RadioIndicationType type,
+ const hidl_string& nitzTime, uint64_t receivedTime) {
+ LOG_CALL << type;
+ networkCb()->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
+ return {};
+}
+
+Return<void> RadioIndication::registrationFailed( //
+ V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+ const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
+ int32_t additionalCauseCode) {
+ LOG_CALL << type;
+ networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn, domain,
+ causeCode, additionalCauseCode);
+ return {};
+}
+
+Return<void> RadioIndication::restrictedStateChanged(V1_0::RadioIndicationType type,
+ V1_0::PhoneRestrictedState state) {
+ LOG_CALL << type;
+ networkCb()->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
+ return {};
+}
+
+Return<void> RadioIndication::suppSvcNotify(V1_0::RadioIndicationType type,
+ const V1_0::SuppSvcNotification& suppSvc) {
+ LOG_CALL << type;
+ networkCb()->suppSvcNotify(toAidl(type), toAidl(suppSvc));
+ return {};
+}
+
+Return<void> RadioIndication::voiceRadioTechChanged(V1_0::RadioIndicationType type,
+ V1_0::RadioTechnology rat) {
+ LOG_CALL << type;
+ networkCb()->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
+ return {};
+}
+
+Return<void> RadioIndication::lceData(V1_0::RadioIndicationType type, const V1_0::LceDataInfo&) {
+ LOG_CALL << type;
+ LOG(WARNING) << "lceData indication is deprecated";
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
new file mode 100644
index 0000000..22b9ede
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioNetwork.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+#include "utils.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Network"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::network;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioNetwork::respond() {
+ return mCallbackManager->response().networkCb();
+}
+
+ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getAllowedNetworkTypesBitmap(serial);
+ } else {
+ mHal1_5->getPreferredNetworkType(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getAvailableBandModes(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getAvailableBandModes(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getAvailableNetworks(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getAvailableNetworks(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getBarringInfo(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getBarringInfo(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getCdmaRoamingPreference(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getCdmaRoamingPreference(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getCellInfoList(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getCellInfoList_1_6(serial);
+ } else {
+ mHal1_5->getCellInfoList(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getDataRegistrationState(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getDataRegistrationState_1_6(serial);
+ } else {
+ mHal1_5->getDataRegistrationState_1_5(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getImsRegistrationState(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getImsRegistrationState(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getNetworkSelectionMode(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getNetworkSelectionMode(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getOperator(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getOperator(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getSignalStrength(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getSignalStrength_1_6(serial);
+ } else {
+ mHal1_5->getSignalStrength_1_4(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getSystemSelectionChannels(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getSystemSelectionChannels(serial);
+ } else {
+ respond()->getSystemSelectionChannelsResponse(notSupported(serial), {});
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getVoiceRadioTechnology(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getVoiceRadioTechnology(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getVoiceRegistrationState(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getVoiceRegistrationState_1_6(serial);
+ } else {
+ mHal1_5->getVoiceRegistrationState_1_5(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::isNrDualConnectivityEnabled(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->isNrDualConnectivityEnabled(serial);
+ } else {
+ respond()->isNrDualConnectivityEnabledResponse(notSupported(serial), false);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setAllowedNetworkTypesBitmap(int32_t serial, int32_t ntype) {
+ LOG_CALL << serial;
+ const auto raf = toHidlBitfield<V1_4::RadioAccessFamily>(ntype);
+ if (mHal1_6) {
+ mHal1_6->setAllowedNetworkTypesBitmap(serial, raf);
+ } else {
+ mHal1_5->setPreferredNetworkType(serial, getNetworkTypeFromRaf(raf));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setBandMode(int32_t serial, aidl::RadioBandMode mode) {
+ LOG_CALL << serial;
+ mHal1_5->setBandMode(serial, V1_0::RadioBandMode(mode));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setBarringPassword(int32_t serial, const std::string& facility,
+ const std::string& oldPw, const std::string& newPw) {
+ LOG_CALL << serial;
+ mHal1_5->setBarringPassword(serial, facility, oldPw, newPw);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setCdmaRoamingPreference(int32_t serial, aidl::CdmaRoamingType type) {
+ LOG_CALL << serial;
+ mHal1_5->setCdmaRoamingPreference(serial, V1_0::CdmaRoamingType(type));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setCellInfoListRate(int32_t serial, int32_t rate) {
+ LOG_CALL << serial;
+ mHal1_5->setCellInfoListRate(serial, rate);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, int32_t indFilter) {
+ LOG_CALL << serial;
+ mHal1_5->setIndicationFilter_1_5(serial, toHidlBitfield<V1_5::IndicationFilter>(indFilter));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setLinkCapacityReportingCriteria( //
+ int32_t serial, int32_t hysteresisMs, int32_t hysteresisDlKbps, int32_t hysteresisUlKbps,
+ const std::vector<int32_t>& thrDownlinkKbps, const std::vector<int32_t>& thrUplinkKbps,
+ AccessNetwork accessNetwork) {
+ LOG_CALL << serial;
+ mHal1_5->setLinkCapacityReportingCriteria_1_5( //
+ serial, hysteresisMs, hysteresisDlKbps, hysteresisUlKbps, thrDownlinkKbps,
+ thrUplinkKbps, V1_5::AccessNetwork(accessNetwork));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setLocationUpdates(int32_t serial, bool enable) {
+ LOG_CALL << serial;
+ mHal1_5->setLocationUpdates(serial, enable);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setNetworkSelectionModeAutomatic(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->setNetworkSelectionModeAutomatic(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setNetworkSelectionModeManual( //
+ int32_t serial, const std::string& opNumeric, AccessNetwork ran) {
+ LOG_CALL << serial;
+ mHal1_5->setNetworkSelectionModeManual_1_5(serial, opNumeric, V1_5::RadioAccessNetworks(ran));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setNrDualConnectivityState(int32_t serial,
+ aidl::NrDualConnectivityState st) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->setNrDualConnectivityState(serial, V1_6::NrDualConnectivityState(st));
+ } else {
+ respond()->setNrDualConnectivityStateResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioNetworkResponse>& response,
+ const std::shared_ptr<aidl::IRadioNetworkIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setSignalStrengthReportingCriteria(
+ int32_t serial, const std::vector<aidl::SignalThresholdInfo>& infos) {
+ LOG_CALL << serial;
+ if (infos.size() == 0) {
+ LOG(ERROR) << "Threshold info array is empty - dropping setSignalStrengthReportingCriteria";
+ return ok();
+ }
+ if (infos.size() > 1) {
+ LOG(WARNING) << "Multi-element reporting criteria are not supported with HIDL HAL";
+ }
+ mHal1_5->setSignalStrengthReportingCriteria_1_5(serial, toHidl(infos[0]),
+ V1_5::AccessNetwork(infos[0].ran));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setSuppServiceNotifications(int32_t serial, bool enable) {
+ LOG_CALL << serial;
+ mHal1_5->setSuppServiceNotifications(serial, enable);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setSystemSelectionChannels( //
+ int32_t serial, bool specifyCh, const std::vector<aidl::RadioAccessSpecifier>& specifiers) {
+ LOG_CALL << serial;
+ mHal1_5->setSystemSelectionChannels_1_5(serial, specifyCh, toHidl(specifiers));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::startNetworkScan(int32_t serial, const aidl::NetworkScanRequest& req) {
+ LOG_CALL << serial;
+ mHal1_5->startNetworkScan_1_5(serial, toHidl(req));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::stopNetworkScan(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->stopNetworkScan(serial);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::supplyNetworkDepersonalization(int32_t ser, const std::string& nPin) {
+ LOG_CALL << ser;
+ mHal1_5->supplyNetworkDepersonalization(ser, nPin);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setUsageSetting(int32_t serial, aidl::UsageSetting) {
+ LOG_CALL << serial;
+ LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+ respond()->setUsageSettingResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t serial) {
+ LOG_CALL << serial;
+ LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+ respond()->getUsageSettingResponse(notSupported(serial), {}); // {} = neither voice nor data
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
new file mode 100644
index 0000000..5a98eb2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+#include "utils.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "NetworkResponse"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioTechnology;
+using ::aidl::android::hardware::radio::RadioTechnologyFamily;
+namespace aidl = ::aidl::android::hardware::radio::network;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkResponse> netCb) {
+ mNetworkCb = netCb;
+}
+
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioResponse::networkCb() {
+ return mNetworkCb.get();
+}
+
+Return<void> RadioResponse::getAllowedNetworkTypesBitmapResponse(
+ const V1_6::RadioResponseInfo& info,
+ hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) {
+ LOG_CALL << info.serial;
+ networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), networkTypeBitmap);
+ return {};
+}
+
+Return<void> RadioResponse::getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::PreferredNetworkType nwType) {
+ LOG_CALL << info.serial;
+ networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), getRafFromNetworkType(nwType));
+ return {};
+}
+
+Return<void> RadioResponse::getPreferredNetworkTypeBitmapResponse(
+ const V1_0::RadioResponseInfo& info, hidl_bitfield<V1_4::RadioAccessFamily>) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getAvailableBandModesResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::RadioBandMode>& bandModes) {
+ LOG_CALL << info.serial;
+ networkCb()->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
+ return {};
+}
+
+Return<void> RadioResponse::getAvailableNetworksResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::OperatorInfo>& networkInfos) {
+ LOG_CALL << info.serial;
+ networkCb()->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
+ return {};
+}
+
+Return<void> RadioResponse::getBarringInfoResponse(
+ const V1_0::RadioResponseInfo& info, const V1_5::CellIdentity& cellIdentity,
+ const hidl_vec<V1_5::BarringInfo>& barringInfos) {
+ LOG_CALL << info.serial;
+ networkCb()->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
+ return {};
+}
+
+Return<void> RadioResponse::getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::CdmaRoamingType type) {
+ LOG_CALL << info.serial;
+ networkCb()->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
+ return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::CellInfo>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_2::CellInfo>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_4::CellInfo>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_5::CellInfo>& cellInfo) {
+ LOG_CALL << info.serial;
+ networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+ return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::CellInfo>& cellInfo) {
+ LOG_CALL << info.serial;
+ networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+ return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::DataRegStateResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_2(
+ const V1_0::RadioResponseInfo& info, const V1_2::DataRegStateResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_4(
+ const V1_0::RadioResponseInfo& info, const V1_4::DataRegStateResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_5(
+ const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& dataRegResponse) {
+ LOG_CALL << info.serial;
+ networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+ return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_6(
+ const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& dataRegResponse) {
+ LOG_CALL << info.serial;
+ networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+ return {};
+}
+
+Return<void> RadioResponse::getImsRegistrationStateResponse( //
+ const V1_0::RadioResponseInfo& info, bool isRegd, V1_0::RadioTechnologyFamily ratFamily) {
+ LOG_CALL << info.serial;
+ networkCb()->getImsRegistrationStateResponse(toAidl(info), isRegd,
+ RadioTechnologyFamily(ratFamily));
+ return {};
+}
+
+Return<void> RadioResponse::getNeighboringCidsResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::NeighboringCell>&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "getNeighboringCidsResponse is not supposed to be called";
+ return {};
+}
+
+Return<void> RadioResponse::getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
+ bool manual) {
+ LOG_CALL << info.serial;
+ networkCb()->getNetworkSelectionModeResponse(toAidl(info), manual);
+ return {};
+}
+
+Return<void> RadioResponse::getOperatorResponse( //
+ const V1_0::RadioResponseInfo& info, const hidl_string& longName,
+ const hidl_string& shortName, const hidl_string& numeric) {
+ LOG_CALL << info.serial;
+ networkCb()->getOperatorResponse(toAidl(info), longName, shortName, numeric);
+ return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::SignalStrength&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const V1_2::SignalStrength&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_4(
+ const V1_0::RadioResponseInfo& info, const V1_4::SignalStrength& signalStrength) {
+ LOG_CALL << info.serial;
+ networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+ return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_6(
+ const V1_6::RadioResponseInfo& info, const V1_6::SignalStrength& signalStrength) {
+ LOG_CALL << info.serial;
+ networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+ return {};
+}
+
+Return<void> RadioResponse::getSystemSelectionChannelsResponse(
+ const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) {
+ LOG_CALL << info.serial;
+ networkCb()->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
+ return {};
+}
+
+Return<void> RadioResponse::getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::RadioTechnology rat) {
+ LOG_CALL << info.serial;
+ networkCb()->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
+ return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::VoiceRegStateResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.0 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_2(
+ const V1_0::RadioResponseInfo& info, const V1_2::VoiceRegStateResult&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.2 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_5(
+ const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& voiceRegResponse) {
+ LOG_CALL << info.serial;
+ networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+ return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_6(
+ const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& voiceRegResponse) {
+ LOG_CALL << info.serial;
+ networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+ return {};
+}
+
+Return<void> RadioResponse::isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
+ bool isEnabled) {
+ LOG_CALL << info.serial;
+ networkCb()->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
+ return {};
+}
+
+Return<void> RadioResponse::pullLceDataResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceDataInfo&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "pullLceDataResponse is not supposed to be called";
+ return {};
+}
+
+Return<void> RadioResponse::setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& i) {
+ LOG_CALL << i.serial;
+ networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(i));
+ return {};
+}
+
+Return<void> RadioResponse::setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setPreferredNetworkTypeBitmapResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "IRadio HAL 1.4 not supported";
+ return {};
+}
+
+Return<void> RadioResponse::setBandModeResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setBandModeResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setBarringPasswordResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setCdmaRoamingPreferenceResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setCellInfoListRateResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setIndicationFilterResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setIndicationFilterResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse_1_5(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setLocationUpdatesResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeAutomaticResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setNetworkSelectionModeAutomaticResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeManualResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeManualResponse_1_5(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setNrDualConnectivityStateResponse(
+ const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setNrDualConnectivityStateResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse_1_5(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSuppServiceNotificationsResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setSuppServiceNotificationsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSystemSelectionChannelsResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSystemSelectionChannelsResponse_1_5(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->startNetworkScanResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->startNetworkScanResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->startNetworkScanResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ networkCb()->stopNetworkScanResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::supplyNetworkDepersonalizationResponse(
+ const V1_0::RadioResponseInfo& info, int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ networkCb()->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::startLceServiceResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceStatusInfo&) {
+ LOG_CALL << info.serial;
+ LOG(WARNING) << "startLceServiceResponse is deprecated";
+ return {};
+}
+
+Return<void> RadioResponse::stopLceServiceResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::LceStatusInfo&) {
+ LOG_CALL << info.serial;
+ LOG(WARNING) << "stopLceServiceResponse is deprecated";
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/structs.cpp b/radio/aidl/compat/libradiocompat/network/structs.cpp
new file mode 100644
index 0000000..c1d9b35
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/structs.cpp
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::network;
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::aidl::android::hardware::radio::RadioTechnology;
+
+aidl::RadioBandMode toAidl(V1_0::RadioBandMode mode) {
+ return aidl::RadioBandMode(mode);
+}
+
+aidl::GeranBands toAidl(V1_1::GeranBands band) {
+ return aidl::GeranBands(band);
+}
+
+V1_1::GeranBands toHidl(aidl::GeranBands band) {
+ return V1_1::GeranBands(band);
+}
+
+aidl::UtranBands toAidl(V1_5::UtranBands band) {
+ return aidl::UtranBands(band);
+}
+
+V1_5::UtranBands toHidl(aidl::UtranBands band) {
+ return V1_5::UtranBands(band);
+}
+
+aidl::EutranBands toAidl(V1_5::EutranBands band) {
+ return aidl::EutranBands(band);
+}
+
+V1_5::EutranBands toHidl(aidl::EutranBands band) {
+ return V1_5::EutranBands(band);
+}
+
+aidl::NgranBands toAidl(V1_5::NgranBands band) {
+ return aidl::NgranBands(band);
+}
+
+V1_5::NgranBands toHidl(aidl::NgranBands band) {
+ return V1_5::NgranBands(band);
+}
+
+V1_5::SignalThresholdInfo toHidl(const aidl::SignalThresholdInfo& info) {
+ return {
+ .signalMeasurement = V1_5::SignalMeasurementType{info.signalMeasurement},
+ .hysteresisMs = info.hysteresisMs,
+ .hysteresisDb = info.hysteresisDb,
+ .thresholds = info.thresholds,
+ .isEnabled = info.isEnabled,
+ };
+}
+
+static aidl::RadioAccessSpecifierBands toAidl(const V1_5::RadioAccessSpecifier::Bands& bands) {
+ using Discr = V1_5::RadioAccessSpecifier::Bands::hidl_discriminator;
+ const auto discr = bands.getDiscriminator();
+
+ if (discr == Discr::geranBands) return toAidl(bands.geranBands());
+ if (discr == Discr::utranBands) return toAidl(bands.utranBands());
+ if (discr == Discr::eutranBands) return toAidl(bands.eutranBands());
+ if (discr == Discr::ngranBands) return toAidl(bands.ngranBands());
+
+ return {};
+}
+
+static V1_5::RadioAccessSpecifier::Bands toHidl(const aidl::RadioAccessSpecifierBands& bands) {
+ V1_5::RadioAccessSpecifier::Bands hidl;
+ using Tag = aidl::RadioAccessSpecifierBands::Tag;
+
+ if (bands.getTag() == Tag::geranBands) hidl.geranBands(toHidl(bands.get<Tag::geranBands>()));
+ if (bands.getTag() == Tag::utranBands) hidl.utranBands(toHidl(bands.get<Tag::utranBands>()));
+ if (bands.getTag() == Tag::eutranBands) hidl.eutranBands(toHidl(bands.get<Tag::eutranBands>()));
+ if (bands.getTag() == Tag::ngranBands) hidl.ngranBands(toHidl(bands.get<Tag::ngranBands>()));
+
+ return hidl;
+}
+
+aidl::RadioAccessSpecifier toAidl(const V1_5::RadioAccessSpecifier& spec) {
+ return {
+ .accessNetwork = AccessNetwork(spec.radioAccessNetwork),
+ .bands = toAidl(spec.bands),
+ .channels = spec.channels,
+ };
+}
+
+V1_5::RadioAccessSpecifier toHidl(const aidl::RadioAccessSpecifier& spec) {
+ return {
+ .radioAccessNetwork = V1_5::RadioAccessNetworks{spec.accessNetwork},
+ .bands = toHidl(spec.bands),
+ .channels = spec.channels,
+ };
+}
+
+V1_5::NetworkScanRequest toHidl(const aidl::NetworkScanRequest& req) {
+ return {
+ .type = V1_1::ScanType{req.type},
+ .interval = req.interval,
+ .specifiers = toHidl(req.specifiers),
+ .maxSearchTime = req.maxSearchTime,
+ .incrementalResults = req.incrementalResults,
+ .incrementalResultsPeriodicity = req.incrementalResultsPeriodicity,
+ .mccMncs = toHidl(req.mccMncs),
+ };
+}
+
+static aidl::OperatorInfo toAidl(const V1_2::CellIdentityOperatorNames& names) {
+ return {
+ .alphaLong = names.alphaLong,
+ .alphaShort = names.alphaShort,
+ .operatorNumeric = "",
+ .status = aidl::OperatorInfo::STATUS_UNKNOWN,
+ };
+}
+
+static aidl::CellIdentityGsm toAidl(const V1_5::CellIdentityGsm& ci) {
+ return {
+ .mcc = ci.base.base.mcc,
+ .mnc = ci.base.base.mnc,
+ .lac = ci.base.base.lac,
+ .cid = ci.base.base.cid,
+ .arfcn = ci.base.base.arfcn,
+ .bsic = static_cast<int8_t>(ci.base.base.bsic),
+ .operatorNames = toAidl(ci.base.operatorNames),
+ .additionalPlmns = toAidl(ci.additionalPlmns),
+ };
+}
+
+aidl::ClosedSubscriberGroupInfo toAidl(const V1_5::ClosedSubscriberGroupInfo& info) {
+ return {
+ .csgIndication = info.csgIndication,
+ .homeNodebName = info.homeNodebName,
+ .csgIdentity = info.csgIdentity,
+ };
+}
+
+static std::optional<aidl::ClosedSubscriberGroupInfo> toAidl(const V1_5::OptionalCsgInfo& opt) {
+ using descr = V1_5::OptionalCsgInfo::hidl_discriminator;
+ if (opt.getDiscriminator() == descr::noinit) return std::nullopt;
+ return toAidl(opt.csgInfo());
+}
+
+static aidl::CellIdentityWcdma toAidl(const V1_5::CellIdentityWcdma& ci) {
+ return {
+ .mcc = ci.base.base.mcc,
+ .mnc = ci.base.base.mnc,
+ .lac = ci.base.base.lac,
+ .cid = ci.base.base.cid,
+ .psc = ci.base.base.psc,
+ .uarfcn = ci.base.base.uarfcn,
+ .operatorNames = toAidl(ci.base.operatorNames),
+ .additionalPlmns = toAidl(ci.additionalPlmns),
+ .csgInfo = toAidl(ci.optionalCsgInfo),
+ };
+}
+
+static aidl::CellIdentityTdscdma toAidl(const V1_5::CellIdentityTdscdma& ci) {
+ return {
+ .mcc = ci.base.base.mcc,
+ .mnc = ci.base.base.mnc,
+ .lac = ci.base.base.lac,
+ .cid = ci.base.base.cid,
+ .cpid = ci.base.base.cpid,
+ .uarfcn = ci.base.uarfcn,
+ .operatorNames = toAidl(ci.base.operatorNames),
+ .additionalPlmns = toAidl(ci.additionalPlmns),
+ .csgInfo = toAidl(ci.optionalCsgInfo),
+ };
+}
+
+static aidl::CellIdentityCdma toAidl(const V1_2::CellIdentityCdma& ci) {
+ return {
+ .networkId = ci.base.networkId,
+ .systemId = ci.base.systemId,
+ .baseStationId = ci.base.baseStationId,
+ .longitude = ci.base.longitude,
+ .latitude = ci.base.latitude,
+ .operatorNames = toAidl(ci.operatorNames),
+ };
+}
+
+static aidl::CellIdentityLte toAidl(const V1_5::CellIdentityLte& ci) {
+ return {
+ .mcc = ci.base.base.mcc,
+ .mnc = ci.base.base.mnc,
+ .ci = ci.base.base.ci,
+ .pci = ci.base.base.pci,
+ .tac = ci.base.base.tac,
+ .earfcn = ci.base.base.earfcn,
+ .operatorNames = toAidl(ci.base.operatorNames),
+ .bandwidth = ci.base.bandwidth,
+ .additionalPlmns = toAidl(ci.additionalPlmns),
+ .csgInfo = toAidl(ci.optionalCsgInfo),
+ .bands = toAidl(ci.bands),
+ };
+}
+
+static aidl::CellIdentityNr toAidl(const V1_5::CellIdentityNr& ci) {
+ return {
+ .mcc = ci.base.mcc,
+ .mnc = ci.base.mnc,
+ .nci = static_cast<int64_t>(ci.base.nci),
+ .pci = static_cast<int32_t>(ci.base.pci),
+ .tac = ci.base.tac,
+ .nrarfcn = ci.base.nrarfcn,
+ .operatorNames = toAidl(ci.base.operatorNames),
+ .additionalPlmns = toAidl(ci.additionalPlmns),
+ .bands = toAidl(ci.bands),
+ };
+}
+
+aidl::CellIdentity toAidl(const V1_5::CellIdentity& ci) {
+ using Discr = V1_5::CellIdentity::hidl_discriminator;
+ const auto discr = ci.getDiscriminator();
+
+ if (discr == Discr::gsm) return toAidl(ci.gsm());
+ if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+ if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+ if (discr == Discr::cdma) return toAidl(ci.cdma());
+ if (discr == Discr::lte) return toAidl(ci.lte());
+ if (discr == Discr::nr) return toAidl(ci.nr());
+
+ return {};
+}
+
+static std::optional<aidl::BarringTypeSpecificInfo> //
+toAidl(const V1_5::BarringInfo::BarringTypeSpecificInfo& opt) {
+ using discr = V1_5::BarringInfo::BarringTypeSpecificInfo::hidl_discriminator;
+ if (opt.getDiscriminator() == discr::noinit) return std::nullopt;
+
+ const auto& info = opt.conditional();
+ return aidl::BarringTypeSpecificInfo{
+ .factor = info.factor,
+ .timeSeconds = info.timeSeconds,
+ .isBarred = info.isBarred,
+ };
+}
+
+aidl::BarringInfo toAidl(const V1_5::BarringInfo& info) {
+ return {
+ .serviceType = static_cast<int32_t>(info.serviceType),
+ .barringType = static_cast<int32_t>(info.barringType),
+ .barringTypeSpecificInfo = toAidl(info.barringTypeSpecificInfo),
+ };
+}
+
+static aidl::GsmSignalStrength toAidl(const V1_0::GsmSignalStrength& sig) {
+ return {
+ .signalStrength = static_cast<int32_t>(sig.signalStrength),
+ .bitErrorRate = static_cast<int32_t>(sig.bitErrorRate),
+ .timingAdvance = sig.timingAdvance,
+ };
+}
+
+static aidl::CellInfoGsm toAidl(const V1_5::CellInfoGsm& info) {
+ return {
+ .cellIdentityGsm = toAidl(info.cellIdentityGsm),
+ .signalStrengthGsm = toAidl(info.signalStrengthGsm),
+ };
+}
+
+static aidl::WcdmaSignalStrength toAidl(const V1_2::WcdmaSignalStrength& sig) {
+ return {
+ .signalStrength = sig.base.signalStrength,
+ .bitErrorRate = sig.base.bitErrorRate,
+ .rscp = static_cast<int32_t>(sig.rscp),
+ .ecno = static_cast<int32_t>(sig.ecno),
+ };
+}
+
+static aidl::CellInfoWcdma toAidl(const V1_5::CellInfoWcdma& info) {
+ return {
+ .cellIdentityWcdma = toAidl(info.cellIdentityWcdma),
+ .signalStrengthWcdma = toAidl(info.signalStrengthWcdma),
+ };
+}
+
+static aidl::TdscdmaSignalStrength toAidl(const V1_2::TdscdmaSignalStrength& sig) {
+ return {
+ .signalStrength = static_cast<int32_t>(sig.signalStrength),
+ .bitErrorRate = static_cast<int32_t>(sig.bitErrorRate),
+ .rscp = static_cast<int32_t>(sig.rscp),
+ };
+}
+
+static aidl::CellInfoTdscdma toAidl(const V1_5::CellInfoTdscdma& info) {
+ return {
+ .cellIdentityTdscdma = toAidl(info.cellIdentityTdscdma),
+ .signalStrengthTdscdma = toAidl(info.signalStrengthTdscdma),
+ };
+}
+
+static aidl::LteSignalStrength toAidl(const V1_6::LteSignalStrength& sig) {
+ return {
+ .signalStrength = static_cast<int32_t>(sig.base.signalStrength),
+ .rsrp = static_cast<int32_t>(sig.base.rsrp),
+ .rsrq = static_cast<int32_t>(sig.base.rsrq),
+ .rssnr = sig.base.rssnr,
+ .cqi = static_cast<int32_t>(sig.base.cqi),
+ .timingAdvance = static_cast<int32_t>(sig.base.timingAdvance),
+ .cqiTableIndex = static_cast<int32_t>(sig.cqiTableIndex),
+ };
+}
+
+static aidl::LteSignalStrength toAidl(const V1_0::LteSignalStrength& sig) {
+ return toAidl({sig, 0});
+}
+
+static aidl::CellInfoLte toAidl(const V1_5::CellInfoLte& info) {
+ return {
+ .cellIdentityLte = toAidl(info.cellIdentityLte),
+ .signalStrengthLte = toAidl(info.signalStrengthLte),
+ };
+}
+
+static aidl::CellInfoLte toAidl(const V1_6::CellInfoLte& info) {
+ return {
+ .cellIdentityLte = toAidl(info.cellIdentityLte),
+ .signalStrengthLte = toAidl(info.signalStrengthLte),
+ };
+}
+
+static aidl::NrSignalStrength toAidl(const V1_6::NrSignalStrength& sig) {
+ return {
+ .ssRsrp = sig.base.ssRsrp,
+ .ssRsrq = sig.base.ssRsrq,
+ .ssSinr = sig.base.ssSinr,
+ .csiRsrp = sig.base.csiRsrp,
+ .csiRsrq = sig.base.csiRsrq,
+ .csiSinr = sig.base.csiSinr,
+ .csiCqiTableIndex = static_cast<int32_t>(sig.csiCqiTableIndex),
+ .csiCqiReport = sig.csiCqiReport,
+ };
+}
+
+static aidl::NrSignalStrength toAidl(const V1_4::NrSignalStrength& sig) {
+ return toAidl({sig, 0, 0});
+}
+
+static aidl::CellInfoNr toAidl(const V1_5::CellInfoNr& info) {
+ return {
+ .cellIdentityNr = toAidl(info.cellIdentityNr),
+ .signalStrengthNr = toAidl(info.signalStrengthNr),
+ };
+}
+
+static aidl::CellInfoNr toAidl(const V1_6::CellInfoNr& info) {
+ return {
+ .cellIdentityNr = toAidl(info.cellIdentityNr),
+ .signalStrengthNr = toAidl(info.signalStrengthNr),
+ };
+}
+
+static aidl::CdmaSignalStrength toAidl(const V1_0::CdmaSignalStrength& sig) {
+ return {
+ .dbm = static_cast<int32_t>(sig.dbm),
+ .ecio = static_cast<int32_t>(sig.ecio),
+ };
+}
+
+static aidl::EvdoSignalStrength toAidl(const V1_0::EvdoSignalStrength& sig) {
+ return {
+ .dbm = static_cast<int32_t>(sig.dbm),
+ .ecio = static_cast<int32_t>(sig.ecio),
+ .signalNoiseRatio = static_cast<int32_t>(sig.signalNoiseRatio),
+ };
+}
+
+static aidl::CellInfoCdma toAidl(const V1_2::CellInfoCdma& info) {
+ return {
+ .cellIdentityCdma = toAidl(info.cellIdentityCdma),
+ .signalStrengthCdma = toAidl(info.signalStrengthCdma),
+ .signalStrengthEvdo = toAidl(info.signalStrengthEvdo),
+ };
+}
+
+static aidl::CellInfoRatSpecificInfo toAidl(const V1_5::CellInfo::CellInfoRatSpecificInfo& ci) {
+ using Discr = V1_5::CellInfo::CellInfoRatSpecificInfo::hidl_discriminator;
+ const auto discr = ci.getDiscriminator();
+
+ if (discr == Discr::gsm) return toAidl(ci.gsm());
+ if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+ if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+ if (discr == Discr::lte) return toAidl(ci.lte());
+ if (discr == Discr::nr) return toAidl(ci.nr());
+ if (discr == Discr::cdma) return toAidl(ci.cdma());
+
+ return {};
+}
+
+static aidl::CellInfoRatSpecificInfo toAidl(const V1_6::CellInfo::CellInfoRatSpecificInfo& ci) {
+ using Discr = V1_6::CellInfo::CellInfoRatSpecificInfo::hidl_discriminator;
+ const auto discr = ci.getDiscriminator();
+
+ if (discr == Discr::gsm) return toAidl(ci.gsm());
+ if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+ if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+ if (discr == Discr::lte) return toAidl(ci.lte());
+ if (discr == Discr::nr) return toAidl(ci.nr());
+ if (discr == Discr::cdma) return toAidl(ci.cdma());
+
+ return {};
+}
+
+aidl::CellInfo toAidl(const V1_5::CellInfo& info) {
+ return {
+ .registered = info.registered,
+ // ignored: timeStampType and timeStamp
+ .connectionStatus = aidl::CellConnectionStatus(info.connectionStatus),
+ .ratSpecificInfo = toAidl(info.ratSpecificInfo),
+ };
+}
+
+aidl::CellInfo toAidl(const V1_6::CellInfo& info) {
+ return {
+ .registered = info.registered,
+ .connectionStatus = aidl::CellConnectionStatus(info.connectionStatus),
+ .ratSpecificInfo = toAidl(info.ratSpecificInfo),
+ };
+}
+
+aidl::LinkCapacityEstimate toAidl(const V1_2::LinkCapacityEstimate& e) {
+ return {
+ .downlinkCapacityKbps = static_cast<int32_t>(e.downlinkCapacityKbps),
+ .uplinkCapacityKbps = static_cast<int32_t>(e.uplinkCapacityKbps),
+ };
+}
+
+aidl::LinkCapacityEstimate toAidl(const V1_6::LinkCapacityEstimate& e) {
+ return {
+ .downlinkCapacityKbps = static_cast<int32_t>(e.downlinkCapacityKbps),
+ .uplinkCapacityKbps = static_cast<int32_t>(e.uplinkCapacityKbps),
+ .secondaryDownlinkCapacityKbps = static_cast<int32_t>(e.secondaryDownlinkCapacityKbps),
+ .secondaryUplinkCapacityKbps = static_cast<int32_t>(e.secondaryUplinkCapacityKbps),
+ };
+}
+
+static aidl::PhysicalChannelConfigBand toAidl(const V1_6::PhysicalChannelConfig::Band& band) {
+ using Discr = V1_6::PhysicalChannelConfig::Band::hidl_discriminator;
+ const auto discr = band.getDiscriminator();
+
+ if (discr == Discr::geranBand) return aidl::GeranBands(band.geranBand());
+ if (discr == Discr::utranBand) return aidl::UtranBands(band.utranBand());
+ if (discr == Discr::eutranBand) return aidl::EutranBands(band.eutranBand());
+ if (discr == Discr::ngranBand) return aidl::NgranBands(band.ngranBand());
+
+ return {};
+}
+
+aidl::PhysicalChannelConfig toAidl(const V1_4::PhysicalChannelConfig& cfg) {
+ int32_t downlinkChannelNumber = 0;
+ // ignored rfInfo.range
+ using Discr = V1_4::RadioFrequencyInfo::hidl_discriminator;
+ if (cfg.rfInfo.getDiscriminator() == Discr::channelNumber) {
+ downlinkChannelNumber = cfg.rfInfo.channelNumber();
+ }
+
+ return {
+ .status = aidl::CellConnectionStatus(cfg.base.status),
+ .rat = RadioTechnology(cfg.rat),
+ .downlinkChannelNumber = downlinkChannelNumber,
+ .cellBandwidthDownlinkKhz = cfg.base.cellBandwidthDownlink,
+ .contextIds = cfg.contextIds,
+ .physicalCellId = static_cast<int32_t>(cfg.physicalCellId),
+ };
+}
+
+aidl::PhysicalChannelConfig toAidl(const V1_6::PhysicalChannelConfig& cfg) {
+ return {
+ .status = aidl::CellConnectionStatus(cfg.status),
+ .rat = RadioTechnology(cfg.rat),
+ .downlinkChannelNumber = cfg.downlinkChannelNumber,
+ .uplinkChannelNumber = cfg.uplinkChannelNumber,
+ .cellBandwidthDownlinkKhz = cfg.cellBandwidthDownlinkKhz,
+ .cellBandwidthUplinkKhz = cfg.cellBandwidthUplinkKhz,
+ .contextIds = cfg.contextIds,
+ .physicalCellId = static_cast<int32_t>(cfg.physicalCellId),
+ .band = toAidl(cfg.band),
+ };
+}
+
+aidl::SignalStrength toAidl(const V1_4::SignalStrength& sig) {
+ return {
+ .gsm = toAidl(sig.gsm),
+ .cdma = toAidl(sig.cdma),
+ .evdo = toAidl(sig.evdo),
+ .lte = toAidl(sig.lte),
+ .tdscdma = toAidl(sig.tdscdma),
+ .wcdma = toAidl(sig.wcdma),
+ .nr = toAidl(sig.nr),
+ };
+}
+
+aidl::SignalStrength toAidl(const V1_6::SignalStrength& sig) {
+ return {
+ .gsm = toAidl(sig.gsm),
+ .cdma = toAidl(sig.cdma),
+ .evdo = toAidl(sig.evdo),
+ .lte = toAidl(sig.lte),
+ .tdscdma = toAidl(sig.tdscdma),
+ .wcdma = toAidl(sig.wcdma),
+ .nr = toAidl(sig.nr),
+ };
+}
+
+aidl::NetworkScanResult toAidl(const V1_5::NetworkScanResult& res) {
+ return {
+ .status = static_cast<int32_t>(res.status),
+ .error = toAidl(res.error),
+ .networkInfos = toAidl(res.networkInfos),
+ };
+}
+
+aidl::NetworkScanResult toAidl(const V1_6::NetworkScanResult& res) {
+ return {
+ .status = static_cast<int32_t>(res.status),
+ .error = toAidl(res.error),
+ .networkInfos = toAidl(res.networkInfos),
+ };
+}
+
+aidl::SuppSvcNotification toAidl(const V1_0::SuppSvcNotification& svc) {
+ return {
+ .isMT = svc.isMT,
+ .code = svc.code,
+ .index = svc.index,
+ .type = svc.type,
+ .number = svc.number,
+ };
+}
+
+aidl::OperatorInfo toAidl(const V1_0::OperatorInfo& info) {
+ return {
+ .alphaLong = info.alphaLong,
+ .alphaShort = info.alphaShort,
+ .operatorNumeric = info.operatorNumeric,
+ .status = static_cast<int32_t>(info.status),
+ };
+}
+
+static aidl::Cdma2000RegistrationInfo //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo::Cdma2000RegistrationInfo& info) {
+ return {
+ .cssSupported = info.cssSupported,
+ .roamingIndicator = info.roamingIndicator,
+ .systemIsInPrl = static_cast<int32_t>(info.systemIsInPrl),
+ .defaultRoamingIndicator = info.defaultRoamingIndicator,
+ };
+}
+
+static aidl::LteVopsInfo toAidl(const V1_4::LteVopsInfo& info) {
+ return {
+ .isVopsSupported = info.isVopsSupported,
+ .isEmcBearerSupported = info.isEmcBearerSupported,
+ };
+}
+
+static aidl::NrIndicators toAidl(const V1_4::NrIndicators& info) {
+ return {
+ .isEndcAvailable = info.isEndcAvailable,
+ .isDcNrRestricted = info.isDcNrRestricted,
+ .isNrAvailable = info.isNrAvailable,
+ };
+}
+
+static aidl::EutranRegistrationInfo //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo::EutranRegistrationInfo& info) {
+ return {
+ .lteVopsInfo = toAidl(info.lteVopsInfo),
+ .nrIndicators = toAidl(info.nrIndicators),
+ };
+}
+
+static aidl::NrVopsInfo toAidl(const V1_6::NrVopsInfo& info) {
+ return {
+ .vopsSupported = static_cast<int8_t>(info.vopsSupported),
+ .emcSupported = static_cast<int8_t>(info.emcSupported),
+ .emfSupported = static_cast<int8_t>(info.emfSupported),
+ };
+}
+
+static aidl::AccessTechnologySpecificInfo //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo& info) {
+ using Discr = V1_5::RegStateResult::AccessTechnologySpecificInfo::hidl_discriminator;
+ const auto discr = info.getDiscriminator();
+
+ if (discr == Discr::cdmaInfo) return toAidl(info.cdmaInfo());
+ if (discr == Discr::eutranInfo) return toAidl(info.eutranInfo());
+
+ return {};
+}
+
+static aidl::AccessTechnologySpecificInfo //
+toAidl(const V1_6::RegStateResult::AccessTechnologySpecificInfo& info) {
+ using Discr = V1_6::RegStateResult::AccessTechnologySpecificInfo::hidl_discriminator;
+ const auto discr = info.getDiscriminator();
+
+ if (discr == Discr::cdmaInfo) return toAidl(info.cdmaInfo());
+ if (discr == Discr::eutranInfo) return toAidl(info.eutranInfo());
+ if (discr == Discr::ngranNrVopsInfo) return toAidl(info.ngranNrVopsInfo());
+ if (discr == Discr::geranDtmSupported) {
+ using T = aidl::AccessTechnologySpecificInfo;
+ return T::make<T::Tag::geranDtmSupported>(info.geranDtmSupported());
+ }
+
+ return {};
+}
+
+aidl::RegStateResult toAidl(const V1_5::RegStateResult& res) {
+ return {
+ .regState = aidl::RegState(res.regState),
+ .rat = RadioTechnology(res.rat),
+ .reasonForDenial = aidl::RegistrationFailCause(res.reasonForDenial),
+ .cellIdentity = toAidl(res.cellIdentity),
+ .registeredPlmn = res.registeredPlmn,
+ .accessTechnologySpecificInfo = toAidl(res.accessTechnologySpecificInfo),
+ };
+}
+
+aidl::RegStateResult toAidl(const V1_6::RegStateResult& res) {
+ return {
+ .regState = aidl::RegState(res.regState),
+ .rat = RadioTechnology(res.rat),
+ .reasonForDenial = aidl::RegistrationFailCause(res.reasonForDenial),
+ .cellIdentity = toAidl(res.cellIdentity),
+ .registeredPlmn = res.registeredPlmn,
+ .accessTechnologySpecificInfo = toAidl(res.accessTechnologySpecificInfo),
+ };
+}
+
+aidl::LceDataInfo toAidl(const V1_0::LceDataInfo& info) {
+ return {
+ .lastHopCapacityKbps = static_cast<int32_t>(info.lastHopCapacityKbps),
+ .confidenceLevel = static_cast<int8_t>(info.confidenceLevel),
+ .lceSuspended = info.lceSuspended,
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/structs.h b/radio/aidl/compat/libradiocompat/network/structs.h
new file mode 100644
index 0000000..aaa49a0
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/structs.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/network/BarringInfo.h>
+#include <aidl/android/hardware/radio/network/CellIdentity.h>
+#include <aidl/android/hardware/radio/network/CellInfo.h>
+#include <aidl/android/hardware/radio/network/LceDataInfo.h>
+#include <aidl/android/hardware/radio/network/LinkCapacityEstimate.h>
+#include <aidl/android/hardware/radio/network/NetworkScanRequest.h>
+#include <aidl/android/hardware/radio/network/NetworkScanResult.h>
+#include <aidl/android/hardware/radio/network/OperatorInfo.h>
+#include <aidl/android/hardware/radio/network/PhysicalChannelConfig.h>
+#include <aidl/android/hardware/radio/network/RadioAccessSpecifier.h>
+#include <aidl/android/hardware/radio/network/RadioBandMode.h>
+#include <aidl/android/hardware/radio/network/RegStateResult.h>
+#include <aidl/android/hardware/radio/network/SignalStrength.h>
+#include <aidl/android/hardware/radio/network/SignalThresholdInfo.h>
+#include <aidl/android/hardware/radio/network/SuppSvcNotification.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+::aidl::android::hardware::radio::network::RadioBandMode toAidl(V1_0::RadioBandMode mode);
+::aidl::android::hardware::radio::network::GeranBands toAidl(V1_1::GeranBands band);
+V1_1::GeranBands toHidl(::aidl::android::hardware::radio::network::GeranBands band);
+::aidl::android::hardware::radio::network::UtranBands toAidl(V1_5::UtranBands band);
+V1_5::UtranBands toHidl(::aidl::android::hardware::radio::network::UtranBands band);
+::aidl::android::hardware::radio::network::EutranBands toAidl(V1_5::EutranBands band);
+V1_5::EutranBands toHidl(::aidl::android::hardware::radio::network::EutranBands band);
+::aidl::android::hardware::radio::network::NgranBands toAidl(V1_5::NgranBands band);
+V1_5::NgranBands toHidl(::aidl::android::hardware::radio::network::NgranBands band);
+
+V1_5::SignalThresholdInfo //
+toHidl(const ::aidl::android::hardware::radio::network::SignalThresholdInfo& info);
+
+::aidl::android::hardware::radio::network::RadioAccessSpecifier //
+toAidl(const V1_5::RadioAccessSpecifier& spec);
+V1_5::RadioAccessSpecifier //
+toHidl(const ::aidl::android::hardware::radio::network::RadioAccessSpecifier& spec);
+
+V1_5::NetworkScanRequest //
+toHidl(const ::aidl::android::hardware::radio::network::NetworkScanRequest& req);
+
+::aidl::android::hardware::radio::network::CellIdentity toAidl(const V1_5::CellIdentity& ci);
+
+::aidl::android::hardware::radio::network::BarringInfo toAidl(const V1_5::BarringInfo& info);
+
+::aidl::android::hardware::radio::network::ClosedSubscriberGroupInfo //
+toAidl(const V1_5::ClosedSubscriberGroupInfo& info);
+
+::aidl::android::hardware::radio::network::CellInfo toAidl(const V1_5::CellInfo& info);
+::aidl::android::hardware::radio::network::CellInfo toAidl(const V1_6::CellInfo& info);
+
+::aidl::android::hardware::radio::network::LinkCapacityEstimate //
+toAidl(const V1_2::LinkCapacityEstimate& lce);
+::aidl::android::hardware::radio::network::LinkCapacityEstimate //
+toAidl(const V1_6::LinkCapacityEstimate& lce);
+
+::aidl::android::hardware::radio::network::PhysicalChannelConfig //
+toAidl(const V1_4::PhysicalChannelConfig& cfg);
+::aidl::android::hardware::radio::network::PhysicalChannelConfig //
+toAidl(const V1_6::PhysicalChannelConfig& cfg);
+
+::aidl::android::hardware::radio::network::SignalStrength toAidl(const V1_4::SignalStrength& sig);
+::aidl::android::hardware::radio::network::SignalStrength toAidl(const V1_6::SignalStrength& sig);
+
+::aidl::android::hardware::radio::network::NetworkScanResult //
+toAidl(const V1_5::NetworkScanResult& res);
+::aidl::android::hardware::radio::network::NetworkScanResult //
+toAidl(const V1_6::NetworkScanResult& res);
+
+::aidl::android::hardware::radio::network::SuppSvcNotification //
+toAidl(const V1_0::SuppSvcNotification& svc);
+
+::aidl::android::hardware::radio::network::OperatorInfo toAidl(const V1_0::OperatorInfo& info);
+
+::aidl::android::hardware::radio::network::RegStateResult toAidl(const V1_5::RegStateResult& res);
+::aidl::android::hardware::radio::network::RegStateResult toAidl(const V1_6::RegStateResult& res);
+
+::aidl::android::hardware::radio::network::LceDataInfo toAidl(const V1_0::LceDataInfo& info);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/utils.cpp b/radio/aidl/compat/libradiocompat/network/utils.cpp
new file mode 100644
index 0000000..6fe3e6e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/utils.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "utils.h"
+
+namespace android::hardware::radio::compat {
+
+namespace RAF {
+using E = V1_4::RadioAccessFamily;
+constexpr auto GSM = E::GSM | E::GPRS;
+constexpr auto CDMA = E::IS95A | E::IS95B | E::ONE_X_RTT;
+constexpr auto EVDO = E::EVDO_0 | E::EVDO_A | E::EVDO_B | E::EHRPD;
+constexpr auto HS = E::HSUPA | E::HSDPA | E::HSPA | E::HSPAP;
+constexpr auto WCDMA = HS | E::UMTS;
+constexpr auto LTE = E::LTE | E::LTE_CA;
+constexpr auto NR = E::NR;
+} // namespace RAF
+
+static hidl_bitfield<V1_4::RadioAccessFamily> //
+getAdjustedRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf) {
+ if (raf & RAF::GSM) raf |= RAF::GSM;
+ if (raf & RAF::WCDMA) raf |= RAF::WCDMA;
+ if (raf & RAF::CDMA) raf |= RAF::CDMA;
+ if (raf & RAF::EVDO) raf |= RAF::EVDO;
+ if (raf & RAF::LTE) raf |= RAF::LTE;
+ if (raf & RAF::NR) raf |= RAF::NR;
+
+ return raf;
+}
+
+V1_0::PreferredNetworkType getNetworkTypeFromRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf) {
+ raf = getAdjustedRaf(raf);
+ switch (raf) {
+ case RAF::GSM | RAF::WCDMA:
+ return V1_0::PreferredNetworkType::GSM_WCDMA_AUTO;
+ case RAF::GSM:
+ return V1_0::PreferredNetworkType::GSM_ONLY;
+ case RAF::WCDMA:
+ return V1_0::PreferredNetworkType::WCDMA;
+ case (RAF::CDMA | RAF::EVDO):
+ return V1_0::PreferredNetworkType::CDMA_EVDO_AUTO;
+ case (RAF::LTE | RAF::CDMA | RAF::EVDO):
+ return V1_0::PreferredNetworkType::LTE_CDMA_EVDO;
+ case (RAF::LTE | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::LTE_GSM_WCDMA;
+ case (RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::LTE_CMDA_EVDO_GSM_WCDMA; // CDMA typo
+ case RAF::LTE:
+ return V1_0::PreferredNetworkType::LTE_ONLY;
+ case (RAF::LTE | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::LTE_WCDMA;
+ case RAF::CDMA:
+ return V1_0::PreferredNetworkType::CDMA_ONLY;
+ case RAF::EVDO:
+ return V1_0::PreferredNetworkType::EVDO_ONLY;
+ case (RAF::GSM | RAF::WCDMA | RAF::CDMA | RAF::EVDO):
+ return V1_0::PreferredNetworkType::GSM_WCDMA_CDMA_EVDO_AUTO;
+ case static_cast<int>(RAF::E::TD_SCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_ONLY;
+ case (RAF::E::TD_SCDMA | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_WCDMA;
+ case (RAF::LTE | RAF::E::TD_SCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_LTE;
+ case (RAF::E::TD_SCDMA | RAF::GSM):
+ return V1_0::PreferredNetworkType::TD_SCDMA_GSM;
+ case (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM):
+ return V1_0::PreferredNetworkType::TD_SCDMA_GSM_LTE;
+ case (RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA;
+ case (RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_WCDMA_LTE;
+ case (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_LTE;
+ case (RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO;
+ case (RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType::TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA;
+ case static_cast<int>(RAF::NR):
+ return V1_0::PreferredNetworkType(23); // NR_ONLY
+ case (RAF::NR | RAF::LTE):
+ return V1_0::PreferredNetworkType(24); // NR_LTE
+ case (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO):
+ return V1_0::PreferredNetworkType(25); // NR_LTE_CDMA_EVDO
+ case (RAF::NR | RAF::LTE | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType(26); // NR_LTE_GSM_WCDMA
+ case (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType(27); // NR_LTE_CDMA_EVDO_GSM_WCDMA
+ case (RAF::NR | RAF::LTE | RAF::WCDMA):
+ return V1_0::PreferredNetworkType(28); // NR_LTE_WCDMA
+ case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA):
+ return V1_0::PreferredNetworkType(29); // NR_LTE_TDSCDMA
+ case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM):
+ return V1_0::PreferredNetworkType(30); // NR_LTE_TDSCDMA_GSM
+ case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA):
+ return V1_0::PreferredNetworkType(31); // NR_LTE_TDSCDMA_WCDMA
+ case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+ return V1_0::PreferredNetworkType(32); // NR_LTE_TDSCDMA_GSM_WCDMA
+ case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM |
+ RAF::WCDMA):
+ return V1_0::PreferredNetworkType(33); // NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+ default:
+ return V1_0::PreferredNetworkType::WCDMA;
+ }
+}
+
+hidl_bitfield<V1_4::RadioAccessFamily> getRafFromNetworkType(V1_0::PreferredNetworkType type) {
+ switch (type) {
+ case V1_0::PreferredNetworkType::GSM_WCDMA_AUTO:
+ return RAF::GSM | RAF::WCDMA;
+ case V1_0::PreferredNetworkType::GSM_ONLY:
+ return RAF::GSM;
+ case V1_0::PreferredNetworkType::WCDMA:
+ return RAF::WCDMA;
+ case V1_0::PreferredNetworkType::CDMA_EVDO_AUTO:
+ return (RAF::CDMA | RAF::EVDO);
+ case V1_0::PreferredNetworkType::LTE_CDMA_EVDO:
+ return (RAF::LTE | RAF::CDMA | RAF::EVDO);
+ case V1_0::PreferredNetworkType::LTE_GSM_WCDMA:
+ return (RAF::LTE | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::LTE_CMDA_EVDO_GSM_WCDMA:
+ return (RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::LTE_ONLY:
+ return RAF::LTE;
+ case V1_0::PreferredNetworkType::LTE_WCDMA:
+ return (RAF::LTE | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::CDMA_ONLY:
+ return RAF::CDMA;
+ case V1_0::PreferredNetworkType::EVDO_ONLY:
+ return RAF::EVDO;
+ case V1_0::PreferredNetworkType::GSM_WCDMA_CDMA_EVDO_AUTO:
+ return (RAF::GSM | RAF::WCDMA | RAF::CDMA | RAF::EVDO);
+ case V1_0::PreferredNetworkType::TD_SCDMA_ONLY:
+ return static_cast<int>(RAF::E::TD_SCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_WCDMA:
+ return (RAF::E::TD_SCDMA | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_LTE:
+ return (RAF::LTE | RAF::E::TD_SCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_GSM:
+ return (RAF::E::TD_SCDMA | RAF::GSM);
+ case V1_0::PreferredNetworkType::TD_SCDMA_GSM_LTE:
+ return (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM);
+ case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA:
+ return (RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_WCDMA_LTE:
+ return (RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_LTE:
+ return (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO:
+ return (RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType::TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA:
+ return (RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+ case V1_0::PreferredNetworkType(23): // NR_ONLY
+ return static_cast<int>(RAF::NR);
+ case V1_0::PreferredNetworkType(24): // NR_LTE
+ return (RAF::NR | RAF::LTE);
+ case V1_0::PreferredNetworkType(25): // NR_LTE_CDMA_EVDO
+ return (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO);
+ case V1_0::PreferredNetworkType(26): // NR_LTE_GSM_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType(27): // NR_LTE_CDMA_EVDO_GSM_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType(28): // NR_LTE_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::WCDMA);
+ case V1_0::PreferredNetworkType(29): // NR_LTE_TDSCDMA
+ return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA);
+ case V1_0::PreferredNetworkType(30): // NR_LTE_TDSCDMA_GSM
+ return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM);
+ case V1_0::PreferredNetworkType(31): // NR_LTE_TDSCDMA_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA);
+ case V1_0::PreferredNetworkType(32): // NR_LTE_TDSCDMA_GSM_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+ case V1_0::PreferredNetworkType(33): // NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+ return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM |
+ RAF::WCDMA);
+#pragma GCC diagnostic pop
+ default:
+ return {}; // unknown
+ }
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/utils.h b/radio/aidl/compat/libradiocompat/network/utils.h
new file mode 100644
index 0000000..10714be
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/utils.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/radio/1.4/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::PreferredNetworkType getNetworkTypeFromRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf);
+hidl_bitfield<V1_4::RadioAccessFamily> getRafFromNetworkType(V1_0::PreferredNetworkType type);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
new file mode 100644
index 0000000..3938e00
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "SimIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioSimIndication> simCb) {
+ mSimCb = simCb;
+}
+
+std::shared_ptr<aidl::IRadioSimIndication> RadioIndication::simCb() {
+ return mSimCb.get();
+}
+
+Return<void> RadioIndication::carrierInfoForImsiEncryption(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ simCb()->carrierInfoForImsiEncryption(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaSubscriptionSourceChanged(
+ V1_0::RadioIndicationType type, V1_0::CdmaSubscriptionSource cdmaSource) {
+ LOG_CALL << type;
+ simCb()->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
+ return {};
+}
+
+Return<void> RadioIndication::simPhonebookChanged(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ simCb()->simPhonebookChanged(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::simPhonebookRecordsReceived(
+ V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
+ const hidl_vec<V1_6::PhonebookRecordInfo>& rec) {
+ LOG_CALL << type;
+ simCb()->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
+ return {};
+}
+
+Return<void> RadioIndication::simRefresh(V1_0::RadioIndicationType type,
+ const V1_0::SimRefreshResult& refreshResult) {
+ LOG_CALL << type;
+ simCb()->simRefresh(toAidl(type), toAidl(refreshResult));
+ return {};
+}
+
+Return<void> RadioIndication::simStatusChanged(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ simCb()->simStatusChanged(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::stkEventNotify(V1_0::RadioIndicationType type,
+ const hidl_string& cmd) {
+ LOG_CALL << type;
+ simCb()->stkEventNotify(toAidl(type), cmd);
+ return {};
+}
+
+Return<void> RadioIndication::stkProactiveCommand(V1_0::RadioIndicationType type,
+ const hidl_string& cmd) {
+ LOG_CALL << type;
+ simCb()->stkProactiveCommand(toAidl(type), cmd);
+ return {};
+}
+
+Return<void> RadioIndication::stkSessionEnd(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ simCb()->stkSessionEnd(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::subscriptionStatusChanged(V1_0::RadioIndicationType type,
+ bool activate) {
+ LOG_CALL << type;
+ simCb()->subscriptionStatusChanged(toAidl(type), activate);
+ return {};
+}
+
+Return<void> RadioIndication::uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
+ bool enabled) {
+ LOG_CALL << type;
+ simCb()->uiccApplicationsEnablementChanged(toAidl(type), enabled);
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
new file mode 100644
index 0000000..3ad9130
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "SimResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioSimResponse> simCb) {
+ mSimCb = simCb;
+}
+
+std::shared_ptr<aidl::IRadioSimResponse> RadioResponse::simCb() {
+ return mSimCb.get();
+}
+
+Return<void> RadioResponse::areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
+ bool enabled) {
+ LOG_CALL << info.serial;
+ simCb()->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
+ return {};
+}
+
+Return<void> RadioResponse::changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->changeIccPinForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->enableUiccApplicationsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::getAllowedCarriersResponse( //
+ const V1_0::RadioResponseInfo& info, bool allAllowed, const V1_0::CarrierRestrictions& cr) {
+ LOG_CALL << info.serial;
+ aidl::CarrierRestrictions aidlCr = toAidl(cr);
+ if (allAllowed) aidlCr = {};
+ simCb()->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
+ return {};
+}
+
+Return<void> RadioResponse::getAllowedCarriersResponse_1_4(
+ const V1_0::RadioResponseInfo& info, const V1_4::CarrierRestrictionsWithPriority& carriers,
+ V1_4::SimLockMultiSimPolicy multiSimPolicy) {
+ LOG_CALL << info.serial;
+ simCb()->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
+ aidl::SimLockMultiSimPolicy(multiSimPolicy));
+ return {};
+}
+
+Return<void> RadioResponse::getCDMASubscriptionResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
+ const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) {
+ LOG_CALL << info.serial;
+ simCb()->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
+ return {};
+}
+
+Return<void> RadioResponse::getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::CdmaSubscriptionSource s) {
+ LOG_CALL << info.serial;
+ simCb()->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
+ return {};
+}
+
+Return<void> RadioResponse::getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t response) {
+ LOG_CALL << info.serial;
+ simCb()->getFacilityLockForAppResponse(toAidl(info), response);
+ return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::CardStatus& cardStatus) {
+ LOG_CALL << info.serial;
+ simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+ return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const V1_2::CardStatus& cardStatus) {
+ LOG_CALL << info.serial;
+ simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+ return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
+ const V1_4::CardStatus& cardStatus) {
+ LOG_CALL << info.serial;
+ simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+ return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
+ const V1_5::CardStatus& cardStatus) {
+ LOG_CALL << info.serial;
+ simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+ return {};
+}
+
+Return<void> RadioResponse::getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& imsi) {
+ LOG_CALL << info.serial;
+ simCb()->getImsiForAppResponse(toAidl(info), imsi);
+ return {};
+}
+
+Return<void> RadioResponse::getSimPhonebookCapacityResponse(
+ const V1_6::RadioResponseInfo& info, const V1_6::PhonebookCapacity& capacity) {
+ LOG_CALL << info.serial;
+ simCb()->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
+ return {};
+}
+
+Return<void> RadioResponse::getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->getSimPhonebookRecordsResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->iccCloseLogicalChannelResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& iccIo) {
+ LOG_CALL << info.serial;
+ simCb()->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
+ return {};
+}
+
+Return<void> RadioResponse::iccOpenLogicalChannelResponse( //
+ const V1_0::RadioResponseInfo& info, int32_t chanId, const hidl_vec<int8_t>& selectResp) {
+ LOG_CALL << info.serial;
+ simCb()->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
+ return {};
+}
+
+Return<void> RadioResponse::iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& result) {
+ LOG_CALL << info.serial;
+ simCb()->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
+ return {};
+}
+
+Return<void> RadioResponse::iccTransmitApduLogicalChannelResponse(
+ const V1_0::RadioResponseInfo& info, const V1_0::IccIoResult& result) {
+ LOG_CALL << info.serial;
+ simCb()->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
+ return {};
+}
+
+Return<void> RadioResponse::reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->reportStkServiceIsRunningResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& result) {
+ LOG_CALL << info.serial;
+ simCb()->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
+ return {};
+}
+
+Return<void> RadioResponse::requestIsimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string&) {
+ LOG_CALL << info.serial;
+ LOG(ERROR) << "requestIsimAuthenticationResponse is not supposed to be called";
+ return {};
+}
+
+Return<void> RadioResponse::sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_string& commandResponse) {
+ LOG_CALL << info.serial;
+ simCb()->sendEnvelopeResponse(toAidl(info), commandResponse);
+ return {};
+}
+
+Return<void> RadioResponse::sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
+ const V1_0::IccIoResult& iccIo) {
+ LOG_CALL << info.serial;
+ simCb()->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
+ return {};
+}
+
+Return<void> RadioResponse::sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->sendTerminalResponseToSimResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
+ int32_t numAllowed) {
+ LOG_CALL << info.serial << ' ' << numAllowed;
+ simCb()->setAllowedCarriersResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setAllowedCarriersResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCarrierInfoForImsiEncryptionResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setCdmaSubscriptionSourceResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t retry) {
+ LOG_CALL << info.serial;
+ simCb()->setFacilityLockForAppResponse(toAidl(info), retry);
+ return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setSimCardPowerResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setSimCardPowerResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setSimCardPowerResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ simCb()->setUiccSubscriptionResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
+ int32_t remainingRetries) {
+ LOG_CALL << info.serial;
+ simCb()->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
+ return {};
+}
+
+Return<void> RadioResponse::supplySimDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+ V1_5::PersoSubstate persoType,
+ int32_t rRet) {
+ LOG_CALL << info.serial;
+ simCb()->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
+ return {};
+}
+
+Return<void> RadioResponse::updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
+ int32_t updatedRecordIndex) {
+ LOG_CALL << info.serial;
+ simCb()->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
new file mode 100644
index 0000000..b43f64f
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioSim.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Sim"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::sim;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioSimResponse> RadioSim::respond() {
+ return mCallbackManager->response().simCb();
+}
+
+ScopedAStatus RadioSim::areUiccApplicationsEnabled(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->areUiccApplicationsEnabled(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
+ const std::string& newPin2, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->changeIccPin2ForApp(serial, oldPin2, newPin2, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::changeIccPinForApp(int32_t serial, const std::string& oldPin,
+ const std::string& newPin, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->changeIccPinForApp(serial, oldPin, newPin, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::enableUiccApplications(int32_t serial, bool enable) {
+ LOG_CALL << serial;
+ mHal1_5->enableUiccApplications(serial, enable);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getAllowedCarriers(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getAllowedCarriers_1_4(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getCdmaSubscription(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getCDMASubscription(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getCdmaSubscriptionSource(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getCdmaSubscriptionSource(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getFacilityLockForApp( //
+ int32_t serial, const std::string& facility, const std::string& password,
+ int32_t serviceClass, const std::string& appId) {
+ LOG_CALL << serial;
+ mHal1_5->getFacilityLockForApp(serial, facility, password, serviceClass, appId);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getIccCardStatus(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getIccCardStatus(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getImsiForApp(int32_t serial, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->getImsiForApp(serial, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::getSimPhonebookCapacity(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getSimPhonebookCapacity(serial);
+ } else {
+ respond()->getSimPhonebookCapacityResponse(notSupported(serial), {});
+ }
+ return ok();
+}
+
+ScopedAStatus RadioSim::getSimPhonebookRecords(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getSimPhonebookRecords(serial);
+ } else {
+ respond()->getSimPhonebookRecordsResponse(notSupported(serial));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioSim::iccCloseLogicalChannel(int32_t serial, int32_t channelId) {
+ LOG_CALL << serial;
+ mHal1_5->iccCloseLogicalChannel(serial, channelId);
+ return ok();
+}
+
+ScopedAStatus RadioSim::iccIoForApp(int32_t serial, const aidl::IccIo& iccIo) {
+ LOG_CALL << serial;
+ mHal1_5->iccIOForApp(serial, toHidl(iccIo));
+ return ok();
+}
+
+ScopedAStatus RadioSim::iccOpenLogicalChannel(int32_t serial, const std::string& aid, int32_t p2) {
+ LOG_CALL << serial;
+ mHal1_5->iccOpenLogicalChannel(serial, aid, p2);
+ return ok();
+}
+
+ScopedAStatus RadioSim::iccTransmitApduBasicChannel(int32_t serial, const aidl::SimApdu& message) {
+ LOG_CALL << serial;
+ mHal1_5->iccTransmitApduBasicChannel(serial, toHidl(message));
+ return ok();
+}
+
+ScopedAStatus RadioSim::iccTransmitApduLogicalChannel(int32_t serial,
+ const aidl::SimApdu& message) {
+ LOG_CALL << serial;
+ mHal1_5->iccTransmitApduLogicalChannel(serial, toHidl(message));
+ return ok();
+}
+
+ScopedAStatus RadioSim::reportStkServiceIsRunning(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->reportStkServiceIsRunning(serial);
+ return ok();
+}
+
+ScopedAStatus RadioSim::requestIccSimAuthentication( //
+ int32_t serial, int32_t authContext, const std::string& authData, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->requestIccSimAuthentication(serial, authContext, authData, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioSim::sendEnvelope(int32_t serial, const std::string& command) {
+ LOG_CALL << serial;
+ mHal1_5->sendEnvelope(serial, command);
+ return ok();
+}
+
+ScopedAStatus RadioSim::sendEnvelopeWithStatus(int32_t serial, const std::string& contents) {
+ LOG_CALL << serial;
+ mHal1_5->sendEnvelopeWithStatus(serial, contents);
+ return ok();
+}
+
+ScopedAStatus RadioSim::sendTerminalResponseToSim(int32_t serial,
+ const std::string& commandResponse) {
+ LOG_CALL << serial;
+ mHal1_5->sendTerminalResponseToSim(serial, commandResponse);
+ return ok();
+}
+
+ScopedAStatus RadioSim::setAllowedCarriers( //
+ int32_t serial, const aidl::CarrierRestrictions& carriers, aidl::SimLockMultiSimPolicy mp) {
+ LOG_CALL << serial;
+ mHal1_5->setAllowedCarriers_1_4(serial, toHidl(carriers), V1_4::SimLockMultiSimPolicy(mp));
+ return ok();
+}
+
+ScopedAStatus RadioSim::setCarrierInfoForImsiEncryption(
+ int32_t serial, const aidl::ImsiEncryptionInfo& imsiEncryptionInfo) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->setCarrierInfoForImsiEncryption_1_6(serial, toHidl_1_6(imsiEncryptionInfo));
+ } else {
+ mHal1_5->setCarrierInfoForImsiEncryption(serial, toHidl(imsiEncryptionInfo));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioSim::setCdmaSubscriptionSource(int32_t serial,
+ aidl::CdmaSubscriptionSource cdmaSub) {
+ LOG_CALL << serial;
+ mHal1_5->setCdmaSubscriptionSource(serial, V1_0::CdmaSubscriptionSource(cdmaSub));
+ return ok();
+}
+
+ScopedAStatus RadioSim::setFacilityLockForApp( //
+ int32_t serial, const std::string& facility, bool lockState, const std::string& password,
+ int32_t serviceClass, const std::string& appId) {
+ LOG_CALL << serial;
+ mHal1_5->setFacilityLockForApp(serial, facility, lockState, password, serviceClass, appId);
+ return ok();
+}
+
+ScopedAStatus RadioSim::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioSimResponse>& response,
+ const std::shared_ptr<aidl::IRadioSimIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+ScopedAStatus RadioSim::setSimCardPower(int32_t serial, aidl::CardPowerState powerUp) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->setSimCardPower_1_6(serial, V1_1::CardPowerState(powerUp));
+ } else {
+ mHal1_5->setSimCardPower_1_1(serial, V1_1::CardPowerState(powerUp));
+ }
+ return ok();
+}
+
+ScopedAStatus RadioSim::setUiccSubscription(int32_t serial, const aidl::SelectUiccSub& uiccSub) {
+ LOG_CALL << serial;
+ mHal1_5->setUiccSubscription(serial, toHidl(uiccSub));
+ return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPin2ForApp(int32_t serial, const std::string& pin2,
+ const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->supplyIccPin2ForApp(serial, pin2, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPinForApp(int32_t serial, const std::string& pin,
+ const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->supplyIccPinForApp(serial, pin, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPuk2ForApp(int32_t serial, const std::string& puk2,
+ const std::string& pin2, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->supplyIccPuk2ForApp(serial, puk2, pin2, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPukForApp(int32_t serial, const std::string& puk,
+ const std::string& pin, const std::string& aid) {
+ LOG_CALL << serial;
+ mHal1_5->supplyIccPukForApp(serial, puk, pin, aid);
+ return ok();
+}
+
+ScopedAStatus RadioSim::supplySimDepersonalization(int32_t serial, aidl::PersoSubstate pss,
+ const std::string& controlKey) {
+ LOG_CALL << serial;
+ mHal1_5->supplySimDepersonalization(serial, V1_5::PersoSubstate(pss), controlKey);
+ return ok();
+}
+
+ScopedAStatus RadioSim::updateSimPhonebookRecords(int32_t serial,
+ const aidl::PhonebookRecordInfo& recordInfo) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->updateSimPhonebookRecords(serial, toHidl(recordInfo));
+ } else {
+ respond()->updateSimPhonebookRecordsResponse(notSupported(serial), 0);
+ }
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.cpp b/radio/aidl/compat/libradiocompat/sim/structs.cpp
new file mode 100644
index 0000000..bfbff02
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/structs.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+V1_0::IccIo toHidl(const aidl::IccIo& icc) {
+ return {
+ .command = icc.command,
+ .fileId = icc.fileId,
+ .path = icc.path,
+ .p1 = icc.p1,
+ .p2 = icc.p2,
+ .p3 = icc.p3,
+ .data = icc.data,
+ .pin2 = icc.pin2,
+ .aid = icc.aid,
+ };
+}
+
+V1_0::SimApdu toHidl(const aidl::SimApdu& apdu) {
+ return {
+ .sessionId = apdu.sessionId,
+ .cla = apdu.cla,
+ .instruction = apdu.instruction,
+ .p1 = apdu.p1,
+ .p2 = apdu.p2,
+ .p3 = apdu.p3,
+ .data = apdu.data,
+ };
+}
+
+aidl::Carrier toAidl(const V1_0::Carrier& carrier) {
+ return {
+ .mcc = carrier.mcc,
+ .mnc = carrier.mnc,
+ .matchType = static_cast<int32_t>(carrier.matchType),
+ .matchData = carrier.matchData,
+ };
+}
+
+V1_0::Carrier toHidl(const aidl::Carrier& carrier) {
+ return {
+ .mcc = carrier.mcc,
+ .mnc = carrier.mnc,
+ .matchType = V1_0::CarrierMatchType{carrier.matchType},
+ .matchData = carrier.matchData,
+ };
+}
+
+aidl::CarrierRestrictions toAidl(const V1_0::CarrierRestrictions& cr) {
+ return {
+ .allowedCarriers = toAidl(cr.allowedCarriers),
+ .excludedCarriers = toAidl(cr.excludedCarriers),
+ .allowedCarriersPrioritized = true,
+ };
+}
+
+aidl::CarrierRestrictions toAidl(const V1_4::CarrierRestrictionsWithPriority& cr) {
+ return {
+ .allowedCarriers = toAidl(cr.allowedCarriers),
+ .excludedCarriers = toAidl(cr.excludedCarriers),
+ .allowedCarriersPrioritized = cr.allowedCarriersPrioritized,
+ };
+}
+
+V1_4::CarrierRestrictionsWithPriority toHidl(const aidl::CarrierRestrictions& cr) {
+ return {
+ .allowedCarriers = toHidl(cr.allowedCarriers),
+ .excludedCarriers = toHidl(cr.excludedCarriers),
+ .allowedCarriersPrioritized = cr.allowedCarriersPrioritized,
+ };
+}
+
+V1_1::ImsiEncryptionInfo toHidl(const aidl::ImsiEncryptionInfo& info) {
+ return {
+ .mcc = info.mcc,
+ .mnc = info.mnc,
+ .carrierKey = info.carrierKey,
+ .keyIdentifier = info.keyIdentifier,
+ .expirationTime = info.expirationTime,
+ };
+}
+
+V1_6::ImsiEncryptionInfo toHidl_1_6(const aidl::ImsiEncryptionInfo& info) {
+ return {
+ .base = toHidl(info),
+ .keyType = V1_6::PublicKeyType{info.keyType},
+ };
+}
+
+V1_0::SelectUiccSub toHidl(const aidl::SelectUiccSub& sub) {
+ return {
+ .slot = sub.slot,
+ .appIndex = sub.appIndex,
+ .subType = {},
+ .actStatus = {},
+ };
+}
+
+aidl::PhonebookRecordInfo toAidl(const V1_6::PhonebookRecordInfo& info) {
+ return {
+ .recordId = static_cast<int32_t>(info.recordId),
+ .name = info.name,
+ .number = info.number,
+ .emails = toAidl(info.emails),
+ .additionalNumbers = toAidl(info.additionalNumbers),
+ };
+}
+
+V1_6::PhonebookRecordInfo toHidl(const aidl::PhonebookRecordInfo& info) {
+ return {
+ .recordId = static_cast<uint32_t>(info.recordId),
+ .name = info.name,
+ .number = info.number,
+ .emails = toHidl(info.emails),
+ .additionalNumbers = toHidl(info.additionalNumbers),
+ };
+}
+
+aidl::SimRefreshResult toAidl(const V1_0::SimRefreshResult& res) {
+ return {
+ .type = static_cast<int32_t>(res.type),
+ .efId = res.efId,
+ .aid = res.aid,
+ };
+}
+
+aidl::CardStatus toAidl(const V1_0::CardStatus& status) {
+ return toAidl(V1_2::CardStatus{status, 0, "", ""});
+}
+
+aidl::CardStatus toAidl(const V1_2::CardStatus& status) {
+ return toAidl(V1_4::CardStatus{status, ""});
+}
+
+aidl::CardStatus toAidl(const V1_4::CardStatus& status) {
+ auto aidlStatus = toAidl(V1_5::CardStatus{status, {}});
+ aidlStatus.applications = toAidl(status.base.base.applications);
+ return aidlStatus;
+}
+
+aidl::CardStatus toAidl(const V1_5::CardStatus& status) {
+ return {
+ .cardState = static_cast<int32_t>(status.base.base.base.cardState),
+ .universalPinState = aidl::PinState(status.base.base.base.universalPinState),
+ .gsmUmtsSubscriptionAppIndex = status.base.base.base.gsmUmtsSubscriptionAppIndex,
+ .cdmaSubscriptionAppIndex = status.base.base.base.cdmaSubscriptionAppIndex,
+ .imsSubscriptionAppIndex = status.base.base.base.imsSubscriptionAppIndex,
+ .applications = toAidl(status.applications),
+ .atr = status.base.base.atr,
+ .iccid = status.base.base.iccid,
+ .eid = status.base.eid,
+ .slotMap = {static_cast<int32_t>(status.base.base.physicalSlotId), 0},
+ };
+}
+
+aidl::AppStatus toAidl(const V1_0::AppStatus& status) {
+ return toAidl({status, V1_5::PersoSubstate(status.persoSubstate)});
+}
+
+aidl::AppStatus toAidl(const V1_5::AppStatus& status) {
+ return {
+ .appType = static_cast<int32_t>(status.base.appType),
+ .appState = static_cast<int32_t>(status.base.appState),
+ .persoSubstate = aidl::PersoSubstate(status.persoSubstate),
+ .aidPtr = status.base.aidPtr,
+ .appLabelPtr = status.base.appLabelPtr,
+ .pin1Replaced = (status.base.pin1Replaced != 0),
+ .pin1 = aidl::PinState(status.base.pin1),
+ .pin2 = aidl::PinState(status.base.pin2),
+ };
+}
+
+aidl::PhonebookCapacity toAidl(const V1_6::PhonebookCapacity& c) {
+ return {
+ .maxAdnRecords = c.maxAdnRecords,
+ .usedAdnRecords = c.usedAdnRecords,
+ .maxEmailRecords = c.maxEmailRecords,
+ .usedEmailRecords = c.usedEmailRecords,
+ .maxAdditionalNumberRecords = c.maxAdditionalNumberRecords,
+ .usedAdditionalNumberRecords = c.usedAdditionalNumberRecords,
+ .maxNameLen = c.maxNameLen,
+ .maxNumberLen = c.maxNumberLen,
+ .maxEmailLen = c.maxEmailLen,
+ .maxAdditionalNumberLen = c.maxAdditionalNumberLen,
+ };
+}
+
+aidl::IccIoResult toAidl(const V1_0::IccIoResult& iir) {
+ return {
+ .sw1 = iir.sw1,
+ .sw2 = iir.sw2,
+ .simResponse = iir.simResponse,
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.h b/radio/aidl/compat/libradiocompat/sim/structs.h
new file mode 100644
index 0000000..54099b7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/structs.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/sim/AppStatus.h>
+#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <aidl/android/hardware/radio/sim/Carrier.h>
+#include <aidl/android/hardware/radio/sim/CarrierRestrictions.h>
+#include <aidl/android/hardware/radio/sim/IccIo.h>
+#include <aidl/android/hardware/radio/sim/IccIoResult.h>
+#include <aidl/android/hardware/radio/sim/ImsiEncryptionInfo.h>
+#include <aidl/android/hardware/radio/sim/PhonebookCapacity.h>
+#include <aidl/android/hardware/radio/sim/PhonebookRecordInfo.h>
+#include <aidl/android/hardware/radio/sim/SelectUiccSub.h>
+#include <aidl/android/hardware/radio/sim/SimApdu.h>
+#include <aidl/android/hardware/radio/sim/SimRefreshResult.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::IccIo toHidl(const ::aidl::android::hardware::radio::sim::IccIo& icc);
+
+V1_0::SimApdu toHidl(const ::aidl::android::hardware::radio::sim::SimApdu& apdu);
+
+::aidl::android::hardware::radio::sim::Carrier toAidl(const V1_0::Carrier& carrier);
+V1_0::Carrier toHidl(const ::aidl::android::hardware::radio::sim::Carrier& carrier);
+
+::aidl::android::hardware::radio::sim::CarrierRestrictions //
+toAidl(const V1_0::CarrierRestrictions& cr);
+::aidl::android::hardware::radio::sim::CarrierRestrictions //
+toAidl(const V1_4::CarrierRestrictionsWithPriority& cr);
+V1_4::CarrierRestrictionsWithPriority //
+toHidl(const ::aidl::android::hardware::radio::sim::CarrierRestrictions& cr);
+
+V1_1::ImsiEncryptionInfo //
+toHidl(const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& info);
+V1_6::ImsiEncryptionInfo //
+toHidl_1_6(const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& info);
+
+V1_0::SelectUiccSub toHidl(const ::aidl::android::hardware::radio::sim::SelectUiccSub& sub);
+
+::aidl::android::hardware::radio::sim::PhonebookRecordInfo //
+toAidl(const V1_6::PhonebookRecordInfo& info);
+V1_6::PhonebookRecordInfo //
+toHidl(const ::aidl::android::hardware::radio::sim::PhonebookRecordInfo& info);
+
+::aidl::android::hardware::radio::sim::SimRefreshResult //
+toAidl(const V1_0::SimRefreshResult& res);
+
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_0::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_2::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_4::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_5::CardStatus& status);
+
+::aidl::android::hardware::radio::sim::AppStatus toAidl(const V1_0::AppStatus& status);
+::aidl::android::hardware::radio::sim::AppStatus toAidl(const V1_5::AppStatus& status);
+
+::aidl::android::hardware::radio::sim::PhonebookCapacity toAidl(const V1_6::PhonebookCapacity& c);
+
+::aidl::android::hardware::radio::sim::IccIoResult toAidl(const V1_0::IccIoResult& iir);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
new file mode 100644
index 0000000..23878ed
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "VoiceIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceIndication> voiceCb) {
+ mVoiceCb = voiceCb;
+}
+
+std::shared_ptr<aidl::IRadioVoiceIndication> RadioIndication::voiceCb() {
+ return mVoiceCb.get();
+}
+
+Return<void> RadioIndication::callRing(V1_0::RadioIndicationType type, bool isGsm,
+ const V1_0::CdmaSignalInfoRecord& record) {
+ LOG_CALL << type;
+ voiceCb()->callRing(toAidl(type), isGsm, toAidl(record));
+ return {};
+}
+
+Return<void> RadioIndication::callStateChanged(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ voiceCb()->callStateChanged(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaCallWaiting(V1_0::RadioIndicationType type,
+ const V1_0::CdmaCallWaiting& callWaitingRecord) {
+ LOG_CALL << type;
+ voiceCb()->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaInfoRec(V1_0::RadioIndicationType type,
+ const V1_0::CdmaInformationRecords& records) {
+ LOG_CALL << type;
+ voiceCb()->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
+ return {};
+}
+
+Return<void> RadioIndication::cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
+ V1_0::CdmaOtaProvisionStatus status) {
+ LOG_CALL << type;
+ voiceCb()->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
+ return {};
+}
+
+Return<void> RadioIndication::currentEmergencyNumberList(
+ V1_0::RadioIndicationType type, const hidl_vec<V1_4::EmergencyNumber>& emergencyNumbers) {
+ LOG_CALL << type;
+ voiceCb()->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
+ return {};
+}
+
+Return<void> RadioIndication::enterEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ voiceCb()->enterEmergencyCallbackMode(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::exitEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ voiceCb()->exitEmergencyCallbackMode(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::indicateRingbackTone(V1_0::RadioIndicationType type, bool start) {
+ LOG_CALL << type;
+ voiceCb()->indicateRingbackTone(toAidl(type), start);
+ return {};
+}
+
+Return<void> RadioIndication::onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
+ const V1_0::StkCcUnsolSsResult& ss) {
+ LOG_CALL << type;
+ voiceCb()->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
+ return {};
+}
+
+Return<void> RadioIndication::onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
+ const hidl_string& msg) {
+ LOG_CALL << type;
+ voiceCb()->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
+ return {};
+}
+
+Return<void> RadioIndication::resendIncallMute(V1_0::RadioIndicationType type) {
+ LOG_CALL << type;
+ voiceCb()->resendIncallMute(toAidl(type));
+ return {};
+}
+
+Return<void> RadioIndication::srvccStateNotify(V1_0::RadioIndicationType type,
+ V1_0::SrvccState state) {
+ LOG_CALL << type;
+ voiceCb()->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
+ return {};
+}
+
+Return<void> RadioIndication::stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
+ const hidl_string& alpha) {
+ LOG_CALL << type;
+ voiceCb()->stkCallControlAlphaNotify(toAidl(type), alpha);
+ return {};
+}
+
+Return<void> RadioIndication::stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) {
+ LOG_CALL << type;
+ voiceCb()->stkCallSetup(toAidl(type), timeout);
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
new file mode 100644
index 0000000..5307e11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "VoiceResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceResponse> voiceCb) {
+ mVoiceCb = voiceCb;
+}
+
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioResponse::voiceCb() {
+ return mVoiceCb.get();
+}
+
+Return<void> RadioResponse::acceptCallResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->acceptCallResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->cancelPendingUssdResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::conferenceResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->conferenceResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::dialResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->dialResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::emergencyDialResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->emergencyDialResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->exitEmergencyCallbackModeResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->explicitCallTransferResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::getCallForwardStatusResponse(
+ const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::CallForwardInfo>& callFwdInfos) {
+ LOG_CALL << info.serial;
+ voiceCb()->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
+ return {};
+}
+
+Return<void> RadioResponse::getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
+ int32_t serviceClass) {
+ LOG_CALL << info.serial;
+ voiceCb()->getCallWaitingResponse(toAidl(info), enable, serviceClass);
+ return {};
+}
+
+Return<void> RadioResponse::getClipResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::ClipStatus status) {
+ LOG_CALL << info.serial;
+ voiceCb()->getClipResponse(toAidl(info), aidl::ClipStatus(status));
+ return {};
+}
+
+Return<void> RadioResponse::getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
+ int32_t m) {
+ LOG_CALL << info.serial;
+ voiceCb()->getClirResponse(toAidl(info), n, m);
+ return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_0::Call>& calls) {
+ LOG_CALL << info.serial;
+ voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+ return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
+ const hidl_vec<V1_2::Call>& calls) {
+ LOG_CALL << info.serial;
+ voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+ return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
+ const hidl_vec<V1_6::Call>& calls) {
+ LOG_CALL << info.serial;
+ voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+ return {};
+}
+
+Return<void> RadioResponse::getLastCallFailCauseResponse(
+ const V1_0::RadioResponseInfo& info, const V1_0::LastCallFailCauseInfo& failCauseinfo) {
+ LOG_CALL << info.serial;
+ voiceCb()->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
+ return {};
+}
+
+Return<void> RadioResponse::getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) {
+ LOG_CALL << info.serial;
+ voiceCb()->getMuteResponse(toAidl(info), enable);
+ return {};
+}
+
+Return<void> RadioResponse::getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
+ bool enable) {
+ LOG_CALL << info.serial;
+ voiceCb()->getPreferredVoicePrivacyResponse(toAidl(info), enable);
+ return {};
+}
+
+Return<void> RadioResponse::getTTYModeResponse(const V1_0::RadioResponseInfo& info,
+ V1_0::TtyMode mode) {
+ LOG_CALL << info.serial;
+ voiceCb()->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
+ return {};
+}
+
+Return<void> RadioResponse::handleStkCallSetupRequestFromSimResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->handleStkCallSetupRequestFromSimResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::hangupConnectionResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->hangupConnectionResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::hangupForegroundResumeBackgroundResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->hangupForegroundResumeBackgroundResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->hangupWaitingOrBackgroundResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::rejectCallResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->rejectCallResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->sendBurstDtmfResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->sendCdmaFeatureCodeResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendDtmfResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->sendDtmfResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::sendUssdResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->sendUssdResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::separateConnectionResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->separateConnectionResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCallForwardResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setCallForwardResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setCallWaitingResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setCallWaitingResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setClirResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setClirResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setMuteResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setMuteResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setPreferredVoicePrivacyResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::setTTYModeResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->setTtyModeResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::startDtmfResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->startDtmfResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::stopDtmfResponse(const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->stopDtmfResponse(toAidl(info));
+ return {};
+}
+
+Return<void> RadioResponse::switchWaitingOrHoldingAndActiveResponse(
+ const V1_0::RadioResponseInfo& info) {
+ LOG_CALL << info.serial;
+ voiceCb()->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
new file mode 100644
index 0000000..9088f01
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <libradiocompat/RadioVoice.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Voice"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::voice;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioVoice::respond() {
+ return mCallbackManager->response().voiceCb();
+}
+
+ScopedAStatus RadioVoice::acceptCall(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->acceptCall(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::cancelPendingUssd(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->cancelPendingUssd(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::conference(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->conference(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::dial(int32_t serial, const aidl::Dial& dialInfo) {
+ LOG_CALL << serial;
+ mHal1_5->dial(serial, toHidl(dialInfo));
+ return ok();
+}
+
+ScopedAStatus RadioVoice::emergencyDial( //
+ int32_t serial, const aidl::Dial& info, int32_t categories,
+ const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
+ bool knownUserIntentEmerg, bool isTesting) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->emergencyDial_1_6( //
+ serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+ toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+ } else {
+ mHal1_5->emergencyDial( //
+ serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+ toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioVoice::exitEmergencyCallbackMode(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->exitEmergencyCallbackMode(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::explicitCallTransfer(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->explicitCallTransfer(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getCallForwardStatus(int32_t serial,
+ const aidl::CallForwardInfo& callInfo) {
+ LOG_CALL << serial;
+ mHal1_5->getCallForwardStatus(serial, toHidl(callInfo));
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getCallWaiting(int32_t serial, int32_t serviceClass) {
+ LOG_CALL << serial;
+ mHal1_5->getCallWaiting(serial, serviceClass);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getClip(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getClip(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getClir(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getClir(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getCurrentCalls(int32_t serial) {
+ LOG_CALL << serial;
+ if (mHal1_6) {
+ mHal1_6->getCurrentCalls_1_6(serial);
+ } else {
+ mHal1_5->getCurrentCalls(serial);
+ }
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getLastCallFailCause(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getLastCallFailCause(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getMute(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getMute(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getPreferredVoicePrivacy(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getPreferredVoicePrivacy(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::getTtyMode(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->getTTYMode(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
+ LOG_CALL << serial;
+ mHal1_5->handleStkCallSetupRequestFromSim(serial, accept);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::hangup(int32_t serial, int32_t gsmIndex) {
+ LOG_CALL << serial;
+ mHal1_5->hangup(serial, gsmIndex);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::hangupForegroundResumeBackground(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->hangupForegroundResumeBackground(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::hangupWaitingOrBackground(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->hangupWaitingOrBackground(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::isVoNrEnabled(int32_t serial) {
+ LOG_CALL << serial;
+ respond()->isVoNrEnabledResponse(notSupported(serial), false);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::rejectCall(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->rejectCall(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::responseAcknowledgement() {
+ LOG_CALL;
+ mHal1_5->responseAcknowledgement();
+ return ok();
+}
+
+ScopedAStatus RadioVoice::sendBurstDtmf(int32_t serial, const std::string& dtmf, int32_t on,
+ int32_t off) {
+ LOG_CALL << serial;
+ mHal1_5->sendBurstDtmf(serial, dtmf, on, off);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::sendCdmaFeatureCode(int32_t serial, const std::string& featureCode) {
+ LOG_CALL << serial;
+ mHal1_5->sendCDMAFeatureCode(serial, featureCode);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::sendDtmf(int32_t serial, const std::string& s) {
+ LOG_CALL << serial;
+ mHal1_5->sendDtmf(serial, s);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::sendUssd(int32_t serial, const std::string& ussd) {
+ LOG_CALL << serial << ' ' << ussd;
+ mHal1_5->sendUssd(serial, ussd);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::separateConnection(int32_t serial, int32_t gsmIndex) {
+ LOG_CALL << serial;
+ mHal1_5->separateConnection(serial, gsmIndex);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setCallForward(int32_t serial, const aidl::CallForwardInfo& callInfo) {
+ LOG_CALL << serial;
+ mHal1_5->setCallForward(serial, toHidl(callInfo));
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
+ LOG_CALL << serial;
+ mHal1_5->setCallWaiting(serial, enable, serviceClass);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setClir(int32_t serial, int32_t status) {
+ LOG_CALL << serial;
+ mHal1_5->setClir(serial, status);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setMute(int32_t serial, bool enable) {
+ LOG_CALL << serial;
+ mHal1_5->setMute(serial, enable);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setPreferredVoicePrivacy(int32_t serial, bool enable) {
+ LOG_CALL << serial;
+ mHal1_5->setPreferredVoicePrivacy(serial, enable);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioVoiceResponse>& response,
+ const std::shared_ptr<aidl::IRadioVoiceIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::setTtyMode(int32_t serial, aidl::TtyMode mode) {
+ LOG_CALL << serial;
+ mHal1_5->setTTYMode(serial, V1_0::TtyMode(mode));
+ return ok();
+}
+
+ndk::ScopedAStatus RadioVoice::setVoNrEnabled(int32_t serial, [[maybe_unused]] bool enable) {
+ LOG_CALL << serial;
+ // Note: a workaround for older HALs could also be setting persist.radio.is_vonr_enabled_
+ respond()->setVoNrEnabledResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioVoice::startDtmf(int32_t serial, const std::string& s) {
+ LOG_CALL << serial;
+ mHal1_5->startDtmf(serial, s);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::stopDtmf(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->stopDtmf(serial);
+ return ok();
+}
+
+ScopedAStatus RadioVoice::switchWaitingOrHoldingAndActive(int32_t serial) {
+ LOG_CALL << serial;
+ mHal1_5->switchWaitingOrHoldingAndActive(serial);
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.cpp b/radio/aidl/compat/libradiocompat/voice/structs.cpp
new file mode 100644
index 0000000..254ea20
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+V1_0::Dial toHidl(const aidl::Dial& info) {
+ return {
+ .address = info.address,
+ .clir = V1_0::Clir{info.clir},
+ .uusInfo = toHidl(info.uusInfo),
+ };
+}
+
+V1_0::UusInfo toHidl(const aidl::UusInfo& info) {
+ return {
+ .uusType = V1_0::UusType{info.uusType},
+ .uusDcs = V1_0::UusDcs{info.uusDcs},
+ .uusData = info.uusData,
+ };
+}
+
+aidl::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info) {
+ return {
+ .status = static_cast<int32_t>(info.status),
+ .reason = info.reason,
+ .serviceClass = info.serviceClass,
+ .toa = info.toa,
+ .number = info.number,
+ .timeSeconds = info.timeSeconds,
+ };
+}
+
+V1_0::CallForwardInfo toHidl(const aidl::CallForwardInfo& info) {
+ return {
+ .status = V1_0::CallForwardInfoStatus{info.status},
+ .reason = info.reason,
+ .serviceClass = info.serviceClass,
+ .toa = info.toa,
+ .number = info.number,
+ .timeSeconds = info.timeSeconds,
+ };
+}
+
+aidl::CdmaSignalInfoRecord toAidl(const V1_0::CdmaSignalInfoRecord& record) {
+ return {
+ .isPresent = record.isPresent,
+ .signalType = record.signalType,
+ .alertPitch = record.alertPitch,
+ .signal = record.signal,
+ };
+}
+
+aidl::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call) {
+ return {
+ .number = call.number,
+ .numberPresentation = static_cast<int32_t>(call.numberPresentation),
+ .name = call.name,
+ .signalInfoRecord = toAidl(call.signalInfoRecord),
+ .numberType = static_cast<int32_t>(call.numberType),
+ .numberPlan = static_cast<int32_t>(call.numberPlan),
+ };
+}
+
+aidl::CdmaInformationRecord toAidl(const V1_0::CdmaInformationRecord& record) {
+ return {
+ .name = static_cast<int32_t>(record.name),
+ .display = toAidl(record.display),
+ .number = toAidl(record.number),
+ .signal = toAidl(record.signal),
+ .redir = toAidl(record.redir),
+ .lineCtrl = toAidl(record.lineCtrl),
+ .clir = toAidl(record.clir),
+ .audioCtrl = toAidl(record.audioCtrl),
+ };
+}
+
+aidl::CdmaDisplayInfoRecord toAidl(const V1_0::CdmaDisplayInfoRecord& record) {
+ return {
+ .alphaBuf = record.alphaBuf,
+ };
+}
+
+aidl::CdmaNumberInfoRecord toAidl(const V1_0::CdmaNumberInfoRecord& record) {
+ return {
+ .number = record.number,
+ .numberType = static_cast<int8_t>(record.numberType),
+ .numberPlan = static_cast<int8_t>(record.numberPlan),
+ .pi = static_cast<int8_t>(record.pi),
+ .si = static_cast<int8_t>(record.si),
+ };
+}
+
+aidl::CdmaRedirectingNumberInfoRecord toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record) {
+ return {
+ .redirectingNumber = toAidl(record.redirectingNumber),
+ .redirectingReason = static_cast<int32_t>(record.redirectingReason),
+ };
+}
+
+aidl::CdmaLineControlInfoRecord toAidl(const V1_0::CdmaLineControlInfoRecord& record) {
+ return {
+ .lineCtrlPolarityIncluded = static_cast<int8_t>(record.lineCtrlPolarityIncluded),
+ .lineCtrlToggle = static_cast<int8_t>(record.lineCtrlToggle),
+ .lineCtrlReverse = static_cast<int8_t>(record.lineCtrlReverse),
+ .lineCtrlPowerDenial = static_cast<int8_t>(record.lineCtrlPowerDenial),
+ };
+}
+
+aidl::CdmaT53ClirInfoRecord toAidl(const V1_0::CdmaT53ClirInfoRecord& record) {
+ return {
+ .cause = static_cast<int8_t>(record.cause),
+ };
+}
+
+aidl::CdmaT53AudioControlInfoRecord toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record) {
+ return {
+ .upLink = static_cast<int8_t>(record.upLink),
+ .downLink = static_cast<int8_t>(record.downLink),
+ };
+}
+
+aidl::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num) {
+ return {
+ .number = num.number,
+ .mcc = num.mcc,
+ .mnc = num.mnc,
+ .categories = num.categories,
+ .urns = toAidl(num.urns),
+ .sources = num.sources,
+ };
+}
+
+aidl::StkCcUnsolSsResult toAidl(const V1_0::StkCcUnsolSsResult& res) {
+ return {
+ .serviceType = static_cast<int32_t>(res.serviceType),
+ .requestType = static_cast<int32_t>(res.requestType),
+ .teleserviceType = static_cast<int32_t>(res.teleserviceType),
+ .serviceClass = res.serviceClass,
+ .result = toAidl(res.result),
+ .ssInfo = toAidl(res.ssInfo),
+ .cfData = toAidl(res.cfData),
+ };
+}
+
+aidl::SsInfoData toAidl(const V1_0::SsInfoData& info) {
+ return {
+ .ssInfo = info.ssInfo,
+ };
+}
+
+aidl::CfData toAidl(const V1_0::CfData& data) {
+ return {
+ .cfInfo = toAidl(data.cfInfo),
+ };
+}
+
+aidl::Call toAidl(const V1_0::Call& call) {
+ return toAidl(V1_2::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_2::Call& call) {
+ return toAidl(V1_6::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_6::Call& call) {
+ return {
+ .state = static_cast<int32_t>(call.base.base.state),
+ .index = call.base.base.index,
+ .toa = call.base.base.toa,
+ .isMpty = call.base.base.isMpty,
+ .isMT = call.base.base.isMT,
+ .als = static_cast<int8_t>(call.base.base.als),
+ .isVoice = call.base.base.isVoice,
+ .isVoicePrivacy = call.base.base.isVoicePrivacy,
+ .number = call.base.base.number,
+ .numberPresentation = static_cast<int32_t>(call.base.base.numberPresentation),
+ .name = call.base.base.name,
+ .namePresentation = static_cast<int32_t>(call.base.base.namePresentation),
+ .uusInfo = toAidl(call.base.base.uusInfo),
+ .audioQuality = aidl::AudioQuality(call.base.audioQuality),
+ .forwardedNumber = call.forwardedNumber,
+ };
+}
+
+aidl::UusInfo toAidl(const V1_0::UusInfo& info) {
+ return {
+ .uusType = static_cast<int32_t>(info.uusType),
+ .uusDcs = static_cast<int32_t>(info.uusDcs),
+ .uusData = info.uusData,
+ };
+}
+
+aidl::LastCallFailCauseInfo toAidl(const V1_0::LastCallFailCauseInfo& info) {
+ return {
+ .causeCode = aidl::LastCallFailCause(info.causeCode),
+ .vendorCause = info.vendorCause,
+ };
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.h b/radio/aidl/compat/libradiocompat/voice/structs.h
new file mode 100644
index 0000000..b55a089
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/voice/Call.h>
+#include <aidl/android/hardware/radio/voice/CallForwardInfo.h>
+#include <aidl/android/hardware/radio/voice/CdmaCallWaiting.h>
+#include <aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaInformationRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CfData.h>
+#include <aidl/android/hardware/radio/voice/Dial.h>
+#include <aidl/android/hardware/radio/voice/EmergencyNumber.h>
+#include <aidl/android/hardware/radio/voice/LastCallFailCauseInfo.h>
+#include <aidl/android/hardware/radio/voice/SsInfoData.h>
+#include <aidl/android/hardware/radio/voice/StkCcUnsolSsResult.h>
+#include <aidl/android/hardware/radio/voice/UusInfo.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::Dial toHidl(const ::aidl::android::hardware::radio::voice::Dial& info);
+
+V1_0::UusInfo toHidl(const ::aidl::android::hardware::radio::voice::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info);
+V1_0::CallForwardInfo toHidl(const ::aidl::android::hardware::radio::voice::CallForwardInfo& info);
+
+::aidl::android::hardware::radio::voice::CdmaSignalInfoRecord //
+toAidl(const V1_0::CdmaSignalInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call);
+
+::aidl::android::hardware::radio::voice::CdmaInformationRecord //
+toAidl(const V1_0::CdmaInformationRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaDisplayInfoRecord //
+toAidl(const V1_0::CdmaDisplayInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaNumberInfoRecord //
+toAidl(const V1_0::CdmaNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaRedirectingNumberInfoRecord //
+toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaLineControlInfoRecord //
+toAidl(const V1_0::CdmaLineControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53ClirInfoRecord //
+toAidl(const V1_0::CdmaT53ClirInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53AudioControlInfoRecord //
+toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num);
+
+::aidl::android::hardware::radio::voice::StkCcUnsolSsResult //
+toAidl(const V1_0::StkCcUnsolSsResult& res);
+
+::aidl::android::hardware::radio::voice::SsInfoData toAidl(const V1_0::SsInfoData& info);
+
+::aidl::android::hardware::radio::voice::CfData toAidl(const V1_0::CfData& data);
+
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_0::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_2::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_6::Call& call);
+
+::aidl::android::hardware::radio::voice::UusInfo toAidl(const V1_0::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::LastCallFailCauseInfo //
+toAidl(const V1_0::LastCallFailCauseInfo& info);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
new file mode 100644
index 0000000..52eb71f
--- /dev/null
+++ b/radio/aidl/compat/service/Android.bp
@@ -0,0 +1,64 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+ name: "android.hardware.radio-service.compat",
+ relative_install_path: "hw",
+ init_rc: ["radio-compat.rc"],
+ vintf_fragments: ["radio-compat.xml"],
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ ],
+ shared_libs: [
+ "android.hardware.radio-library.compat",
+ "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.config@1.0",
+ "android.hardware.radio.config@1.1",
+ "android.hardware.radio.config@1.2",
+ "android.hardware.radio.config@1.3",
+ "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.messaging-V1-ndk",
+ "android.hardware.radio.modem-V1-ndk",
+ "android.hardware.radio.network-V1-ndk",
+ "android.hardware.radio.sim-V1-ndk",
+ "android.hardware.radio.voice-V1-ndk",
+ "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.hardware.radio@1.6",
+ "libbase",
+ "libbinder_ndk",
+ "libhidlbase",
+ "libutils",
+ ],
+ srcs: [
+ "hidl-utils.cpp",
+ "service.cpp",
+ ],
+}
diff --git a/radio/aidl/compat/service/hidl-utils.cpp b/radio/aidl/compat/service/hidl-utils.cpp
new file mode 100644
index 0000000..fc0d54d
--- /dev/null
+++ b/radio/aidl/compat/service/hidl-utils.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "hidl-utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+
+namespace android::hardware::hidl_utils {
+
+class HalDeathRecipient : public hidl_death_recipient {
+ void serviceDied(uint64_t /* cookie */, const wp<hidl::base::V1_0::IBase>& /* who */) override {
+ LOG(FATAL) << "One of the linked HALs died. Restarting...";
+ }
+};
+
+static const auto gHalDeathRecipient = sp<HalDeathRecipient>::make();
+
+void linkDeathToDeath(sp<::android::hidl::base::V1_0::IBase> hal) {
+ const auto linkStatus = hal->linkToDeath(gHalDeathRecipient, 0);
+ CHECK(linkStatus.withDefault(false)) << "Failed to link to HAL death";
+}
+
+hidl_vec<hidl_string> listManifestByInterface(const char* descriptor) {
+ auto manager = hidl::manager::V1_2::IServiceManager::getService();
+ hidl_vec<hidl_string> services;
+ manager->listManifestByInterface(descriptor, hidl_utils::fill(&services));
+ CHECK_GT(services.size(), 0u) << "No " << descriptor
+ << " services in manifest (missing privileges?)" << std::endl;
+ return services;
+}
+
+} // namespace android::hardware::hidl_utils
diff --git a/radio/aidl/compat/service/hidl-utils.h b/radio/aidl/compat/service/hidl-utils.h
new file mode 100644
index 0000000..be3386f
--- /dev/null
+++ b/radio/aidl/compat/service/hidl-utils.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/hidl/base/1.0/IBase.h>
+
+#include <functional>
+
+namespace android::hardware::hidl_utils {
+
+/**
+ * Helper functor to fetch results from multi-return HIDL calls.
+ * It's meant to be used in place of _hidl_cb callbacks.
+ *
+ * Please note extracting these return variables outside of the callback scope requires making
+ * a copy of each return variable. This may be costly for frequently called HIDL methods with
+ * non-negligible return object size. Please be cautious about performance when using this.
+ *
+ * Example usage:
+ * Result result;
+ * sp<ISomeInterface> iface;
+ * hidlObject->someMethod(arg1, arg2, hidl_utils::fill(&result, &iface)).assertOk();
+ * // use result and iface
+ */
+template <typename... T>
+struct fill : public std::function<void(const T&...)> {
+ /**
+ * Create _hidl_cb functor that copies the call arguments to specified pointers.
+ *
+ * \param args... Targets to copy the call arguments to
+ */
+ fill(T*... args) : mTargets(args...) {}
+
+ void operator()(const T&... args) { copy<0, T...>(args...); }
+
+ private:
+ std::tuple<T*...> mTargets;
+
+ template <int Pos, typename First>
+ inline void copy(const First& first) {
+ *std::get<Pos>(mTargets) = first;
+ }
+
+ template <int Pos, typename First, typename... Rest>
+ inline void copy(const First& first, const Rest&... rest) {
+ *std::get<Pos>(mTargets) = first;
+ copy<Pos + 1, Rest...>(rest...);
+ }
+};
+
+/**
+ * Link to a given HALs death and restart the current process in such a case.
+ * \param hal HAL to which death to link
+ */
+void linkDeathToDeath(sp<hidl::base::V1_0::IBase> hal);
+
+/**
+ * List HAL instances of a given interface.
+ *
+ * \descriptor HIDL HAL descriptor
+ */
+hidl_vec<hidl_string> listManifestByInterface(const char* descriptor);
+
+} // namespace android::hardware::hidl_utils
diff --git a/radio/aidl/compat/service/radio-compat.rc b/radio/aidl/compat/service/radio-compat.rc
new file mode 100644
index 0000000..a159876
--- /dev/null
+++ b/radio/aidl/compat/service/radio-compat.rc
@@ -0,0 +1,4 @@
+service vendor.radio-compat /vendor/bin/hw/android.hardware.radio-service.compat
+ class hal
+ user nobody
+ group system
diff --git a/radio/aidl/compat/service/radio-compat.xml b/radio/aidl/compat/service/radio-compat.xml
new file mode 100644
index 0000000..a7089e6
--- /dev/null
+++ b/radio/aidl/compat/service/radio-compat.xml
@@ -0,0 +1,37 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.radio.config</name>
+ <fqname>IRadioConfig/default</fqname>
+ </hal>
+<!--
+ Instances other than config are configured per-device, depending on the slot count (framework
+ currently supports slot1, slot2 and slot3 instances) and Radio HALs device wishes to provide.
+ You can either copy the following tags to device manifest or simply uncomment them here for
+ quick testing.
+
+ <hal format="aidl">
+ <name>android.hardware.radio.data</name>
+ <fqname>IRadioData/slot1</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.radio.messaging</name>
+ <fqname>IRadioMessaging/slot1</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.radio.modem</name>
+ <fqname>IRadioModem/slot1</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.radio.network</name>
+ <fqname>IRadioNetwork/slot1</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.radio.sim</name>
+ <fqname>IRadioSim/slot1</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.radio.voice</name>
+ <fqname>IRadioVoice/slot1</fqname>
+ </hal>
+-->
+</manifest>
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
new file mode 100644
index 0000000..8af05de
--- /dev/null
+++ b/radio/aidl/compat/service/service.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "hidl-utils.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <libradiocompat/CallbackManager.h>
+#include <libradiocompat/RadioConfig.h>
+#include <libradiocompat/RadioData.h>
+#include <libradiocompat/RadioMessaging.h>
+#include <libradiocompat/RadioModem.h>
+#include <libradiocompat/RadioNetwork.h>
+#include <libradiocompat/RadioSim.h>
+#include <libradiocompat/RadioVoice.h>
+
+namespace android::hardware::radio::service {
+
+using namespace std::string_literals;
+
+static std::vector<std::shared_ptr<ndk::ICInterface>> gPublishedHals;
+
+template <typename T>
+static void publishRadioHal(std::shared_ptr<compat::DriverContext> ctx, sp<V1_5::IRadio> hidlHal,
+ std::shared_ptr<compat::CallbackManager> cm, const std::string& slot) {
+ const auto instance = T::descriptor + "/"s + slot;
+ if (!AServiceManager_isDeclared(instance.c_str())) {
+ LOG(INFO) << instance << " is not declared in VINTF (this may be intentional)";
+ return;
+ }
+ LOG(DEBUG) << "Publishing " << instance;
+
+ auto aidlHal = ndk::SharedRefBase::make<T>(ctx, hidlHal, cm);
+ gPublishedHals.push_back(aidlHal);
+ const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+}
+
+static void publishRadio(std::string slot) {
+ auto radioHidl = V1_5::IRadio::getService(slot);
+ CHECK(radioHidl) << "HIDL IRadio not present in VINTF";
+
+ hidl_utils::linkDeathToDeath(radioHidl);
+
+ auto context = std::make_shared<compat::DriverContext>();
+ auto callbackMgr = std::make_shared<compat::CallbackManager>(context, radioHidl);
+
+ publishRadioHal<compat::RadioData>(context, radioHidl, callbackMgr, slot);
+ publishRadioHal<compat::RadioMessaging>(context, radioHidl, callbackMgr, slot);
+ publishRadioHal<compat::RadioModem>(context, radioHidl, callbackMgr, slot);
+ publishRadioHal<compat::RadioNetwork>(context, radioHidl, callbackMgr, slot);
+ publishRadioHal<compat::RadioSim>(context, radioHidl, callbackMgr, slot);
+ publishRadioHal<compat::RadioVoice>(context, radioHidl, callbackMgr, slot);
+}
+
+static void publishRadioConfig() {
+ auto hidlHal = config::V1_1::IRadioConfig::getService();
+ CHECK(hidlHal) << "HIDL IRadioConfig not present in VINTF";
+
+ hidl_utils::linkDeathToDeath(hidlHal);
+
+ auto aidlHal = ndk::SharedRefBase::make<compat::RadioConfig>(hidlHal);
+ gPublishedHals.push_back(aidlHal);
+ const auto instance = compat::RadioConfig::descriptor + "/default"s;
+ const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+}
+
+static void main() {
+ base::InitLogging(nullptr, base::LogdLogger(base::RADIO));
+ base::SetDefaultTag("radiocompat");
+ base::SetMinimumLogSeverity(base::VERBOSE);
+ LOG(DEBUG) << "Radio HAL compat service starting...";
+
+ publishRadioConfig();
+
+ const auto slots = hidl_utils::listManifestByInterface(V1_0::IRadio::descriptor);
+ LOG(INFO) << "Found " << slots.size() << " slot(s)";
+ for (const auto& slot : slots) {
+ publishRadio(slot);
+ }
+
+ LOG(DEBUG) << "Radio HAL compat service is operational";
+ ABinderProcess_joinThreadPool();
+ LOG(FATAL) << "Radio HAL compat service has stopped";
+}
+
+} // namespace android::hardware::radio::service
+
+int main() {
+ android::hardware::radio::service::main();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
new file mode 100644
index 0000000..8f28255
--- /dev/null
+++ b/radio/aidl/vts/Android.bp
@@ -0,0 +1,80 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalRadioTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ tidy_timeout_srcs: [
+ "radio_messaging_test.cpp",
+ "radio_network_test.cpp",
+ "radio_sim_test.cpp",
+ "radio_voice_test.cpp",
+ ],
+ srcs: [
+ "radio_aidl_hal_utils.cpp",
+ "radio_config_indication.cpp",
+ "radio_config_response.cpp",
+ "radio_config_test.cpp",
+ "radio_data_indication.cpp",
+ "radio_data_response.cpp",
+ "radio_data_test.cpp",
+ "radio_messaging_indication.cpp",
+ "radio_messaging_response.cpp",
+ "radio_messaging_test.cpp",
+ "radio_modem_indication.cpp",
+ "radio_modem_response.cpp",
+ "radio_modem_test.cpp",
+ "radio_network_indication.cpp",
+ "radio_network_response.cpp",
+ "radio_network_test.cpp",
+ "radio_sim_indication.cpp",
+ "radio_sim_response.cpp",
+ "radio_sim_test.cpp",
+ "radio_voice_indication.cpp",
+ "radio_voice_response.cpp",
+ "radio_voice_test.cpp",
+ "VtsHalRadioTargetTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libvintf",
+ ],
+ static_libs: [
+ "android.hardware.radio-V1-ndk",
+ "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.data-V1-ndk",
+ "android.hardware.radio.messaging-V1-ndk",
+ "android.hardware.radio.modem-V1-ndk",
+ "android.hardware.radio.network-V1-ndk",
+ "android.hardware.radio.sim-V1-ndk",
+ "android.hardware.radio.voice-V1-ndk",
+ ],
+ // TODO(b/210712359): enable after b/207695009 is resolved.
+ //test_suites: [
+ // "general-tests",
+ // "vts",
+ //],
+}
diff --git a/radio/aidl/vts/OWNERS b/radio/aidl/vts/OWNERS
new file mode 100644
index 0000000..e75c6c8
--- /dev/null
+++ b/radio/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../../1.0/vts/OWNERS
+
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
new file mode 100644
index 0000000..1ebc6af
--- /dev/null
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/binder_process.h>
+
+#include "radio_config_utils.h"
+#include "radio_data_utils.h"
+#include "radio_messaging_utils.h"
+#include "radio_modem_utils.h"
+#include "radio_network_utils.h"
+#include "radio_sim_utils.h"
+#include "radio_voice_utils.h"
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioConfigTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioConfig::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioDataTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioDataTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioData::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioMessagingTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioMessagingTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioMessaging::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioModemTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioModemTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioModem::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioNetworkTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioNetworkTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioNetwork::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSimTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioSimTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioSim::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioVoiceTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioVoiceTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioVoice::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
new file mode 100644
index 0000000..dc61a3c
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "radio_aidl_hal_utils.h"
+#include <iostream>
+#include "VtsCoreUtil.h"
+#include "radio_config_utils.h"
+#include "radio_sim_utils.h"
+
+#define WAIT_TIMEOUT_PERIOD 75
+
+sim::CardStatus cardStatus = {};
+int serial = 0;
+int count_ = 0;
+
+int GetRandomSerialNumber() {
+ return rand();
+}
+
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> errors,
+ CheckFlag flag) {
+ const static std::vector<RadioError> generalErrors = {
+ RadioError::RADIO_NOT_AVAILABLE, RadioError::NO_MEMORY,
+ RadioError::INTERNAL_ERR, RadioError::SYSTEM_ERR,
+ RadioError::REQUEST_NOT_SUPPORTED, 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 >= RadioError::OEM_ERROR_1 && err <= 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";
+}
+
+// Runs "pm list features" and attempts to find the specified feature in its output.
+bool deviceSupportsFeature(const char* feature) {
+ bool hasFeature = false;
+ FILE* p = popen("/system/bin/pm list features", "re");
+ if (p) {
+ char* line = NULL;
+ size_t len = 0;
+ while (getline(&line, &len, p) > 0) {
+ if (strstr(line, feature)) {
+ hasFeature = true;
+ break;
+ }
+ }
+ pclose(p);
+ } else {
+ __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "popen failed: %d", errno);
+ _exit(EXIT_FAILURE);
+ }
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported", feature,
+ hasFeature ? "" : "not ");
+ return hasFeature;
+}
+
+bool isSsSsEnabled() {
+ // Do not use checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "")
+ // until b/148904287 is fixed. We need exact matching instead of partial matching. (i.e.
+ // by definition the empty string "" is a substring of any string).
+ return !isDsDsEnabled() && !isTsTsEnabled();
+}
+
+bool isDsDsEnabled() {
+ return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds");
+}
+
+bool isTsTsEnabled() {
+ return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
+}
+
+bool isVoiceInService(RegState state) {
+ return RegState::REG_HOME == state || RegState::REG_ROAMING == state;
+}
+
+bool isVoiceEmergencyOnly(RegState state) {
+ return RegState::NOT_REG_MT_NOT_SEARCHING_OP_EM == state ||
+ RegState::NOT_REG_MT_SEARCHING_OP_EM == state || RegState::REG_DENIED_EM == state ||
+ RegState::UNKNOWN_EM == state;
+}
+
+bool stringEndsWith(std::string const& string, std::string const& end) {
+ if (string.size() >= end.size()) {
+ return (0 == string.compare(string.size() - end.size() - 1, end.size(), end));
+ } else {
+ return false;
+ }
+}
+
+bool isServiceValidForDeviceConfiguration(std::string& serviceName) {
+ if (isSsSsEnabled()) {
+ // Device is configured as SSSS.
+ if (stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME)) {
+ ALOGI("%s instance is not valid for SSSS device.", serviceName.c_str());
+ return false;
+ }
+ } else if (isDsDsEnabled()) {
+ // Device is configured as DSDS.
+ if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME)) {
+ ALOGI("%s instance is not valid for DSDS device.", serviceName.c_str());
+ return false;
+ }
+ } else if (isTsTsEnabled()) {
+ // Device is configured as TSTS.
+ if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT3_NAME)) {
+ ALOGI("%s instance is not valid for TSTS device.", serviceName.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioServiceTest::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 WAIT_TIMEOUT_PERIOD.
+ */
+std::cv_status RadioServiceTest::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(WAIT_TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) {
+ return status;
+ }
+ }
+ count_--;
+ return status;
+}
+
+/**
+ * Specific features on the Radio HAL rely on Radio HAL Capabilities.
+ * The VTS test related to those features must not run if the related capability is disabled.
+ * Typical usage within VTS:
+ * if (getRadioHalCapabilities()) return;
+ */
+bool RadioServiceTest::getRadioHalCapabilities() {
+ // Get HalDeviceCapabilities from RadioConfig
+ std::shared_ptr<RadioConfigResponse> radioConfigRsp =
+ ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+ std::shared_ptr<RadioConfigIndication> radioConfigInd =
+ ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+ radio_config->setResponseFunctions(radioConfigRsp, radioConfigInd);
+ serial = GetRandomSerialNumber();
+ radio_config->getHalDeviceCapabilities(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ return radioConfigRsp->modemReducedFeatureSet1;
+}
+
+/**
+ * Some VTS tests require the SIM card status to be present before running.
+ * Update the SIM card status, which can be accessed via the extern cardStatus.
+ */
+void RadioServiceTest::updateSimCardStatus() {
+ // Update CardStatus from RadioSim
+ std::shared_ptr<RadioSimResponse> radioSimRsp =
+ ndk::SharedRefBase::make<RadioSimResponse>(*this);
+ std::shared_ptr<RadioSimIndication> radioSimInd =
+ ndk::SharedRefBase::make<RadioSimIndication>(*this);
+ radio_sim->setResponseFunctions(radioSimRsp, radioSimInd);
+ serial = GetRandomSerialNumber();
+ radio_sim->getIccCardStatus(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioSimRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioSimRsp->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioSimRsp->rspInfo.error);
+}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
new file mode 100644
index 0000000..414ffbc
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/radio/RadioError.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/network/RegState.h>
+#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
+#include <utils/Log.h>
+#include <vector>
+
+using namespace aidl::android::hardware::radio;
+using aidl::android::hardware::radio::network::RegState;
+using aidl::android::hardware::radio::sim::CardStatus;
+
+extern CardStatus cardStatus;
+extern int serial;
+extern int count_;
+
+/*
+ * MACRO used to skip test case when radio response return error REQUEST_NOT_SUPPORTED
+ * on HAL versions which has deprecated the request interfaces. The MACRO can only be used
+ * AFTER receiving radio response.
+ */
+#define SKIP_TEST_IF_REQUEST_NOT_SUPPORTED_WITH_HAL(__ver__, __radio__, __radioRsp__) \
+ do { \
+ sp<::android::hardware::radio::V##__ver__::IRadio> __radio = \
+ ::android::hardware::radio::V##__ver__::IRadio::castFrom(__radio__); \
+ if (__radio && __radioRsp__->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED) { \
+ GTEST_SKIP() << "REQUEST_NOT_SUPPORTED"; \
+ } \
+ } while (0)
+
+enum CheckFlag {
+ CHECK_DEFAULT = 0,
+ CHECK_GENERAL_ERROR = 1,
+ CHECK_OEM_ERROR = 2,
+ CHECK_OEM_AND_GENERAL_ERROR = 3,
+ CHECK_SAP_ERROR = 4,
+};
+
+static constexpr const char* FEATURE_VOICE_CALL = "android.software.connectionservice";
+
+static constexpr const char* FEATURE_TELEPHONY = "android.hardware.telephony";
+
+static constexpr const char* FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
+
+static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
+
+#define RADIO_SERVICE_SLOT1_NAME "slot1" // HAL instance name for SIM slot 1 or single SIM device
+#define RADIO_SERVICE_SLOT2_NAME "slot2" // HAL instance name for SIM slot 2 on dual SIM device
+#define RADIO_SERVICE_SLOT3_NAME "slot3" // HAL instance name for SIM slot 3 on triple SIM device
+
+/*
+ * Generate random serial number for radio test
+ */
+int GetRandomSerialNumber();
+
+/*
+ * 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(RadioError err, std::vector<RadioError> generalError,
+ CheckFlag flag = CHECK_DEFAULT);
+
+/*
+ * Check if device supports feature.
+ */
+bool deviceSupportsFeature(const char* feature);
+
+/*
+ * Check if device is in SsSs (Single SIM Single Standby).
+ */
+bool isSsSsEnabled();
+
+/*
+ * Check if device is in DSDS (Dual SIM Dual Standby).
+ */
+bool isDsDsEnabled();
+
+/*
+ * Check if device is in TSTS (Triple SIM Triple Standby).
+ */
+bool isTsTsEnabled();
+
+/*
+ * Check if voice status is in emergency only.
+ */
+bool isVoiceEmergencyOnly(RegState state);
+
+/*
+ * Check if voice status is in service.
+ */
+bool isVoiceInService(RegState state);
+
+/*
+ * Check if service is valid for device configuration
+ */
+bool isServiceValidForDeviceConfiguration(std::string& serviceName);
+
+/**
+ * RadioServiceTest base class
+ */
+class RadioServiceTest {
+ protected:
+ std::mutex mtx_;
+ std::condition_variable cv_;
+ std::shared_ptr<config::IRadioConfig> radio_config;
+ std::shared_ptr<sim::IRadioSim> radio_sim;
+
+ public:
+ /* 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();
+
+ /* Get the radio HAL capabilities */
+ bool getRadioHalCapabilities();
+
+ /* Update SIM card status */
+ void updateSimCardStatus();
+};
diff --git a/radio/aidl/vts/radio_config_indication.cpp b/radio/aidl/vts/radio_config_indication.cpp
new file mode 100644
index 0000000..a84c20b
--- /dev/null
+++ b/radio/aidl/vts/radio_config_indication.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_config_utils.h"
+
+RadioConfigIndication::RadioConfigIndication(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigIndication::simSlotsStatusChanged(
+ RadioIndicationType /*type*/, const std::vector<SimSlotStatus>& /*slotStatus*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_response.cpp b/radio/aidl/vts/radio_config_response.cpp
new file mode 100644
index 0000000..8d81605
--- /dev/null
+++ b/radio/aidl/vts/radio_config_response.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_config_utils.h"
+
+RadioConfigResponse::RadioConfigResponse(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigResponse::getSimSlotsStatusResponse(
+ const RadioResponseInfo& info, const std::vector<SimSlotStatus>& /* slotStatus */) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getPhoneCapabilityResponse(
+ const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+ rspInfo = info;
+ phoneCap = phoneCapability;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setPreferredDataModemResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getNumOfLiveModemsResponse(
+ const RadioResponseInfo& info, const int8_t /* numOfLiveModems */) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setNumOfLiveModemsResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+ const RadioResponseInfo& info, bool modemReducedFeatures) {
+ rspInfo = info;
+ modemReducedFeatureSet1 = modemReducedFeatures;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
new file mode 100644
index 0000000..a271b8a
--- /dev/null
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_config_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioConfigTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_config = IRadioConfig::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_config.get());
+
+ radioRsp_config = ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_config.get());
+
+ count_ = 0;
+
+ radioInd_config = ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_config.get());
+
+ radio_config->setResponseFunctions(radioRsp_config, radioInd_config);
+}
+
+/*
+ * Test IRadioConfig.getHalDeviceCapabilities() for the response returned.
+ */
+TEST_P(RadioConfigTest, getHalDeviceCapabilities) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getHalDeviceCapabilities(serial);
+ ASSERT_OK(res);
+ ALOGI("getHalDeviceCapabilities, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+}
+
+/*
+ * Test IRadioConfig.getSimSlotsStatus() for the response returned.
+ */
+TEST_P(RadioConfigTest, getSimSlotsStatus) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getSimSlotsStatus(serial);
+ ASSERT_OK(res);
+ ALOGI("getSimSlotsStatus, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+}
+
+/*
+ * Test IRadioConfig.getPhoneCapability() for the response returned.
+ */
+TEST_P(RadioConfigTest, getPhoneCapability) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getPhoneCapability(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+ ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_config->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioRsp_config->rspInfo.error == RadioError ::NONE) {
+ // maxActiveData should be greater than or equal to maxActiveInternetData.
+ EXPECT_GE(radioRsp_config->phoneCap.maxActiveData,
+ radioRsp_config->phoneCap.maxActiveInternetData);
+ // maxActiveData and maxActiveInternetData should be 0 or positive numbers.
+ EXPECT_GE(radioRsp_config->phoneCap.maxActiveInternetData, 0);
+ }
+}
+
+/*
+ * Test IRadioConfig.setPreferredDataModem() for the response returned.
+ */
+TEST_P(RadioConfigTest, setPreferredDataModem) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getPhoneCapability(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+ ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_config->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioRsp_config->rspInfo.error != RadioError ::NONE) {
+ return;
+ }
+
+ if (radioRsp_config->phoneCap.logicalModemIds.size() == 0) {
+ return;
+ }
+
+ // We get phoneCapability. Send setPreferredDataModem command
+ serial = GetRandomSerialNumber();
+ uint8_t modemId = radioRsp_config->phoneCap.logicalModemIds[0];
+ res = radio_config->setPreferredDataModem(serial, modemId);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+ ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_config->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+}
+
+/*
+ * Test IRadioConfig.setPreferredDataModem() with invalid arguments.
+ */
+TEST_P(RadioConfigTest, setPreferredDataModem_invalidArgument) {
+ serial = GetRandomSerialNumber();
+ uint8_t modemId = -1;
+ ndk::ScopedAStatus res = radio_config->setPreferredDataModem(serial, modemId);
+
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+ ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_config->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INTERNAL_ERR}));
+}
diff --git a/radio/aidl/vts/radio_config_utils.h b/radio/aidl/vts/radio_config_utils.h
new file mode 100644
index 0000000..465c106
--- /dev/null
+++ b/radio/aidl/vts/radio_config_utils.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/config/BnRadioConfigIndication.h>
+#include <aidl/android/hardware/radio/config/BnRadioConfigResponse.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::config;
+
+class RadioConfigTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public BnRadioConfigResponse {
+ protected:
+ RadioServiceTest& parent_config;
+
+ public:
+ RadioConfigResponse(RadioServiceTest& parent_config);
+ virtual ~RadioConfigResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ PhoneCapability phoneCap;
+ bool modemReducedFeatureSet1;
+
+ virtual ndk::ScopedAStatus getSimSlotsStatusResponse(
+ const RadioResponseInfo& info, const std::vector<SimSlotStatus>& slotStatus) override;
+
+ virtual ndk::ScopedAStatus setSimSlotsMappingResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getPhoneCapabilityResponse(
+ const RadioResponseInfo& info, const PhoneCapability& phoneCapability) override;
+
+ virtual ndk::ScopedAStatus setPreferredDataModemResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getNumOfLiveModemsResponse(const RadioResponseInfo& info,
+ const int8_t numOfLiveModems) override;
+
+ virtual ndk::ScopedAStatus setNumOfLiveModemsResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getHalDeviceCapabilitiesResponse(
+ const RadioResponseInfo& info, bool modemReducedFeatureSet1) override;
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public BnRadioConfigIndication {
+ protected:
+ RadioServiceTest& parent_config;
+
+ public:
+ RadioConfigIndication(RadioServiceTest& parent_config);
+ virtual ~RadioConfigIndication() = default;
+
+ virtual ndk::ScopedAStatus simSlotsStatusChanged(
+ RadioIndicationType type, const std::vector<SimSlotStatus>& slotStatus) override;
+};
+
+// The main test class for Radio AIDL Config.
+class RadioConfigTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+ ndk::ScopedAStatus updateSimCardStatus();
+
+ /* radio config service handle in RadioServiceTest */
+ /* radio config response handle */
+ std::shared_ptr<RadioConfigResponse> radioRsp_config;
+ /* radio config indication handle */
+ std::shared_ptr<RadioConfigIndication> radioInd_config;
+};
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
new file mode 100644
index 0000000..61e079e
--- /dev/null
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_data_utils.h"
+
+RadioDataIndication::RadioDataIndication(RadioServiceTest& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataIndication::dataCallListChanged(
+ RadioIndicationType /*type*/, const std::vector<SetupDataCallResult>& /*dcList*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::keepaliveStatus(RadioIndicationType /*type*/,
+ const KeepaliveStatus& /*status*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::pcoData(RadioIndicationType /*type*/,
+ const PcoDataInfo& /*pco*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::unthrottleApn(RadioIndicationType /*type*/,
+ const DataProfileInfo& /*dataProfileInfo*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::slicingConfigChanged(
+ RadioIndicationType /*type*/, const SlicingConfig& /*slicingConfig*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_response.cpp b/radio/aidl/vts/radio_data_response.cpp
new file mode 100644
index 0000000..8d51760
--- /dev/null
+++ b/radio/aidl/vts/radio_data_response.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_data_utils.h"
+
+RadioDataResponse::RadioDataResponse(RadioServiceTest& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::allocatePduSessionIdResponse(const RadioResponseInfo& info,
+ int32_t id) {
+ rspInfo = info;
+ allocatedPduSessionId = id;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::cancelHandoverResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::deactivateDataCallResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getDataCallListResponse(
+ const RadioResponseInfo& info, const std::vector<SetupDataCallResult>& /*dcResponse*/) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getSlicingConfigResponse(
+ const RadioResponseInfo& info, const SlicingConfig& /*slicingConfig*/) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::releasePduSessionIdResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataAllowedResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataProfileResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataThrottlingResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setInitialAttachApnResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setupDataCallResponse(const RadioResponseInfo& info,
+ const SetupDataCallResult& dcResponse) {
+ rspInfo = info;
+ setupDataCallResult = dcResponse;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startHandoverResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startKeepaliveResponse(const RadioResponseInfo& info,
+ const KeepaliveStatus& /*status*/) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::stopKeepaliveResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_data.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp
new file mode 100644
index 0000000..f38a958
--- /dev/null
+++ b/radio/aidl/vts/radio_data_test.cpp
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/data/ApnTypes.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_data_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioDataTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_data = IRadioData::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_data.get());
+
+ radioRsp_data = ndk::SharedRefBase::make<RadioDataResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_data.get());
+
+ count_ = 0;
+
+ radioInd_data = ndk::SharedRefBase::make<RadioDataIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_data.get());
+
+ radio_data->setResponseFunctions(radioRsp_data, radioInd_data);
+
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+}
+
+ndk::ScopedAStatus RadioDataTest::getDataCallList() {
+ serial = GetRandomSerialNumber();
+ radio_data->getDataCallList(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioData.setupDataCall() for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall) {
+ serial = GetRandomSerialNumber();
+
+ AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+ DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+ dataProfileInfo.apn = std::string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IP;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = std::string("username");
+ dataProfileInfo.password = std::string("password");
+ dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+ dataProfileInfo.maxConnsTime = 300;
+ dataProfileInfo.maxConns = 20;
+ dataProfileInfo.waitTime = 0;
+ dataProfileInfo.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap =
+ static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+ dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+ static_cast<int32_t>(RadioAccessFamily::EDGE) |
+ static_cast<int32_t>(RadioAccessFamily::UMTS) |
+ static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSPA) |
+ static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+ static_cast<int32_t>(RadioAccessFamily::LTE) |
+ static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+ static_cast<int32_t>(RadioAccessFamily::IWLAN);
+ dataProfileInfo.mtuV4 = 0;
+ dataProfileInfo.mtuV6 = 0;
+ dataProfileInfo.preferred = true;
+ dataProfileInfo.persistent = false;
+
+ bool roamingAllowed = false;
+
+ std::vector<LinkAddress> addresses = {};
+ std::vector<std::string> dnses = {};
+
+ DataRequestReason reason = DataRequestReason::NORMAL;
+ SliceInfo sliceInfo;
+ bool matchAllRuleAllowed = true;
+
+ ndk::ScopedAStatus res =
+ radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+ reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ }
+}
+
+/*
+ * Test IRadioData.setupDataCall() with osAppId for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall_osAppId) {
+ serial = GetRandomSerialNumber();
+
+ AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+ TrafficDescriptor trafficDescriptor;
+ OsAppId osAppId;
+ std::string osAppIdString("osAppId");
+ std::vector<unsigned char> osAppIdVec(osAppIdString.begin(), osAppIdString.end());
+ osAppId.osAppId = osAppIdVec;
+ trafficDescriptor.osAppId = osAppId;
+
+ DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+ dataProfileInfo.apn = std::string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IP;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = std::string("username");
+ dataProfileInfo.password = std::string("password");
+ dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+ dataProfileInfo.maxConnsTime = 300;
+ dataProfileInfo.maxConns = 20;
+ dataProfileInfo.waitTime = 0;
+ dataProfileInfo.enabled = true;
+ dataProfileInfo.supportedApnTypesBitmap =
+ static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+ dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+ static_cast<int32_t>(RadioAccessFamily::EDGE) |
+ static_cast<int32_t>(RadioAccessFamily::UMTS) |
+ static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSPA) |
+ static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+ static_cast<int32_t>(RadioAccessFamily::LTE) |
+ static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+ static_cast<int32_t>(RadioAccessFamily::IWLAN);
+ dataProfileInfo.mtuV4 = 0;
+ dataProfileInfo.mtuV6 = 0;
+ dataProfileInfo.preferred = true;
+ dataProfileInfo.persistent = false;
+ dataProfileInfo.trafficDescriptor = trafficDescriptor;
+
+ bool roamingAllowed = false;
+
+ std::vector<LinkAddress> addresses = {};
+ std::vector<std::string> dnses = {};
+
+ DataRequestReason reason = DataRequestReason::NORMAL;
+ SliceInfo sliceInfo;
+ bool matchAllRuleAllowed = true;
+
+ ndk::ScopedAStatus res =
+ radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+ reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+ if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0) {
+ return;
+ }
+ EXPECT_EQ(trafficDescriptor.osAppId.value().osAppId,
+ radioRsp_data->setupDataCallResult.trafficDescriptors[0].osAppId.value().osAppId);
+ }
+}
+
+/*
+ * Test IRadioData.getSlicingConfig() for the response returned.
+ */
+TEST_P(RadioDataTest, getSlicingConfig) {
+ serial = GetRandomSerialNumber();
+ radio_data->getSlicingConfig(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INTERNAL_ERR, RadioError::MODEM_ERR}));
+ }
+}
+
+/*
+ * Test IRadioData.setDataThrottling() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataThrottling) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_data->setDataThrottling(
+ serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60000);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+ RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+
+ sleep(1);
+ serial = GetRandomSerialNumber();
+
+ res = radio_data->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
+ 60000);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+ RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+
+ sleep(1);
+ serial = GetRandomSerialNumber();
+
+ res = radio_data->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+ RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+
+ sleep(1);
+ serial = GetRandomSerialNumber();
+
+ res = radio_data->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+ RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+ }
+
+ sleep(1);
+}
+
+/*
+ * Test IRadioData.setInitialAttachApn() for the response returned.
+ */
+TEST_P(RadioDataTest, setInitialAttachApn) {
+ serial = GetRandomSerialNumber();
+
+ // Create a dataProfileInfo
+ DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+ dataProfileInfo.apn = std::string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = std::string("username");
+ dataProfileInfo.password = std::string("password");
+ dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+ 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;
+
+ radio_data->setInitialAttachApn(serial, dataProfileInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
+
+/*
+ * Test IRadioData.setDataProfile() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataProfile) {
+ serial = GetRandomSerialNumber();
+
+ // Create a dataProfileInfo
+ DataProfileInfo dataProfileInfo;
+ memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+ dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+ dataProfileInfo.apn = std::string("internet");
+ dataProfileInfo.protocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6;
+ dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+ dataProfileInfo.user = std::string("username");
+ dataProfileInfo.password = std::string("password");
+ dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+ 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 = true;
+
+ // Create a dataProfileInfoList
+ std::vector<DataProfileInfo> dataProfileInfoList = {dataProfileInfo};
+
+ radio_data->setDataProfile(serial, dataProfileInfoList);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
+
+/*
+ * Test IRadioData.deactivateDataCall() for the response returned.
+ */
+TEST_P(RadioDataTest, deactivateDataCall) {
+ serial = GetRandomSerialNumber();
+ int cid = 1;
+ DataRequestReason reason = DataRequestReason::NORMAL;
+
+ ndk::ScopedAStatus res = radio_data->deactivateDataCall(serial, cid, reason);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INVALID_CALL_ID, RadioError::INVALID_STATE,
+ RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+ RadioError::CANCELLED, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_CALL_ID,
+ RadioError::INVALID_STATE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED, RadioError::CANCELLED}));
+ }
+}
+
+/*
+ * Test IRadioData.startKeepalive() for the response returned.
+ */
+TEST_P(RadioDataTest, startKeepalive) {
+ std::vector<KeepaliveRequest> requests = {
+ {
+ // Invalid IPv4 source address
+ KeepaliveRequest::TYPE_NATT_IPV4,
+ {192, 168, 0 /*, 100*/},
+ 1234,
+ {8, 8, 4, 4},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid IPv4 destination address
+ KeepaliveRequest::TYPE_NATT_IPV4,
+ {192, 168, 0, 100},
+ 1234,
+ {8, 8, 4, 4, 1, 2, 3, 4},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid Keepalive Type
+ -1,
+ {192, 168, 0, 100},
+ 1234,
+ {8, 8, 4, 4},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid IPv6 source address
+ KeepaliveRequest::TYPE_NATT_IPV6,
+ {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xED, 0xBE, 0xEF, 0xBD},
+ 1234,
+ {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x44},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid IPv6 destination address
+ KeepaliveRequest::TYPE_NATT_IPV6,
+ {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xED, 0xBE, 0xEF},
+ 1234,
+ {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88,
+ /*0x44*/},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid Context ID (cid), this should survive the initial
+ // range checking and fail in the modem data layer
+ KeepaliveRequest::TYPE_NATT_IPV4,
+ {192, 168, 0, 100},
+ 1234,
+ {8, 8, 4, 4},
+ 4500,
+ 20000,
+ 0xBAD,
+ },
+ {
+ // Invalid Context ID (cid), this should survive the initial
+ // range checking and fail in the modem data layer
+ KeepaliveRequest::TYPE_NATT_IPV6,
+ {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xED, 0xBE, 0xEF},
+ 1234,
+ {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x44},
+ 4500,
+ 20000,
+ 0xBAD,
+ }};
+
+ for (auto req = requests.begin(); req != requests.end(); req++) {
+ serial = GetRandomSerialNumber();
+ radio_data->startKeepalive(serial, *req);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioData.stopKeepalive() for the response returned.
+ */
+TEST_P(RadioDataTest, stopKeepalive) {
+ serial = GetRandomSerialNumber();
+
+ radio_data->stopKeepalive(serial, 0xBAD);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioData.getDataCallList() for the response returned.
+ */
+TEST_P(RadioDataTest, getDataCallList) {
+ LOG(DEBUG) << "getDataCallList";
+ serial = GetRandomSerialNumber();
+
+ radio_data->getDataCallList(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_data->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
+ }
+ LOG(DEBUG) << "getDataCallList finished";
+}
+
+/*
+ * Test IRadioData.setDataAllowed() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataAllowed) {
+ LOG(DEBUG) << "setDataAllowed";
+ serial = GetRandomSerialNumber();
+ bool allow = true;
+
+ radio_data->setDataAllowed(serial, allow);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_data->rspInfo.error);
+ }
+ LOG(DEBUG) << "setDataAllowed finished";
+}
diff --git a/radio/aidl/vts/radio_data_utils.h b/radio/aidl/vts/radio_data_utils.h
new file mode 100644
index 0000000..fb91ef6
--- /dev/null
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/data/BnRadioDataIndication.h>
+#include <aidl/android/hardware/radio/data/BnRadioDataResponse.h>
+#include <aidl/android/hardware/radio/data/IRadioData.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::data;
+
+class RadioDataTest;
+
+/* Callback class for radio data response */
+class RadioDataResponse : public BnRadioDataResponse {
+ protected:
+ RadioServiceTest& parent_data;
+
+ public:
+ RadioDataResponse(RadioServiceTest& parent_data);
+ virtual ~RadioDataResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ int32_t allocatedPduSessionId;
+ SetupDataCallResult setupDataCallResult;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus allocatePduSessionIdResponse(const RadioResponseInfo& info,
+ int32_t id) override;
+
+ virtual ndk::ScopedAStatus cancelHandoverResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus deactivateDataCallResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getDataCallListResponse(
+ const RadioResponseInfo& info,
+ const std::vector<SetupDataCallResult>& dcResponse) override;
+
+ virtual ndk::ScopedAStatus getSlicingConfigResponse(
+ const RadioResponseInfo& info, const SlicingConfig& slicingConfig) override;
+
+ virtual ndk::ScopedAStatus releasePduSessionIdResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setDataAllowedResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setDataProfileResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setDataThrottlingResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setInitialAttachApnResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setupDataCallResponse(
+ const RadioResponseInfo& info, const SetupDataCallResult& dcResponse) override;
+
+ virtual ndk::ScopedAStatus startHandoverResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus startKeepaliveResponse(const RadioResponseInfo& info,
+ const KeepaliveStatus& status) override;
+
+ virtual ndk::ScopedAStatus stopKeepaliveResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio data indication */
+class RadioDataIndication : public BnRadioDataIndication {
+ protected:
+ RadioServiceTest& parent_data;
+
+ public:
+ RadioDataIndication(RadioServiceTest& parent_data);
+ virtual ~RadioDataIndication() = default;
+
+ virtual ndk::ScopedAStatus dataCallListChanged(
+ RadioIndicationType type, const std::vector<SetupDataCallResult>& dcList) override;
+
+ virtual ndk::ScopedAStatus keepaliveStatus(RadioIndicationType type,
+ const KeepaliveStatus& status) override;
+
+ virtual ndk::ScopedAStatus pcoData(RadioIndicationType type, const PcoDataInfo& pco) override;
+
+ virtual ndk::ScopedAStatus unthrottleApn(RadioIndicationType type,
+ const DataProfileInfo& dataProfile) override;
+ virtual ndk::ScopedAStatus slicingConfigChanged(RadioIndicationType type,
+ const SlicingConfig& slicingConfig) override;
+};
+
+// The main test class for Radio AIDL Data.
+class RadioDataTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ protected:
+ /* Get current data call list */
+ ndk::ScopedAStatus getDataCallList();
+
+ public:
+ virtual void SetUp() override;
+
+ /* radio data service handle */
+ std::shared_ptr<IRadioData> radio_data;
+ /* radio data response handle */
+ std::shared_ptr<RadioDataResponse> radioRsp_data;
+ /* radio data indication handle */
+ std::shared_ptr<RadioDataIndication> radioInd_data;
+};
diff --git a/radio/aidl/vts/radio_messaging_indication.cpp b/radio/aidl/vts/radio_messaging_indication.cpp
new file mode 100644
index 0000000..481239e
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_indication.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_messaging_utils.h"
+
+RadioMessagingIndication::RadioMessagingIndication(RadioServiceTest& parent)
+ : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaNewSms(RadioIndicationType /*type*/,
+ const CdmaSmsMessage& /*msg*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newBroadcastSms(RadioIndicationType /*type*/,
+ const std::vector<uint8_t>& /*data*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSms(RadioIndicationType /*type*/,
+ const std::vector<uint8_t>& /*pdu*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsOnSim(RadioIndicationType /*type*/,
+ int32_t /*recordNumber*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsStatusReport(
+ RadioIndicationType /*type*/, const std::vector<uint8_t>& /*pdu*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::simSmsStorageFull(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_response.cpp b/radio/aidl/vts/radio_messaging_response.cpp
new file mode 100644
index 0000000..49c0806
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_response.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_messaging_utils.h"
+
+RadioMessagingResponse::RadioMessagingResponse(RadioServiceTest& parent)
+ : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeIncomingGsmSmsWithPduResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingCdmaSmsResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingGsmSmsResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnRuimResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnSimResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& info, const std::vector<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getGsmBroadcastConfigResponse(
+ const RadioResponseInfo& info, const std::vector<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getSmscAddressResponse(const RadioResponseInfo& info,
+ const std::string& /*smsc*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::reportSmsMemoryStatusResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsExpectMoreResponse(
+ const RadioResponseInfo& info, const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendImsSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& /*sms*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) {
+ rspInfo = info;
+ sendSmsResult = sms;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastActivationResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastActivationResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastConfigResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setSmscAddressResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToRuimResponse(const RadioResponseInfo& info,
+ int32_t /*index*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToSimResponse(const RadioResponseInfo& info,
+ int32_t /*index*/) {
+ rspInfo = info;
+ parent_messaging.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_test.cpp b/radio/aidl/vts/radio_messaging_test.cpp
new file mode 100644
index 0000000..9f1718b
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_test.cpp
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_messaging_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioMessagingTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_messaging = IRadioMessaging::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_messaging.get());
+
+ radioRsp_messaging = ndk::SharedRefBase::make<RadioMessagingResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_messaging.get());
+
+ count_ = 0;
+
+ radioInd_messaging = ndk::SharedRefBase::make<RadioMessagingIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_messaging.get());
+
+ radio_messaging->setResponseFunctions(radioRsp_messaging, radioInd_messaging);
+
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+}
+
+/*
+ * Test IRadioMessaging.sendSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSms) {
+ LOG(DEBUG) << "sendSms";
+ serial = GetRandomSerialNumber();
+ GsmSmsMessage msg;
+ msg.smscPdu = "";
+ msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+ radio_messaging->sendSms(serial, msg);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ EXPECT_EQ(0, radioRsp_messaging->sendSmsResult.errorCode);
+ }
+ LOG(DEBUG) << "sendSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSmsExpectMore) {
+ LOG(DEBUG) << "sendSmsExpectMore";
+ serial = GetRandomSerialNumber();
+ GsmSmsMessage msg;
+ msg.smscPdu = "";
+ msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+ radio_messaging->sendSmsExpectMore(serial, msg);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendSmsExpectMore finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSms) {
+ LOG(DEBUG) << "sendCdmaSms";
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+ cdmaSmsAddress.isNumberModeDataNetwork = false;
+ cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_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 = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ 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_messaging->sendCdmaSms(serial, cdmaSmsMessage);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendCdmaSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSmsExpectMore) {
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+ cdmaSmsAddress.isNumberModeDataNetwork = false;
+ cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_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 = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ 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_messaging->sendCdmaSmsExpectMore(serial, cdmaSmsMessage);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioMessaging.setGsmBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setGsmBroadcastConfig) {
+ LOG(DEBUG) << "setGsmBroadcastConfig";
+ serial = GetRandomSerialNumber();
+
+ // Create GsmBroadcastSmsConfigInfo #1
+ GsmBroadcastSmsConfigInfo gbSmsConfig1;
+ gbSmsConfig1.fromServiceId = 4352;
+ gbSmsConfig1.toServiceId = 4354;
+ gbSmsConfig1.fromCodeScheme = 0;
+ gbSmsConfig1.toCodeScheme = 255;
+ gbSmsConfig1.selected = true;
+
+ // Create GsmBroadcastSmsConfigInfo #2
+ GsmBroadcastSmsConfigInfo gbSmsConfig2;
+ gbSmsConfig2.fromServiceId = 4356;
+ gbSmsConfig2.toServiceId = 4356;
+ gbSmsConfig2.fromCodeScheme = 0;
+ gbSmsConfig2.toCodeScheme = 255;
+ gbSmsConfig2.selected = true;
+
+ // Create GsmBroadcastSmsConfigInfo #3
+ GsmBroadcastSmsConfigInfo gbSmsConfig3;
+ gbSmsConfig3.fromServiceId = 4370;
+ gbSmsConfig3.toServiceId = 4379;
+ gbSmsConfig3.fromCodeScheme = 0;
+ gbSmsConfig3.toCodeScheme = 255;
+ gbSmsConfig3.selected = true;
+
+ // Create GsmBroadcastSmsConfigInfo #4
+ GsmBroadcastSmsConfigInfo gbSmsConfig4;
+ gbSmsConfig4.fromServiceId = 4383;
+ gbSmsConfig4.toServiceId = 4391;
+ gbSmsConfig4.fromCodeScheme = 0;
+ gbSmsConfig4.toCodeScheme = 255;
+ gbSmsConfig4.selected = true;
+
+ // Create GsmBroadcastSmsConfigInfo #5
+ GsmBroadcastSmsConfigInfo gbSmsConfig5;
+ gbSmsConfig5.fromServiceId = 4392;
+ gbSmsConfig5.toServiceId = 4392;
+ gbSmsConfig5.fromCodeScheme = 0;
+ gbSmsConfig5.toCodeScheme = 255;
+ gbSmsConfig5.selected = true;
+
+ std::vector<GsmBroadcastSmsConfigInfo> gsmBroadcastSmsConfigsInfoList = {
+ gbSmsConfig1, gbSmsConfig2, gbSmsConfig3, gbSmsConfig4, gbSmsConfig5};
+
+ radio_messaging->setGsmBroadcastConfig(serial, gsmBroadcastSmsConfigsInfoList);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setGsmBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.getGsmBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getGsmBroadcastConfig) {
+ LOG(DEBUG) << "getGsmBroadcastConfig";
+ serial = GetRandomSerialNumber();
+
+ radio_messaging->getGsmBroadcastConfig(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getGsmBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.setCdmaBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setCdmaBroadcastConfig) {
+ LOG(DEBUG) << "setCdmaBroadcastConfig";
+ serial = GetRandomSerialNumber();
+
+ CdmaBroadcastSmsConfigInfo cbSmsConfig;
+ cbSmsConfig.serviceCategory = 4096;
+ cbSmsConfig.language = 1;
+ cbSmsConfig.selected = true;
+
+ std::vector<CdmaBroadcastSmsConfigInfo> cdmaBroadcastSmsConfigInfoList = {cbSmsConfig};
+
+ radio_messaging->setCdmaBroadcastConfig(serial, cdmaBroadcastSmsConfigInfoList);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_MODEM_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setCdmaBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.getCdmaBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getCdmaBroadcastConfig) {
+ LOG(DEBUG) << "getCdmaBroadcastConfig";
+ serial = GetRandomSerialNumber();
+
+ radio_messaging->getCdmaBroadcastConfig(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getCdmaBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.setCdmaBroadcastActivation() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setCdmaBroadcastActivation) {
+ LOG(DEBUG) << "setCdmaBroadcastActivation";
+ serial = GetRandomSerialNumber();
+ bool activate = false;
+
+ radio_messaging->setCdmaBroadcastActivation(serial, activate);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setCdmaBroadcastActivation finished";
+}
+
+/*
+ * Test IRadioMessaging.setGsmBroadcastActivation() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setGsmBroadcastActivation) {
+ LOG(DEBUG) << "setGsmBroadcastActivation";
+ serial = GetRandomSerialNumber();
+ bool activate = false;
+
+ radio_messaging->setGsmBroadcastActivation(serial, activate);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+ RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setGsmBroadcastActivation finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeLastIncomingGsmSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeLastIncomingGsmSms) {
+ LOG(DEBUG) << "acknowledgeLastIncomingGsmSms";
+ serial = GetRandomSerialNumber();
+ bool success = true;
+
+ radio_messaging->acknowledgeLastIncomingGsmSms(
+ serial, success, SmsAcknowledgeFailCause::MEMORY_CAPACITY_EXCEEDED);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "acknowledgeLastIncomingGsmSms finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeIncomingGsmSmsWithPdu() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeIncomingGsmSmsWithPdu) {
+ LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu";
+ serial = GetRandomSerialNumber();
+ bool success = true;
+ std::string ackPdu = "";
+
+ radio_messaging->acknowledgeIncomingGsmSmsWithPdu(serial, success, ackPdu);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeLastIncomingCdmaSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeLastIncomingCdmaSms) {
+ LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms";
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAck
+ CdmaSmsAck cdmaSmsAck;
+ cdmaSmsAck.errorClass = false;
+ cdmaSmsAck.smsCauseCode = 1;
+
+ radio_messaging->acknowledgeLastIncomingCdmaSms(serial, cdmaSmsAck);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendImsSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendImsSms) {
+ LOG(DEBUG) << "sendImsSms";
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+ cdmaSmsAddress.isNumberModeDataNetwork = false;
+ cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_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 = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ 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};
+
+ // Creata an ImsSmsMessage
+ ImsSmsMessage msg;
+ msg.tech = RadioTechnologyFamily::THREE_GPP2;
+ msg.retry = false;
+ msg.messageRef = 0;
+ msg.cdmaMessage = (std::vector<CdmaSmsMessage>){cdmaSmsMessage};
+ msg.gsmMessage = (std::vector<GsmSmsMessage>){};
+
+ radio_messaging->sendImsSms(serial, msg);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS}, CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendImsSms finished";
+}
+
+/*
+ * Test IRadioMessaging.getSmscAddress() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getSmscAddress) {
+ LOG(DEBUG) << "getSmscAddress";
+ serial = GetRandomSerialNumber();
+
+ radio_messaging->getSmscAddress(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE,
+ RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getSmscAddress finished";
+}
+
+/*
+ * Test IRadioMessaging.setSmscAddress() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setSmscAddress) {
+ LOG(DEBUG) << "setSmscAddress";
+ serial = GetRandomSerialNumber();
+ std::string address = std::string("smscAddress");
+
+ radio_messaging->setSmscAddress(serial, address);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
+ RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setSmscAddress finished";
+}
+
+/*
+ * Test IRadioMessaging.writeSmsToSim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, writeSmsToSim) {
+ LOG(DEBUG) << "writeSmsToSim";
+ serial = GetRandomSerialNumber();
+ SmsWriteArgs smsWriteArgs;
+ smsWriteArgs.status = SmsWriteArgs::STATUS_REC_UNREAD;
+ smsWriteArgs.smsc = "";
+ smsWriteArgs.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+ radio_messaging->writeSmsToSim(serial, smsWriteArgs);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+ RadioError::INVALID_SMSC_ADDRESS, RadioError::MODEM_ERR,
+ RadioError::NETWORK_NOT_READY, RadioError::NO_RESOURCES, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "writeSmsToSim finished";
+}
+
+/*
+ * Test IRadioMessaging.deleteSmsOnSim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, deleteSmsOnSim) {
+ LOG(DEBUG) << "deleteSmsOnSim";
+ serial = GetRandomSerialNumber();
+ int index = 1;
+
+ radio_messaging->deleteSmsOnSim(serial, index);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+ RadioError::INVALID_MODEM_STATE, RadioError::NO_SUCH_ENTRY, RadioError::MODEM_ERR,
+ RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "deleteSmsOnSim finished";
+}
+
+/*
+ * Test IRadioMessaging.writeSmsToRuim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, writeSmsToRuim) {
+ LOG(DEBUG) << "writeSmsToRuim";
+ serial = GetRandomSerialNumber();
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+ cdmaSmsAddress.isNumberModeDataNetwork = false;
+ cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_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 = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ 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};
+
+ // Create a CdmaSmsWriteArgs
+ CdmaSmsWriteArgs cdmaSmsWriteArgs;
+ cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
+ cdmaSmsWriteArgs.message = cdmaSmsMessage;
+
+ radio_messaging->writeSmsToRuim(serial, cdmaSmsWriteArgs);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
+ RadioError::INVALID_SMSC_ADDRESS, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+ RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "writeSmsToRuim finished";
+}
+
+/*
+ * Test IRadioMessaging.deleteSmsOnRuim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, deleteSmsOnRuim) {
+ LOG(DEBUG) << "deleteSmsOnRuim";
+ serial = GetRandomSerialNumber();
+ int index = 1;
+
+ // Create a CdmaSmsAddress
+ CdmaSmsAddress cdmaSmsAddress;
+ cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+ cdmaSmsAddress.isNumberModeDataNetwork = false;
+ cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+ cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_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 = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+ cdmaSmsSubaddress.odd = false;
+ cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+ // Create a CdmaSmsMessage
+ 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};
+
+ // Create a CdmaSmsWriteArgs
+ CdmaSmsWriteArgs cdmaSmsWriteArgs;
+ cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
+ cdmaSmsWriteArgs.message = cdmaSmsMessage;
+
+ radio_messaging->deleteSmsOnRuim(serial, index);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_messaging->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+ RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "deleteSmsOnRuim finished";
+}
+
+/*
+ * Test IRadioMessaging.reportSmsMemoryStatus() for the response returned.
+ */
+TEST_P(RadioMessagingTest, reportSmsMemoryStatus) {
+ LOG(DEBUG) << "reportSmsMemoryStatus";
+ serial = GetRandomSerialNumber();
+ bool available = true;
+
+ radio_messaging->reportSmsMemoryStatus(serial, available);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+ RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "reportSmsMemoryStatus finished";
+}
diff --git a/radio/aidl/vts/radio_messaging_utils.h b/radio/aidl/vts/radio_messaging_utils.h
new file mode 100644
index 0000000..7b66192
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_utils.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessaging.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::messaging;
+
+class RadioMessagingTest;
+
+/* Callback class for radio messaging response */
+class RadioMessagingResponse : public BnRadioMessagingResponse {
+ protected:
+ RadioServiceTest& parent_messaging;
+
+ public:
+ RadioMessagingResponse(RadioServiceTest& parent_messaging);
+ virtual ~RadioMessagingResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ SendSmsResult sendSmsResult;
+
+ virtual ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPduResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus acknowledgeLastIncomingCdmaSmsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus acknowledgeLastIncomingGsmSmsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus deleteSmsOnRuimResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus deleteSmsOnSimResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& info,
+ const std::vector<CdmaBroadcastSmsConfigInfo>& configs) override;
+
+ virtual ndk::ScopedAStatus getGsmBroadcastConfigResponse(
+ const RadioResponseInfo& info,
+ const std::vector<GsmBroadcastSmsConfigInfo>& configs) override;
+
+ virtual ndk::ScopedAStatus getSmscAddressResponse(const RadioResponseInfo& info,
+ const std::string& smsc) override;
+
+ virtual ndk::ScopedAStatus reportSmsMemoryStatusResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) override;
+
+ virtual ndk::ScopedAStatus sendCdmaSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) override;
+
+ virtual ndk::ScopedAStatus sendImsSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) override;
+
+ virtual ndk::ScopedAStatus sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) override;
+
+ virtual ndk::ScopedAStatus sendSmsResponse(const RadioResponseInfo& info,
+ const SendSmsResult& sms) override;
+
+ virtual ndk::ScopedAStatus setCdmaBroadcastActivationResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCdmaBroadcastConfigResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setGsmBroadcastActivationResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setGsmBroadcastConfigResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setSmscAddressResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus writeSmsToRuimResponse(const RadioResponseInfo& info,
+ int32_t index) override;
+
+ virtual ndk::ScopedAStatus writeSmsToSimResponse(const RadioResponseInfo& info,
+ int32_t index) override;
+};
+
+/* Callback class for radio messaging indication */
+class RadioMessagingIndication : public BnRadioMessagingIndication {
+ protected:
+ RadioServiceTest& parent_messaging;
+
+ public:
+ RadioMessagingIndication(RadioServiceTest& parent_messaging);
+ virtual ~RadioMessagingIndication() = default;
+
+ virtual ndk::ScopedAStatus cdmaNewSms(RadioIndicationType type,
+ const CdmaSmsMessage& msg) override;
+
+ virtual ndk::ScopedAStatus cdmaRuimSmsStorageFull(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus newBroadcastSms(RadioIndicationType type,
+ const std::vector<uint8_t>& data) override;
+
+ virtual ndk::ScopedAStatus newSms(RadioIndicationType type,
+ const std::vector<uint8_t>& pdu) override;
+
+ virtual ndk::ScopedAStatus newSmsOnSim(RadioIndicationType type, int32_t recordNumber) override;
+
+ virtual ndk::ScopedAStatus newSmsStatusReport(RadioIndicationType type,
+ const std::vector<uint8_t>& pdu) override;
+
+ virtual ndk::ScopedAStatus simSmsStorageFull(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Messaging.
+class RadioMessagingTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+
+ /* radio messaging service handle */
+ std::shared_ptr<IRadioMessaging> radio_messaging;
+ /* radio messaging response handle */
+ std::shared_ptr<RadioMessagingResponse> radioRsp_messaging;
+ /* radio messaging indication handle */
+ std::shared_ptr<RadioMessagingIndication> radioInd_messaging;
+};
diff --git a/radio/aidl/vts/radio_modem_indication.cpp b/radio/aidl/vts/radio_modem_indication.cpp
new file mode 100644
index 0000000..0bfcd66
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_indication.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_modem_utils.h"
+
+RadioModemIndication::RadioModemIndication(RadioServiceTest& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemIndication::hardwareConfigChanged(
+ RadioIndicationType /*type*/, const std::vector<HardwareConfig>& /*configs*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::modemReset(RadioIndicationType /*type*/,
+ const std::string& /*reason*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioCapabilityIndication(RadioIndicationType /*type*/,
+ const RadioCapability& /*rc*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioStateChanged(RadioIndicationType /*type*/,
+ RadioState /*radioState*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::rilConnected(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_response.cpp b/radio/aidl/vts/radio_modem_response.cpp
new file mode 100644
index 0000000..d2715a8
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_response.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_modem_utils.h"
+
+RadioModemResponse::RadioModemResponse(RadioServiceTest& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::enableModemResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getBasebandVersionResponse(const RadioResponseInfo& info,
+ const std::string& /*version*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getDeviceIdentityResponse(const RadioResponseInfo& info,
+ const std::string& /*imei*/,
+ const std::string& /*imeisv*/,
+ const std::string& /*esn*/,
+ const std::string& /*meid*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getHardwareConfigResponse(
+ const RadioResponseInfo& info, const std::vector<HardwareConfig>& /*config*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemActivityInfoResponse(
+ const RadioResponseInfo& info, const ActivityStatsInfo& /*activityInfo*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemStackStatusResponse(const RadioResponseInfo& info,
+ const bool enabled) {
+ rspInfo = info;
+ isModemEnabled = enabled;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getRadioCapabilityResponse(const RadioResponseInfo& info,
+ const RadioCapability& /*rc*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvReadItemResponse(const RadioResponseInfo& info,
+ const std::string& /*result*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvResetConfigResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteCdmaPrlResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteItemResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::requestShutdownResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::sendDeviceStateResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioCapabilityResponse(const RadioResponseInfo& info,
+ const RadioCapability& /*rc*/) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioPowerResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_modem.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_test.cpp b/radio/aidl/vts/radio_modem_test.cpp
new file mode 100644
index 0000000..f88da13
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_test.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_modem_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioModemTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_modem = IRadioModem::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_modem.get());
+
+ radioRsp_modem = ndk::SharedRefBase::make<RadioModemResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_modem.get());
+
+ count_ = 0;
+
+ radioInd_modem = ndk::SharedRefBase::make<RadioModemIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_modem.get());
+
+ radio_modem->setResponseFunctions(radioRsp_modem, radioInd_modem);
+
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+}
+
+/*
+ * Test IRadioModem.setRadioPower() for the response returned.
+ */
+TEST_P(RadioModemTest, setRadioPower_emergencyCall_cancelled) {
+ // Set radio power to off.
+ serial = GetRandomSerialNumber();
+ radio_modem->setRadioPower(serial, false, false, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+ // Set radio power to on with forEmergencyCall being true. This should put modem to only scan
+ // emergency call bands.
+ serial = GetRandomSerialNumber();
+ radio_modem->setRadioPower(serial, true, true, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+ // Set radio power to on with forEmergencyCall being false. This should put modem in regular
+ // operation modem.
+ serial = GetRandomSerialNumber();
+ radio_modem->setRadioPower(serial, true, false, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+}
+
+/*
+ * Test IRadioModem.enableModem() for the response returned.
+ */
+TEST_P(RadioModemTest, enableModem) {
+ serial = GetRandomSerialNumber();
+
+ if (isSsSsEnabled()) {
+ ALOGI("enableModem, no need to test in single SIM mode");
+ return;
+ }
+
+ bool responseToggle = radioRsp_modem->enableModemResponseToggle;
+ ndk::ScopedAStatus res = radio_modem->enableModem(serial, true);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+ toString(radioRsp_modem->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
+
+ // checking if getModemStackStatus returns true, as modem was enabled above
+ if (RadioError::NONE == radioRsp_modem->rspInfo.error) {
+ // wait until modem enabling is finished
+ while (responseToggle == radioRsp_modem->enableModemResponseToggle) {
+ sleep(1);
+ }
+ ndk::ScopedAStatus resEnabled = radio_modem->getModemStackStatus(serial);
+ ASSERT_OK(resEnabled);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+ toString(radioRsp_modem->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
+ // verify that enableModem did set isEnabled correctly
+ EXPECT_EQ(true, radioRsp_modem->isModemEnabled);
+ }
+}
+
+/*
+ * Test IRadioModem.getModemStackStatus() for the response returned.
+ */
+TEST_P(RadioModemTest, getModemStackStatus) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_modem->getModemStackStatus(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+ ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+ toString(radioRsp_modem->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+}
+
+/*
+ * Test IRadioModem.getBasebandVersion() for the response returned.
+ */
+TEST_P(RadioModemTest, getBasebandVersion) {
+ LOG(DEBUG) << "getBasebandVersion";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->getBasebandVersion(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+ }
+ LOG(DEBUG) << "getBasebandVersion finished";
+}
+
+/*
+ * Test IRadioModem.getDeviceIdentity() for the response returned.
+ */
+TEST_P(RadioModemTest, getDeviceIdentity) {
+ LOG(DEBUG) << "getDeviceIdentity";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->getDeviceIdentity(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::EMPTY_RECORD}));
+ }
+ LOG(DEBUG) << "getDeviceIdentity finished";
+}
+
+/*
+ * Test IRadioModem.nvReadItem() for the response returned.
+ */
+TEST_P(RadioModemTest, nvReadItem) {
+ LOG(DEBUG) << "nvReadItem";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->nvReadItem(serial, NvItem::LTE_BAND_ENABLE_25);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "nvReadItem finished";
+}
+
+/*
+ * Test IRadioModem.nvWriteItem() for the response returned.
+ */
+TEST_P(RadioModemTest, nvWriteItem) {
+ LOG(DEBUG) << "nvWriteItem";
+ serial = GetRandomSerialNumber();
+ NvWriteItem item;
+ memset(&item, 0, sizeof(item));
+ item.value = std::string();
+
+ radio_modem->nvWriteItem(serial, item);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "nvWriteItem finished";
+}
+
+/*
+ * Test IRadioModem.nvWriteCdmaPrl() for the response returned.
+ */
+TEST_P(RadioModemTest, nvWriteCdmaPrl) {
+ LOG(DEBUG) << "nvWriteCdmaPrl";
+ serial = GetRandomSerialNumber();
+ std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
+
+ radio_modem->nvWriteCdmaPrl(serial, std::vector<uint8_t>(prl));
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "nvWriteCdmaPrl finished";
+}
+
+/*
+ * Test IRadioModem.nvResetConfig() for the response returned.
+ */
+TEST_P(RadioModemTest, nvResetConfig) {
+ LOG(DEBUG) << "nvResetConfig";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->nvResetConfig(serial, ResetNvType::FACTORY_RESET);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "nvResetConfig finished";
+}
+
+/*
+ * Test IRadioModem.getHardwareConfig() for the response returned.
+ */
+TEST_P(RadioModemTest, getHardwareConfig) {
+ LOG(DEBUG) << "getHardwareConfig";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->getHardwareConfig(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getHardwareConfig finished";
+}
+
+/*
+ * The following test is disabled due to b/64734869
+ *
+ * Test IRadioModem.requestShutdown() for the response returned.
+ */
+TEST_P(RadioModemTest, DISABLED_requestShutdown) {
+ serial = GetRandomSerialNumber();
+
+ radio_modem->requestShutdown(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioModem.getRadioCapability() for the response returned.
+ */
+TEST_P(RadioModemTest, getRadioCapability) {
+ LOG(DEBUG) << "getRadioCapability";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->getRadioCapability(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+ }
+ LOG(DEBUG) << "getRadioCapability finished";
+}
+
+/*
+ * Test IRadioModem.setRadioCapability() for the response returned.
+ */
+TEST_P(RadioModemTest, setRadioCapability) {
+ LOG(DEBUG) << "setRadioCapability";
+ serial = GetRandomSerialNumber();
+ RadioCapability rc;
+ memset(&rc, 0, sizeof(rc));
+ rc.logicalModemUuid = std::string();
+
+ radio_modem->setRadioCapability(serial, rc);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setRadioCapability finished";
+}
+
+/*
+ * Test IRadioModem.getModemActivityInfo() for the response returned.
+ */
+TEST_P(RadioModemTest, getModemActivityInfo) {
+ LOG(DEBUG) << "getModemActivityInfo";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->getModemActivityInfo(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "getModemActivityInfo finished";
+}
+
+/*
+ * Test IRadioModem.sendDeviceState() for the response returned.
+ */
+TEST_P(RadioModemTest, sendDeviceState) {
+ LOG(DEBUG) << "sendDeviceState";
+ serial = GetRandomSerialNumber();
+
+ radio_modem->sendDeviceState(serial, DeviceStateType::POWER_SAVE_MODE, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+ std::cout << static_cast<int>(radioRsp_modem->rspInfo.error) << std::endl;
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "sendDeviceState finished";
+}
diff --git a/radio/aidl/vts/radio_modem_utils.h b/radio/aidl/vts/radio_modem_utils.h
new file mode 100644
index 0000000..8779e0c
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_utils.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/BnRadioModemIndication.h>
+#include <aidl/android/hardware/radio/modem/BnRadioModemResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModem.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::modem;
+
+class RadioModemTest;
+
+/* Callback class for radio modem response */
+class RadioModemResponse : public BnRadioModemResponse {
+ protected:
+ RadioServiceTest& parent_modem;
+
+ public:
+ RadioModemResponse(RadioServiceTest& parent_modem);
+ virtual ~RadioModemResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ bool isModemEnabled;
+ bool enableModemResponseToggle;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus enableModemResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getBasebandVersionResponse(const RadioResponseInfo& info,
+ const std::string& version) override;
+
+ virtual ndk::ScopedAStatus getDeviceIdentityResponse(const RadioResponseInfo& info,
+ const std::string& imei,
+ const std::string& imeisv,
+ const std::string& esn,
+ const std::string& meid) override;
+
+ virtual ndk::ScopedAStatus getHardwareConfigResponse(
+ const RadioResponseInfo& info, const std::vector<HardwareConfig>& config) override;
+
+ virtual ndk::ScopedAStatus getModemActivityInfoResponse(
+ const RadioResponseInfo& info, const ActivityStatsInfo& activityInfo) override;
+
+ virtual ndk::ScopedAStatus getModemStackStatusResponse(const RadioResponseInfo& info,
+ const bool enabled) override;
+
+ virtual ndk::ScopedAStatus getRadioCapabilityResponse(const RadioResponseInfo& info,
+ const RadioCapability& rc) override;
+
+ virtual ndk::ScopedAStatus nvReadItemResponse(const RadioResponseInfo& info,
+ const std::string& result) override;
+
+ virtual ndk::ScopedAStatus nvResetConfigResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus nvWriteCdmaPrlResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus nvWriteItemResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus requestShutdownResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendDeviceStateResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setRadioCapabilityResponse(const RadioResponseInfo& info,
+ const RadioCapability& rc) override;
+
+ virtual ndk::ScopedAStatus setRadioPowerResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio modem indication */
+class RadioModemIndication : public BnRadioModemIndication {
+ protected:
+ RadioServiceTest& parent_modem;
+
+ public:
+ RadioModemIndication(RadioServiceTest& parent_modem);
+ virtual ~RadioModemIndication() = default;
+
+ virtual ndk::ScopedAStatus hardwareConfigChanged(
+ RadioIndicationType type, const std::vector<HardwareConfig>& configs) override;
+
+ virtual ndk::ScopedAStatus modemReset(RadioIndicationType type,
+ const std::string& reason) override;
+
+ virtual ndk::ScopedAStatus radioCapabilityIndication(RadioIndicationType type,
+ const RadioCapability& rc) override;
+
+ virtual ndk::ScopedAStatus radioStateChanged(RadioIndicationType type,
+ RadioState radioState) override;
+
+ virtual ndk::ScopedAStatus rilConnected(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Modem.
+class RadioModemTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+
+ /* radio modem service handle */
+ std::shared_ptr<IRadioModem> radio_modem;
+ /* radio modem response handle */
+ std::shared_ptr<RadioModemResponse> radioRsp_modem;
+ /* radio modem indication handle */
+ std::shared_ptr<RadioModemIndication> radioInd_modem;
+};
diff --git a/radio/aidl/vts/radio_network_indication.cpp b/radio/aidl/vts/radio_network_indication.cpp
new file mode 100644
index 0000000..7acbff4
--- /dev/null
+++ b/radio/aidl/vts/radio_network_indication.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_network_utils.h"
+
+RadioNetworkIndication::RadioNetworkIndication(RadioServiceTest& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkIndication::barringInfoChanged(
+ RadioIndicationType /*type*/, const CellIdentity& /*cellIdentity*/,
+ const std::vector<BarringInfo>& /*barringInfos*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cdmaPrlChanged(RadioIndicationType /*type*/,
+ int32_t /*version*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cellInfoList(RadioIndicationType /*type*/,
+ const std::vector<CellInfo>& /*records*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentLinkCapacityEstimate(
+ RadioIndicationType /*type*/, const LinkCapacityEstimate& /*lce*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentPhysicalChannelConfigs(
+ RadioIndicationType /*type*/, const std::vector<PhysicalChannelConfig>& /*configs*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentSignalStrength(
+ RadioIndicationType /*type*/, const SignalStrength& /*signalStrength*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkScanResult(RadioIndicationType /*type*/,
+ const NetworkScanResult& /*result*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkStateChanged(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::nitzTimeReceived(RadioIndicationType /*type*/,
+ const std::string& /*nitzTime*/,
+ int64_t /*receivedTime*/,
+ int64_t /*age*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::registrationFailed(RadioIndicationType /*type*/,
+ const CellIdentity& /*cellIdentity*/,
+ const std::string& /*chosenPlmn*/,
+ int32_t /*domain*/,
+ int32_t /*causeCode*/,
+ int32_t /*additionalCauseCode*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::restrictedStateChanged(RadioIndicationType /*type*/,
+ PhoneRestrictedState /*state*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::suppSvcNotify(RadioIndicationType /*type*/,
+ const SuppSvcNotification& /*suppSvc*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::voiceRadioTechChanged(RadioIndicationType /*type*/,
+ RadioTechnology /*rat*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
new file mode 100644
index 0000000..666d617
--- /dev/null
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_network_utils.h"
+
+RadioNetworkResponse::RadioNetworkResponse(RadioServiceTest& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAllowedNetworkTypesBitmapResponse(
+ const RadioResponseInfo& info, const int32_t networkTypeBitmap) {
+ rspInfo = info;
+ networkTypeBitmapResponse = networkTypeBitmap;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableBandModesResponse(
+ const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) {
+ rspInfo = info;
+ radioBandModes = bandModes;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableNetworksResponse(
+ const RadioResponseInfo& info, const std::vector<OperatorInfo>& operatorInfos) {
+ rspInfo = info;
+ networkInfos = operatorInfos;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getBarringInfoResponse(
+ const RadioResponseInfo& info, const CellIdentity& cellIdentity,
+ const std::vector<BarringInfo>& barringInfos) {
+ rspInfo = info;
+ barringCellIdentity = cellIdentity;
+ barringInfoList = barringInfos;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCdmaRoamingPreferenceResponse(
+ const RadioResponseInfo& info, CdmaRoamingType /*type*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCellInfoListResponse(
+ const RadioResponseInfo& info, const std::vector<CellInfo>& /*cellInfo*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getDataRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& regResponse) {
+ rspInfo = info;
+ dataRegResp = regResponse;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getImsRegistrationStateResponse(
+ const RadioResponseInfo& info, bool /*isRegistered*/, RadioTechnologyFamily /*ratFamily*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getNetworkSelectionModeResponse(
+ const RadioResponseInfo& info, bool /*manual*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getOperatorResponse(const RadioResponseInfo& info,
+ const std::string& /*longName*/,
+ const std::string& /*shortName*/,
+ const std::string& /*numeric*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSignalStrengthResponse(
+ const RadioResponseInfo& info, const SignalStrength& /*sig_strength*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSystemSelectionChannelsResponse(
+ const RadioResponseInfo& info, const std::vector<RadioAccessSpecifier>& /*specifier*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getUsageSettingResponse(const RadioResponseInfo& info,
+ const UsageSetting usageSetting) {
+ rspInfo = info;
+ this->usageSetting = usageSetting;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRadioTechnologyResponse(
+ const RadioResponseInfo& info, RadioTechnology /*rat*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& regResponse) {
+ rspInfo = info;
+ voiceRegResp = regResponse;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::isNrDualConnectivityEnabledResponse(
+ const RadioResponseInfo& info, bool isEnabled) {
+ rspInfo = info;
+ isNrDualConnectivityEnabled = isEnabled;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setAllowedNetworkTypesBitmapResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBandModeResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBarringPasswordResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCdmaRoamingPreferenceResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCellInfoListRateResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setIndicationFilterResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLinkCapacityReportingCriteriaResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLocationUpdatesResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeAutomaticResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeManualResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNrDualConnectivityStateResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSignalStrengthReportingCriteriaResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSuppServiceNotificationsResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSystemSelectionChannelsResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setUsageSettingResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::startNetworkScanResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::stopNetworkScanResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::supplyNetworkDepersonalizationResponse(
+ const RadioResponseInfo& info, int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
new file mode 100644
index 0000000..e1d508d
--- /dev/null
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -0,0 +1,1736 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/network/IndicationFilter.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_network_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioNetworkTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_network = IRadioNetwork::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_network.get());
+
+ radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_network.get());
+
+ count_ = 0;
+
+ radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_network.get());
+
+ radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+}
+
+void RadioNetworkTest::stopNetworkScan() {
+ serial = GetRandomSerialNumber();
+ radio_network->stopNetworkScan(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
+
+/*
+ * Test IRadioNetwork.setAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, setAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
+
+ radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::OPERATION_NOT_ALLOWED,
+ RadioError::MODE_NOT_SUPPORTED, RadioError::INTERNAL_ERR, RadioError::MODEM_ERR,
+ RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+ RadioError::NO_RESOURCES}));
+}
+
+/*
+ * Test IRadioNetwork.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
+
+ radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ sleep(3); // wait for modem
+ serial = GetRandomSerialNumber();
+ radio_network->getAllowedNetworkTypesBitmap(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+ RadioError::OPERATION_NOT_ALLOWED, RadioError::MODE_NOT_SUPPORTED,
+ RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR,
+ RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.setNrDualConnectivityState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNrDualConnectivityState) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_network->setNrDualConnectivityState(serial, NrDualConnectivityState::DISABLE);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+ RadioError::INVALID_STATE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.isNrDualConnectivityEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, isNrDualConnectivityEnabled) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->isNrDualConnectivityEnabled(serial);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR, RadioError::NONE}));
+ }
+}
+
+void RadioNetworkTest::invokeAndExpectResponse(
+ std::function<ndk::ScopedAStatus(int32_t serial)> request,
+ std::vector<RadioError> errors_to_check) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = request(serial);
+ ASSERT_OK(res);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, errors_to_check));
+}
+
+/*
+ * Test IRadioNetwork.getUsageSetting()
+ *
+ * Verify that the usage setting can be retrieved.
+ */
+TEST_P(RadioNetworkTest, getUsageSetting) {
+ invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+ RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+ ASSERT_TRUE(radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC ||
+ radioRsp_network->usageSetting == UsageSetting::DATA_CENTRIC);
+}
+
+void RadioNetworkTest::testSetUsageSetting_InvalidValues(std::vector<RadioError> errors) {
+ invokeAndExpectResponse(
+ [&](int serial) {
+ return radio_network->setUsageSetting(serial,
+ UsageSetting(0) /*below valid range*/);
+ },
+ errors);
+ invokeAndExpectResponse(
+ [&](int serial) {
+ return radio_network->setUsageSetting(serial, UsageSetting(-1) /*negative*/);
+ },
+ errors);
+ invokeAndExpectResponse(
+ [&](int serial) {
+ return radio_network->setUsageSetting(serial,
+ UsageSetting(3) /*above valid range*/);
+ },
+ errors);
+}
+
+/*
+ * Test IRadioNetwork.setUsageSetting() and IRadioNetwork.getUsageSetting()
+ *
+ * Verify the following:
+ * -That the usage setting can be retrieved.
+ * -That the usage setting can be successfully set to allowed values.
+ * -That the usage setting cannot be set to invalid values.
+ */
+TEST_P(RadioNetworkTest, setUsageSetting) {
+ invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+ {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+ RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+ if (radioRsp_network->rspInfo.error != RadioError::NONE) {
+ // Test only for invalid values, with the only allowable response being the same error
+ // that was previously provided, or an error indicating invalid arguments.
+ testSetUsageSetting_InvalidValues(
+ {radioRsp_network->rspInfo.error, RadioError::INVALID_ARGUMENTS});
+ // It is unsafe to proceed with setting valid values without knowing the starting value, but
+ // we expect errors anyway, so not necessary.
+ return;
+ } else {
+ // Because querying succeeded, the device is in a valid state to test for invalid values
+ // and the only thing that can change is that we expect to have an EINVAL return each time.
+ testSetUsageSetting_InvalidValues({RadioError::INVALID_ARGUMENTS});
+ }
+
+ // Store the original setting value to reset later.
+ const UsageSetting originalSetting = radioRsp_network->usageSetting;
+
+ // Choose the "other" value that is not the current value for test.
+ const UsageSetting testSetting = radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC
+ ? UsageSetting::DATA_CENTRIC
+ : UsageSetting::VOICE_CENTRIC;
+
+ // Set an alternative setting; it may either succeed or be disallowed as out of range for
+ // the current device (if the device only supports its current mode).
+ invokeAndExpectResponse(
+ [&](int serial) { return radio_network->setUsageSetting(serial, testSetting); },
+ {RadioError::INVALID_ARGUMENTS, RadioError::NONE});
+
+ // If there was no error, then we expect the test setting to be set, or if there is an error
+ // we expect the original setting to be maintained.
+ const UsageSetting expectedSetting =
+ radioRsp_network->rspInfo.error == RadioError::NONE ? testSetting : originalSetting;
+ invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+ {RadioError::NONE});
+
+ const UsageSetting updatedSetting = radioRsp_network->usageSetting;
+
+ // Re-set the original setting, which must always succeed.
+ invokeAndExpectResponse(
+ [&](int serial) { return radio_network->setUsageSetting(serial, originalSetting); },
+ {RadioError::NONE});
+
+ // After resetting the value to its original value, update the local cache, which must
+ // always succeed.
+ invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+ {RadioError::NONE});
+
+ // Check that indeed the updated setting was set. We do this after resetting to original
+ // conditions to avoid early-exiting the test and leaving the device in a modified state.
+ EXPECT_EQ(expectedSetting, updatedSetting);
+ // Check that indeed the original setting was reset.
+ EXPECT_EQ(originalSetting, radioRsp_network->usageSetting);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() with invalid hysteresisDb
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_invalidHysteresisDb) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 10; // hysteresisDb too large given threshold list deltas
+ signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_invalidHysteresisDb, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() with empty thresholds
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_EmptyThresholds) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+ signalThresholdInfo.hysteresisMs = 0;
+ signalThresholdInfo.hysteresisDb = 0;
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_EmptyParams, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for GERAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Geran) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_Geran, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for UTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Utran) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSCP;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-110, -97, -73, -49, -25};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::UTRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_Utran, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSRP) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSRP;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-128, -108, -88, -68};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_Eutran, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSRQ) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSRQ;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-27, -20, -13, -6};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_Eutran, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSSNR) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSNR;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for CDMA2000
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Cdma2000) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::CDMA2000;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_Cdma2000, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSRSRP
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSRSRP) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRP;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 0;
+ signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSRSRP, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+
+ // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+ // setSignalStrengthReportingCriteria()
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSRSRQ
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSRSRQ) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRQ;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 0;
+ signalThresholdInfo.thresholds = {-43, -20, 0, 20};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSRSRQ, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+
+ // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+ // setSignalStrengthReportingCriteria()
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Disable_RSSNR) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSNR;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 2;
+ signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+ signalThresholdInfo.isEnabled = false;
+ signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSSINR
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSSINR) {
+ serial = GetRandomSerialNumber();
+
+ SignalThresholdInfo signalThresholdInfo;
+ signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSSINR;
+ signalThresholdInfo.hysteresisMs = 5000;
+ signalThresholdInfo.hysteresisDb = 0;
+ signalThresholdInfo.thresholds = {-10, 3, 16, 18};
+ signalThresholdInfo.isEnabled = true;
+ signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+ ndk::ScopedAStatus res =
+ radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSSINR, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+
+ // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+ // setSignalStrengthReportingCriteria()
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() invalid hysteresisDlKbps
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_invalidHysteresisDlKbps) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+ serial, 5000,
+ 5000, // hysteresisDlKbps too big for thresholds delta
+ 100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000}, AccessNetwork::GERAN);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setLinkCapacityReportingCriteria_invalidHysteresisDlKbps, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+ // for GERAN
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() invalid hysteresisUlKbps
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_invalidHysteresisUlKbps) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+ serial, 5000, 500, 1000, // hysteresisUlKbps too big for thresholds delta
+ {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000}, AccessNetwork::GERAN);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setLinkCapacityReportingCriteria_invalidHysteresisUlKbps, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+ // for GERAN
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() empty params
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_emptyParams) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+ serial, 0, 0, 0, {}, {}, AccessNetwork::GERAN);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setLinkCapacityReportingCriteria_emptyParams, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+ // for GERAN
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() for GERAN
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_Geran) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+ serial, 5000, 500, 100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+ AccessNetwork::GERAN);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setLinkCapacityReportingCriteria_Geran, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+ // for GERAN
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSystemSelectionChannels() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setSystemSelectionChannels) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ ndk::ScopedAStatus res =
+ radio_network->setSystemSelectionChannels(serial, true, {specifierP900, specifier850});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_network->setSystemSelectionChannels(
+ serial, false, {specifierP900, specifier850});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() for the response returned.
+ */
+TEST_P(RadioNetworkTest, startNetworkScan) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::SIM_ABSENT}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do
+ // not support the required manual GSM search functionality. This is
+ // tracked in b/112206766. Modems have "GSM" rat scan need to
+ // support scanning requests combined with some parameters.
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+ }
+
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ ALOGI("Stop Network Scan");
+ stopNetworkScan();
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid specifier.
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidArgument) {
+ serial = GetRandomSerialNumber();
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT, .interval = 60};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid interval (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidInterval1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 4,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid interval (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidInterval2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 301,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid max search time (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidMaxSearchTime1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 59,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid max search time (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidMaxSearchTime2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 3601,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid periodicity (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidPeriodicity1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 600,
+ .incrementalResults = true,
+ .incrementalResultsPeriodicity = 0};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid periodicity (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidPeriodicity2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 600,
+ .incrementalResults = true,
+ .incrementalResultsPeriodicity = 11};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with valid periodicity
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_GoodRequest1) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 360,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_GoodRequest1, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ ALOGI("Stop Network Scan");
+ stopNetworkScan();
+ }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with valid periodicity and plmns
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_GoodRequest2) {
+ serial = GetRandomSerialNumber();
+
+ RadioAccessSpecifierBands bandP900 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_P900});
+ RadioAccessSpecifierBands band850 =
+ RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+ {GeranBands::BAND_850});
+ RadioAccessSpecifier specifierP900 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+ RadioAccessSpecifier specifier850 = {
+ .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+ NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifierP900, specifier850},
+ .maxSearchTime = 360,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10,
+ .mccMncs = {"310410"}};
+
+ ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("startNetworkScan_GoodRequest2, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ ALOGI("Stop Network Scan");
+ stopNetworkScan();
+ }
+}
+
+/*
+ * Test IRadioNetwork.setNetworkSelectionModeManual() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNetworkSelectionModeManual) {
+ serial = GetRandomSerialNumber();
+
+ // can't camp on nonexistent MCCMNC, so we expect this to fail.
+ ndk::ScopedAStatus res =
+ radio_network->setNetworkSelectionModeManual(serial, "123456", AccessNetwork::GERAN);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
+ RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioNetwork.getBarringInfo() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getBarringInfo) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_network->getBarringInfo(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ASSERT_TRUE(radioRsp_network->barringInfoList.size() > 0);
+
+ std::set<int> reportedServices;
+
+ // validate that the service types are in range
+ for (const auto& info : radioRsp_network->barringInfoList) {
+ ASSERT_TRUE((info.serviceType >= BarringInfo::SERVICE_TYPE_CS_SERVICE &&
+ info.serviceType <= BarringInfo::SERVICE_TYPE_SMS) ||
+ (info.serviceType >= BarringInfo::SERVICE_TYPE_OPERATOR_1 &&
+ info.serviceType <= BarringInfo::SERVICE_TYPE_OPERATOR_32));
+ reportedServices.insert(info.serviceType);
+
+ // Any type that is "conditional" must have valid values for conditional barring
+ // factor and time.
+ switch (info.barringType) {
+ case BarringInfo::BARRING_TYPE_NONE: // fall through
+ case BarringInfo::BARRING_TYPE_UNCONDITIONAL:
+ break;
+ case BarringInfo::BARRING_TYPE_CONDITIONAL: {
+ const int32_t barringFactor = info.barringTypeSpecificInfo->factor;
+ ASSERT_TRUE(barringFactor >= 0 && barringFactor <= 100);
+ ASSERT_TRUE(info.barringTypeSpecificInfo->timeSeconds > 0);
+ break;
+ }
+ default:
+ FAIL();
+ }
+ }
+
+ // 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 check that implementations are
+ // not providing information that they don't have.
+ static const std::set<int> UTRA_SERVICES{
+ BarringInfo::SERVICE_TYPE_CS_SERVICE, BarringInfo::SERVICE_TYPE_PS_SERVICE,
+ BarringInfo::SERVICE_TYPE_CS_VOICE, BarringInfo::SERVICE_TYPE_EMERGENCY,
+ BarringInfo::SERVICE_TYPE_SMS,
+ };
+
+ static const std::set<int> EUTRA_SERVICES{
+ BarringInfo::SERVICE_TYPE_MO_SIGNALLING, BarringInfo::SERVICE_TYPE_MO_DATA,
+ BarringInfo::SERVICE_TYPE_CS_FALLBACK, BarringInfo::SERVICE_TYPE_MMTEL_VOICE,
+ BarringInfo::SERVICE_TYPE_MMTEL_VIDEO, BarringInfo::SERVICE_TYPE_EMERGENCY,
+ BarringInfo::SERVICE_TYPE_SMS,
+ };
+
+ static const std::set<int> NGRA_SERVICES = {
+ BarringInfo::SERVICE_TYPE_MO_SIGNALLING, BarringInfo::SERVICE_TYPE_MO_DATA,
+ BarringInfo::SERVICE_TYPE_CS_FALLBACK, BarringInfo::SERVICE_TYPE_MMTEL_VOICE,
+ BarringInfo::SERVICE_TYPE_MMTEL_VIDEO, BarringInfo::SERVICE_TYPE_EMERGENCY,
+ BarringInfo::SERVICE_TYPE_SMS, BarringInfo::SERVICE_TYPE_OPERATOR_1,
+ BarringInfo::SERVICE_TYPE_OPERATOR_2, BarringInfo::SERVICE_TYPE_OPERATOR_3,
+ BarringInfo::SERVICE_TYPE_OPERATOR_4, BarringInfo::SERVICE_TYPE_OPERATOR_5,
+ BarringInfo::SERVICE_TYPE_OPERATOR_6, BarringInfo::SERVICE_TYPE_OPERATOR_7,
+ BarringInfo::SERVICE_TYPE_OPERATOR_8, BarringInfo::SERVICE_TYPE_OPERATOR_9,
+ BarringInfo::SERVICE_TYPE_OPERATOR_10, BarringInfo::SERVICE_TYPE_OPERATOR_11,
+ BarringInfo::SERVICE_TYPE_OPERATOR_12, BarringInfo::SERVICE_TYPE_OPERATOR_13,
+ BarringInfo::SERVICE_TYPE_OPERATOR_14, BarringInfo::SERVICE_TYPE_OPERATOR_15,
+ BarringInfo::SERVICE_TYPE_OPERATOR_16, BarringInfo::SERVICE_TYPE_OPERATOR_17,
+ BarringInfo::SERVICE_TYPE_OPERATOR_18, BarringInfo::SERVICE_TYPE_OPERATOR_19,
+ BarringInfo::SERVICE_TYPE_OPERATOR_20, BarringInfo::SERVICE_TYPE_OPERATOR_21,
+ BarringInfo::SERVICE_TYPE_OPERATOR_22, BarringInfo::SERVICE_TYPE_OPERATOR_23,
+ BarringInfo::SERVICE_TYPE_OPERATOR_24, BarringInfo::SERVICE_TYPE_OPERATOR_25,
+ BarringInfo::SERVICE_TYPE_OPERATOR_26, BarringInfo::SERVICE_TYPE_OPERATOR_27,
+ BarringInfo::SERVICE_TYPE_OPERATOR_28, BarringInfo::SERVICE_TYPE_OPERATOR_29,
+ BarringInfo::SERVICE_TYPE_OPERATOR_30, BarringInfo::SERVICE_TYPE_OPERATOR_31,
+ };
+
+ const std::set<int>* compareTo = nullptr;
+
+ switch (radioRsp_network->barringCellIdentity.getTag()) {
+ case CellIdentity::Tag::wcdma:
+ // fall through
+ case CellIdentity::Tag::tdscdma:
+ compareTo = &UTRA_SERVICES;
+ break;
+ case CellIdentity::Tag::lte:
+ compareTo = &EUTRA_SERVICES;
+ break;
+ case CellIdentity::Tag::nr:
+ compareTo = &NGRA_SERVICES;
+ break;
+ case CellIdentity::Tag::cdma:
+ // fall through
+ default:
+ FAIL();
+ break;
+ }
+
+ std::set<int> diff;
+
+ std::set_difference(reportedServices.begin(), reportedServices.end(), compareTo->begin(),
+ compareTo->end(), std::inserter(diff, diff.begin()));
+}
+
+/*
+ * Test IRadioNetwork.getSignalStrength() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getSignalStrength) {
+ serial = GetRandomSerialNumber();
+
+ radio_network->getSignalStrength(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.getCellInfoList() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getCellInfoList) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->getCellInfoList(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("getCellInfoList, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::NO_NETWORK_FOUND}));
+}
+
+/*
+ * Test IRadioNetwork.getVoiceRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getVoiceRegistrationState) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->getVoiceRegistrationState(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("getVoiceRegistrationStateResponse, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+}
+
+/*
+ * Test IRadioNetwork.getDataRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getDataRegistrationState) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->getDataRegistrationState(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("getDataRegistrationStateResponse, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+
+ // Check the mcc [0, 999] and mnc [0, 999].
+ std::string mcc;
+ std::string mnc;
+ bool checkMccMnc = true;
+ CellIdentity cellIdentity = radioRsp_network->dataRegResp.cellIdentity;
+ switch (cellIdentity.getTag()) {
+ case CellIdentity::noinit: {
+ checkMccMnc = false;
+ break;
+ }
+ case CellIdentity::gsm: {
+ CellIdentityGsm cig = cellIdentity.get<CellIdentity::gsm>();
+ mcc = cig.mcc;
+ mnc = cig.mnc;
+ break;
+ }
+ case CellIdentity::wcdma: {
+ CellIdentityWcdma ciw = cellIdentity.get<CellIdentity::wcdma>();
+ mcc = ciw.mcc;
+ mnc = ciw.mnc;
+ break;
+ }
+ case CellIdentity::tdscdma: {
+ CellIdentityTdscdma cit = cellIdentity.get<CellIdentity::tdscdma>();
+ mcc = cit.mcc;
+ mnc = cit.mnc;
+ break;
+ }
+ case CellIdentity::cdma: {
+ // CellIdentityCdma has no mcc/mnc
+ CellIdentityCdma cic = cellIdentity.get<CellIdentity::cdma>();
+ checkMccMnc = false;
+ break;
+ }
+ case CellIdentity::lte: {
+ CellIdentityLte cil = cellIdentity.get<CellIdentity::lte>();
+ mcc = cil.mcc;
+ mnc = cil.mnc;
+ break;
+ }
+ case CellIdentity::nr: {
+ CellIdentityNr cin = cellIdentity.get<CellIdentity::nr>();
+ mcc = cin.mcc;
+ mnc = cin.mnc;
+ break;
+ }
+ }
+
+ // 32 bit system might return invalid mcc and mnc string "\xff\xff..."
+ if (checkMccMnc && mcc.size() < 4 && mnc.size() < 4) {
+ int mcc_int = stoi(mcc);
+ int mnc_int = stoi(mnc);
+ EXPECT_TRUE(mcc_int >= 0 && mcc_int <= 999);
+ EXPECT_TRUE(mnc_int >= 0 && mnc_int <= 999);
+ }
+
+ // Check for access technology specific info
+ AccessTechnologySpecificInfo info = radioRsp_network->dataRegResp.accessTechnologySpecificInfo;
+ RadioTechnology rat = radioRsp_network->dataRegResp.rat;
+ // TODO: add logic for cdmaInfo
+ if (rat == RadioTechnology::LTE || rat == RadioTechnology::LTE_CA) {
+ ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::eutranInfo);
+ } else if (rat == RadioTechnology::NR) {
+ ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::ngranNrVopsInfo);
+ }
+}
+
+/*
+ * Test IRadioNetwork.getAvailableBandModes() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAvailableBandModes) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->getAvailableBandModes(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ALOGI("getAvailableBandModes, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INTERNAL_ERR,
+ // If REQUEST_NOT_SUPPORTED is returned, then it should also be
+ // returned for setBandMode().
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ bool hasUnspecifiedBandMode = false;
+ if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+ for (const RadioBandMode& mode : radioRsp_network->radioBandModes) {
+ // Automatic mode selection must be supported
+ if (mode == RadioBandMode::BAND_MODE_UNSPECIFIED) hasUnspecifiedBandMode = true;
+ }
+ ASSERT_TRUE(hasUnspecifiedBandMode);
+ }
+}
+
+/*
+ * Test IRadioNetwork.setIndicationFilter()
+ */
+TEST_P(RadioNetworkTest, setIndicationFilter) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_network->setIndicationFilter(serial, static_cast<int>(IndicationFilter::ALL));
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ALOGI("setIndicationFilter, rspInfo.error = %s\n",
+ toString(radioRsp_network->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setBarringPassword() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setBarringPassword) {
+ serial = GetRandomSerialNumber();
+ std::string facility = "";
+ std::string oldPassword = "";
+ std::string newPassword = "";
+
+ radio_network->setBarringPassword(serial, facility, oldPassword, newPassword);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::FDN_CHECK_FAILURE,
+ RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioNetwork.setSuppServiceNotifications() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setSuppServiceNotifications) {
+ serial = GetRandomSerialNumber();
+ bool enable = false;
+
+ radio_network->setSuppServiceNotifications(serial, enable);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ }
+}
+
+/*
+ * Test IRadioNetwork.getImsRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getImsRegistrationState) {
+ serial = GetRandomSerialNumber();
+
+ radio_network->getImsRegistrationState(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::MODEM_ERR, RadioError::INVALID_MODEM_STATE},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioNetwork.getOperator() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getOperator) {
+ LOG(DEBUG) << "getOperator";
+ serial = GetRandomSerialNumber();
+
+ radio_network->getOperator(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+ }
+ LOG(DEBUG) << "getOperator finished";
+}
+
+/*
+ * Test IRadioNetwork.getNetworkSelectionMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getNetworkSelectionMode) {
+ LOG(DEBUG) << "getNetworkSelectionMode";
+ serial = GetRandomSerialNumber();
+
+ radio_network->getNetworkSelectionMode(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+ }
+ LOG(DEBUG) << "getNetworkSelectionMode finished";
+}
+
+/*
+ * Test IRadioNetwork.setNetworkSelectionModeAutomatic() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNetworkSelectionModeAutomatic) {
+ LOG(DEBUG) << "setNetworkSelectionModeAutomatic";
+ serial = GetRandomSerialNumber();
+
+ radio_network->setNetworkSelectionModeAutomatic(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
+ RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setNetworkSelectionModeAutomatic finished";
+}
+
+/*
+ * Test IRadioNetwork.getAvailableNetworks() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAvailableNetworks) {
+ LOG(DEBUG) << "getAvailableNetworks";
+ serial = GetRandomSerialNumber();
+
+ radio_network->getAvailableNetworks(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+ ASSERT_TRUE(radioRsp_network->rspInfo.type == RadioResponseType::SOLICITED ||
+ radioRsp_network->rspInfo.type == RadioResponseType::SOLICITED_ACK_EXP);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::CANCELLED, RadioError::DEVICE_IN_USE,
+ RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getAvailableNetworks finished";
+}
+
+/*
+ * Test IRadioNetwork.setBandMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setBandMode) {
+ LOG(DEBUG) << "setBandMode";
+ serial = GetRandomSerialNumber();
+
+ radio_network->setBandMode(serial, RadioBandMode::BAND_MODE_USA);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setBandMode finished";
+}
+
+/*
+ * Test IRadioNetwork.setLocationUpdates() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setLocationUpdates) {
+ LOG(DEBUG) << "setLocationUpdates";
+ serial = GetRandomSerialNumber();
+
+ radio_network->setLocationUpdates(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ }
+ LOG(DEBUG) << "setLocationUpdates finished";
+}
+
+/*
+ * Test IRadioNetwork.setCdmaRoamingPreference() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setCdmaRoamingPreference) {
+ LOG(DEBUG) << "setCdmaRoamingPreference";
+ serial = GetRandomSerialNumber();
+
+ radio_network->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "setCdmaRoamingPreference finished";
+}
+
+/*
+ * Test IRadioNetwork.getCdmaRoamingPreference() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getCdmaRoamingPreference) {
+ LOG(DEBUG) << "getCdmaRoamingPreference";
+ serial = GetRandomSerialNumber();
+
+ radio_network->getCdmaRoamingPreference(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getCdmaRoamingPreference finished";
+}
+
+/*
+ * Test IRadioNetwork.getVoiceRadioTechnology() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getVoiceRadioTechnology) {
+ LOG(DEBUG) << "getVoiceRadioTechnology";
+ serial = GetRandomSerialNumber();
+
+ radio_network->getVoiceRadioTechnology(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+ }
+ LOG(DEBUG) << "getVoiceRadioTechnology finished";
+}
+
+/*
+ * Test IRadioNetwork.setCellInfoListRate() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setCellInfoListRate) {
+ LOG(DEBUG) << "setCellInfoListRate";
+ serial = GetRandomSerialNumber();
+
+ radio_network->setCellInfoListRate(serial, 10);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "setCellInfoListRate finished";
+}
+
+/*
+ * Test IRadioNetwork.supplyNetworkDepersonalization() for the response returned.
+ */
+TEST_P(RadioNetworkTest, supplyNetworkDepersonalization) {
+ LOG(DEBUG) << "supplyNetworkDepersonalization";
+ serial = GetRandomSerialNumber();
+
+ radio_network->supplyNetworkDepersonalization(serial, std::string("test"));
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INTERNAL_ERR,
+ RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+ RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
+ }
+ LOG(DEBUG) << "supplyNetworkDepersonalization finished";
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
new file mode 100644
index 0000000..29ba2f2
--- /dev/null
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/network/BnRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/network/BnRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/network/IRadioNetwork.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::network;
+
+class RadioNetworkTest;
+
+/* Callback class for radio network response */
+class RadioNetworkResponse : public BnRadioNetworkResponse {
+ protected:
+ RadioServiceTest& parent_network;
+
+ public:
+ RadioNetworkResponse(RadioServiceTest& parent_network);
+ virtual ~RadioNetworkResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ std::vector<RadioBandMode> radioBandModes;
+ std::vector<OperatorInfo> networkInfos;
+ bool isNrDualConnectivityEnabled;
+ int networkTypeBitmapResponse;
+ RegStateResult voiceRegResp;
+ RegStateResult dataRegResp;
+ CellIdentity barringCellIdentity;
+ std::vector<BarringInfo> barringInfoList;
+ UsageSetting usageSetting;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus getAllowedNetworkTypesBitmapResponse(
+ const RadioResponseInfo& info, const int32_t networkTypeBitmap) override;
+
+ virtual ndk::ScopedAStatus getAvailableBandModesResponse(
+ const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) override;
+
+ virtual ndk::ScopedAStatus getAvailableNetworksResponse(
+ const RadioResponseInfo& info, const std::vector<OperatorInfo>& networkInfos) override;
+
+ virtual ndk::ScopedAStatus getBarringInfoResponse(
+ const RadioResponseInfo& info, const CellIdentity& cellIdentity,
+ const std::vector<BarringInfo>& barringInfos) override;
+
+ virtual ndk::ScopedAStatus getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+ CdmaRoamingType type) override;
+
+ virtual ndk::ScopedAStatus getCellInfoListResponse(
+ const RadioResponseInfo& info, const std::vector<CellInfo>& cellInfo) override;
+
+ virtual ndk::ScopedAStatus getDataRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& dataRegResponse) override;
+
+ virtual ndk::ScopedAStatus getImsRegistrationStateResponse(
+ const RadioResponseInfo& info, bool isRegistered,
+ RadioTechnologyFamily ratFamily) override;
+
+ virtual ndk::ScopedAStatus getNetworkSelectionModeResponse(const RadioResponseInfo& info,
+ bool manual) override;
+
+ virtual ndk::ScopedAStatus getOperatorResponse(const RadioResponseInfo& info,
+ const std::string& longName,
+ const std::string& shortName,
+ const std::string& numeric) override;
+
+ virtual ndk::ScopedAStatus getSignalStrengthResponse(
+ const RadioResponseInfo& info, const SignalStrength& sigStrength) override;
+
+ virtual ndk::ScopedAStatus getSystemSelectionChannelsResponse(
+ const RadioResponseInfo& info,
+ const std::vector<RadioAccessSpecifier>& specifier) override;
+
+ virtual ndk::ScopedAStatus getUsageSettingResponse(const RadioResponseInfo& info,
+ UsageSetting usageSetting) override;
+
+ virtual ndk::ScopedAStatus getVoiceRadioTechnologyResponse(const RadioResponseInfo& info,
+ RadioTechnology rat) override;
+
+ virtual ndk::ScopedAStatus getVoiceRegistrationStateResponse(
+ const RadioResponseInfo& info, const RegStateResult& voiceRegResponse) override;
+
+ virtual ndk::ScopedAStatus isNrDualConnectivityEnabledResponse(const RadioResponseInfo& info,
+ bool isEnabled) override;
+
+ virtual ndk::ScopedAStatus setAllowedNetworkTypesBitmapResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setBandModeResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setBarringPasswordResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCdmaRoamingPreferenceResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCellInfoListRateResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setIndicationFilterResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setLinkCapacityReportingCriteriaResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setLocationUpdatesResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setNetworkSelectionModeAutomaticResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setNetworkSelectionModeManualResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setNrDualConnectivityStateResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setSignalStrengthReportingCriteriaResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setSuppServiceNotificationsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setSystemSelectionChannelsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setUsageSettingResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus startNetworkScanResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus stopNetworkScanResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus supplyNetworkDepersonalizationResponse(
+ const RadioResponseInfo& info, int32_t remainingRetries) override;
+};
+
+/* Callback class for radio network indication */
+class RadioNetworkIndication : public BnRadioNetworkIndication {
+ protected:
+ RadioServiceTest& parent_network;
+
+ public:
+ RadioNetworkIndication(RadioServiceTest& parent_network);
+ virtual ~RadioNetworkIndication() = default;
+
+ virtual ndk::ScopedAStatus barringInfoChanged(
+ RadioIndicationType type, const CellIdentity& cellIdentity,
+ const std::vector<BarringInfo>& barringInfos) override;
+
+ virtual ndk::ScopedAStatus cdmaPrlChanged(RadioIndicationType type, int32_t version) override;
+
+ virtual ndk::ScopedAStatus cellInfoList(RadioIndicationType type,
+ const std::vector<CellInfo>& records) override;
+
+ virtual ndk::ScopedAStatus currentLinkCapacityEstimate(
+ RadioIndicationType type, const LinkCapacityEstimate& lce) override;
+
+ virtual ndk::ScopedAStatus currentPhysicalChannelConfigs(
+ RadioIndicationType type, const std::vector<PhysicalChannelConfig>& configs) override;
+
+ virtual ndk::ScopedAStatus currentSignalStrength(RadioIndicationType type,
+ const SignalStrength& signalStrength) override;
+
+ virtual ndk::ScopedAStatus imsNetworkStateChanged(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus networkScanResult(RadioIndicationType type,
+ const NetworkScanResult& result) override;
+
+ virtual ndk::ScopedAStatus networkStateChanged(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus nitzTimeReceived(RadioIndicationType type,
+ const std::string& nitzTime, int64_t receivedTimeMs,
+ int64_t ageMs) override;
+
+ virtual ndk::ScopedAStatus registrationFailed(RadioIndicationType type,
+ const CellIdentity& cellIdentity,
+ const std::string& chosenPlmn, int32_t domain,
+ int32_t causeCode,
+ int32_t additionalCauseCode) override;
+
+ virtual ndk::ScopedAStatus restrictedStateChanged(RadioIndicationType type,
+ PhoneRestrictedState state) override;
+
+ virtual ndk::ScopedAStatus suppSvcNotify(RadioIndicationType type,
+ const SuppSvcNotification& suppSvc) override;
+
+ virtual ndk::ScopedAStatus voiceRadioTechChanged(RadioIndicationType type,
+ RadioTechnology rat) override;
+};
+
+// The main test class for Radio AIDL Network.
+class RadioNetworkTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+
+ /* radio network service handle */
+ std::shared_ptr<IRadioNetwork> radio_network;
+ /* radio network response handle */
+ std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+ /* radio network indication handle */
+ std::shared_ptr<RadioNetworkIndication> radioInd_network;
+
+ void invokeAndExpectResponse(std::function<ndk::ScopedAStatus(int32_t serial)> request,
+ std::vector<RadioError> errors_to_check);
+
+ // Helper function to reduce copy+paste
+ void testSetUsageSetting_InvalidValues(std::vector<RadioError> errors);
+
+ void stopNetworkScan();
+};
diff --git a/radio/aidl/vts/radio_sim_indication.cpp b/radio/aidl/vts/radio_sim_indication.cpp
new file mode 100644
index 0000000..c03d947
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_indication.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_sim_utils.h"
+
+RadioSimIndication::RadioSimIndication(RadioServiceTest& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimIndication::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::cdmaSubscriptionSourceChanged(
+ RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookChanged(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookRecordsReceived(
+ RadioIndicationType /*type*/, PbReceivedStatus /*status*/,
+ const std::vector<PhonebookRecordInfo>& /*records*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simRefresh(RadioIndicationType /*type*/,
+ const SimRefreshResult& /*refreshResult*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simStatusChanged(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkEventNotify(RadioIndicationType /*type*/,
+ const std::string& /*cmd*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkProactiveCommand(RadioIndicationType /*type*/,
+ const std::string& /*cmd*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkSessionEnd(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::subscriptionStatusChanged(RadioIndicationType /*type*/,
+ bool /*activate*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::uiccApplicationsEnablementChanged(
+ RadioIndicationType /*type*/, bool /*enabled*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_response.cpp b/radio/aidl/vts/radio_sim_response.cpp
new file mode 100644
index 0000000..391c9cb
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_response.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_sim_utils.h"
+
+RadioSimResponse::RadioSimResponse(RadioServiceTest& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::areUiccApplicationsEnabledResponse(
+ const RadioResponseInfo& info, bool enabled) {
+ rspInfo = info;
+ areUiccApplicationsEnabled = enabled;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getAllowedCarriersResponse(
+ const RadioResponseInfo& info, const CarrierRestrictions& carriers,
+ SimLockMultiSimPolicy multiSimPolicy) {
+ rspInfo = info;
+ carrierRestrictionsResp = carriers;
+ multiSimPolicyResp = multiSimPolicy;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionResponse(
+ const RadioResponseInfo& info, const std::string& /*mdn*/, const std::string& /*hSid*/,
+ const std::string& /*hNid*/, const std::string& /*min*/, const std::string& /*prl*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& info, CdmaSubscriptionSource /*source*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getFacilityLockForAppResponse(const RadioResponseInfo& info,
+ int32_t /*response*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getIccCardStatusResponse(const RadioResponseInfo& info,
+ const CardStatus& card_status) {
+ rspInfo = info;
+ cardStatus = card_status;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getImsiForAppResponse(const RadioResponseInfo& info,
+ const std::string& imsi_str) {
+ rspInfo = info;
+ imsi = imsi_str;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookCapacityResponse(
+ const RadioResponseInfo& info, const PhonebookCapacity& pbCapacity) {
+ rspInfo = info;
+ capacity = pbCapacity;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookRecordsResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccCloseLogicalChannelResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccIoForAppResponse(const RadioResponseInfo& info,
+ const IccIoResult& /*iccIo*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccOpenLogicalChannelResponse(
+ const RadioResponseInfo& info, int32_t /*channelId*/,
+ const std::vector<uint8_t>& /*selectResponse*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduBasicChannelResponse(
+ const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduLogicalChannelResponse(
+ const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::reportStkServiceIsRunningResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::requestIccSimAuthenticationResponse(
+ const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeResponse(const RadioResponseInfo& info,
+ const std::string& /*commandResponse*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+ const IccIoResult& /*iccIo*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendTerminalResponseToSimResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setAllowedCarriersResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCarrierInfoForImsiEncryptionResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setFacilityLockForAppResponse(const RadioResponseInfo& info,
+ int32_t /*retry*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setSimCardPowerResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setUiccSubscriptionResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPukForAppResponse(const RadioResponseInfo& info,
+ int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplySimDepersonalizationResponse(
+ const RadioResponseInfo& info, PersoSubstate /*persoType*/, int32_t /*remainingRetries*/) {
+ rspInfo = info;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::updateSimPhonebookRecordsResponse(
+ const RadioResponseInfo& info, int32_t recordIndex) {
+ rspInfo = info;
+ updatedRecordIndex = recordIndex;
+ parent_sim.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
new file mode 100644
index 0000000..64474c9
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioConst.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_sim_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioSimTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_sim = IRadioSim::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_sim.get());
+
+ radioRsp_sim = ndk::SharedRefBase::make<RadioSimResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_sim.get());
+
+ count_ = 0;
+
+ radioInd_sim = ndk::SharedRefBase::make<RadioSimIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_sim.get());
+
+ radio_sim->setResponseFunctions(radioRsp_sim, radioInd_sim);
+ // Assert SIM is present before testing
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+}
+
+void RadioSimTest::updateSimCardStatus() {
+ serial = GetRandomSerialNumber();
+ radio_sim->getIccCardStatus(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+}
+
+/*
+ * Test IRadioSim.setSimCardPower() for the response returned.
+ */
+TEST_P(RadioSimTest, setSimCardPower) {
+ /* Test setSimCardPower power down */
+ serial = GetRandomSerialNumber();
+ radio_sim->setSimCardPower(serial, CardPowerState::POWER_DOWN);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+ // setSimCardPower does not return until the request is handled, and should not trigger
+ // CardStatus::STATE_ABSENT when turning off power
+ if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+ /* Wait some time for setting sim power down and then verify it */
+ updateSimCardStatus();
+ // We cannot assert the consistency of CardState here due to b/203031664
+ // EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+ // applications should be an empty vector of AppStatus
+ EXPECT_EQ(0, cardStatus.applications.size());
+ }
+
+ // Give some time for modem to fully power down the SIM card
+ sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+ /* Test setSimCardPower power up */
+ serial = GetRandomSerialNumber();
+ radio_sim->setSimCardPower(serial, CardPowerState::POWER_UP);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+ // Give some time for modem to fully power up the SIM card
+ sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+ // setSimCardPower does not return until the request is handled. Just verify that we still
+ // have CardStatus::STATE_PRESENT after turning the power back on
+ if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+ }
+}
+
+/*
+ * Test IRadioSim.setCarrierInfoForImsiEncryption() for the response returned.
+ */
+TEST_P(RadioSimTest, setCarrierInfoForImsiEncryption) {
+ serial = GetRandomSerialNumber();
+ ImsiEncryptionInfo imsiInfo;
+ imsiInfo.mcc = "310";
+ imsiInfo.mnc = "004";
+ imsiInfo.carrierKey = (std::vector<uint8_t>){1, 2, 3, 4, 5, 6};
+ imsiInfo.keyIdentifier = "Test";
+ imsiInfo.expirationTime = 20180101;
+ imsiInfo.keyType = ImsiEncryptionInfo::PUBLIC_KEY_TYPE_EPDG;
+
+ radio_sim->setCarrierInfoForImsiEncryption(serial, imsiInfo);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookRecords) {
+ serial = GetRandomSerialNumber();
+ radio_sim->getSimPhonebookRecords(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookCapacity for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookCapacity) {
+ serial = GetRandomSerialNumber();
+ radio_sim->getSimPhonebookCapacity(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+
+ PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+ if (pbCapacity.maxAdnRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxNameLen > 0 && pbCapacity.maxNumberLen > 0);
+ EXPECT_TRUE(pbCapacity.usedAdnRecords <= pbCapacity.maxAdnRecords);
+ }
+
+ if (pbCapacity.maxEmailRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxEmailLen > 0);
+ EXPECT_TRUE(pbCapacity.usedEmailRecords <= pbCapacity.maxEmailRecords);
+ }
+
+ if (pbCapacity.maxAdditionalNumberRecords > 0) {
+ EXPECT_TRUE(pbCapacity.maxAdditionalNumberLen > 0);
+ EXPECT_TRUE(pbCapacity.usedAdditionalNumberRecords <=
+ pbCapacity.maxAdditionalNumberRecords);
+ }
+ }
+}
+
+/*
+ * Test IRadioSim.updateSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, updateSimPhonebookRecords) {
+ serial = GetRandomSerialNumber();
+ radio_sim->getSimPhonebookCapacity(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+
+ serial = GetRandomSerialNumber();
+ radio_sim->getSimPhonebookRecords(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+
+ if (pbCapacity.maxAdnRecords > 0 && pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
+ // Add a phonebook record
+ PhonebookRecordInfo recordInfo;
+ recordInfo.recordId = 0;
+ recordInfo.name = "ABC";
+ recordInfo.number = "1234567890";
+ serial = GetRandomSerialNumber();
+ radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+ int index = radioRsp_sim->updatedRecordIndex;
+ EXPECT_TRUE(index > 0);
+
+ // Deleted a phonebook record
+ recordInfo.recordId = index;
+ recordInfo.name = "";
+ recordInfo.number = "";
+ serial = GetRandomSerialNumber();
+ radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+ }
+ }
+}
+
+/*
+ * Test IRadioSim.enableUiccApplications() for the response returned.
+ * For SIM ABSENT case.
+ */
+TEST_P(RadioSimTest, togglingUiccApplicationsSimAbsent) {
+ // This test case only test SIM ABSENT case.
+ if (cardStatus.cardState != CardStatus::STATE_ABSENT) return;
+
+ // Disable Uicc applications.
+ serial = GetRandomSerialNumber();
+ radio_sim->enableUiccApplications(serial, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+ EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+
+ // Query Uicc application enablement.
+ serial = GetRandomSerialNumber();
+ radio_sim->areUiccApplicationsEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+ EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+}
+
+/*
+ * Test IRadioSim.enableUiccApplications() for the response returned.
+ * For SIM PRESENT case.
+ */
+TEST_P(RadioSimTest, togglingUiccApplicationsSimPresent) {
+ // This test case only test SIM ABSENT case.
+ if (cardStatus.cardState != CardStatus::STATE_PRESENT) return;
+ if (cardStatus.applications.size() == 0) return;
+
+ // Disable Uicc applications.
+ serial = GetRandomSerialNumber();
+ radio_sim->enableUiccApplications(serial, false);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is present, there shouldn't be error.
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+ // Query Uicc application enablement.
+ serial = GetRandomSerialNumber();
+ radio_sim->areUiccApplicationsEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is present, there shouldn't be error.
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+ ASSERT_FALSE(radioRsp_sim->areUiccApplicationsEnabled);
+
+ // Enable Uicc applications.
+ serial = GetRandomSerialNumber();
+ radio_sim->enableUiccApplications(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is present, there shouldn't be error.
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+ // Query Uicc application enablement.
+ serial = GetRandomSerialNumber();
+ radio_sim->areUiccApplicationsEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ // As SIM is present, there shouldn't be error.
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+ ASSERT_TRUE(radioRsp_sim->areUiccApplicationsEnabled);
+}
+
+/*
+ * Test IRadioSim.areUiccApplicationsEnabled() for the response returned.
+ */
+TEST_P(RadioSimTest, areUiccApplicationsEnabled) {
+ // Disable Uicc applications.
+ serial = GetRandomSerialNumber();
+ radio_sim->areUiccApplicationsEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ // If SIM is absent, RadioError::SIM_ABSENT should be thrown. Otherwise there shouldn't be any
+ // error.
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+ } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+ }
+}
+
+/*
+ * Test IRadioSim.getAllowedCarriers() for the response returned.
+ */
+TEST_P(RadioSimTest, getAllowedCarriers) {
+ serial = GetRandomSerialNumber();
+
+ radio_sim->getAllowedCarriers(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/**
+ * Test IRadioSim.setAllowedCarriers() for the response returned.
+ */
+TEST_P(RadioSimTest, setAllowedCarriers) {
+ // TODO (b/210712359): remove once shim supports 1.4 or alternative is found
+ GTEST_SKIP();
+ serial = GetRandomSerialNumber();
+ CarrierRestrictions carrierRestrictions;
+ memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
+ carrierRestrictions.allowedCarriers.resize(1);
+ carrierRestrictions.excludedCarriers.resize(0);
+ carrierRestrictions.allowedCarriers[0].mcc = std::string("123");
+ carrierRestrictions.allowedCarriers[0].mnc = std::string("456");
+ carrierRestrictions.allowedCarriers[0].matchType = Carrier::MATCH_TYPE_ALL;
+ carrierRestrictions.allowedCarriers[0].matchData = std::string();
+ carrierRestrictions.allowedCarriersPrioritized = true;
+ SimLockMultiSimPolicy multisimPolicy = SimLockMultiSimPolicy::NO_MULTISIM_POLICY;
+
+ radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+
+ if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+ /* Verify the update of the SIM status. This might need some time */
+ if (cardStatus.cardState != CardStatus::STATE_ABSENT) {
+ updateSimCardStatus();
+ auto startTime = std::chrono::system_clock::now();
+ while (cardStatus.cardState != CardStatus::STATE_RESTRICTED &&
+ std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now() - startTime)
+ .count() < 30) {
+ /* Set 2 seconds as interval to check card status */
+ sleep(2);
+ updateSimCardStatus();
+ }
+ EXPECT_EQ(CardStatus::STATE_RESTRICTED, cardStatus.cardState);
+ }
+
+ /* Verify that configuration was set correctly, retrieving it from the modem */
+ serial = GetRandomSerialNumber();
+
+ radio_sim->getAllowedCarriers(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+ EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
+ EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarriers.size());
+ ASSERT_TRUE(std::string("123") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mcc);
+ ASSERT_TRUE(std::string("456") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mnc);
+ EXPECT_EQ(Carrier::MATCH_TYPE_ALL,
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].matchType);
+ ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
+ EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
+
+ sleep(10);
+
+ /**
+ * Another test case of the API to cover to allow carrier.
+ * If the API is supported, this is also used to reset to no carrier restriction
+ * status for cardStatus.
+ */
+ memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
+ carrierRestrictions.allowedCarriers.resize(0);
+ carrierRestrictions.excludedCarriers.resize(0);
+ carrierRestrictions.allowedCarriersPrioritized = false;
+
+ serial = GetRandomSerialNumber();
+ radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+ if (cardStatus.cardState != CardStatus::STATE_ABSENT) {
+ /* Resetting back to no carrier restriction needs some time */
+ updateSimCardStatus();
+ auto startTime = std::chrono::system_clock::now();
+ while (cardStatus.cardState == CardStatus::STATE_RESTRICTED &&
+ std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now() - startTime)
+ .count() < 10) {
+ /* Set 2 seconds as interval to check card status */
+ sleep(2);
+ updateSimCardStatus();
+ }
+ EXPECT_NE(CardStatus::STATE_RESTRICTED, cardStatus.cardState);
+ sleep(10);
+ }
+ }
+}
+
+/*
+ * Test IRadioSim.getIccCardStatus() for the response returned.
+ */
+TEST_P(RadioSimTest, getIccCardStatus) {
+ LOG(DEBUG) << "getIccCardStatus";
+ EXPECT_LE(cardStatus.applications.size(), RadioConst::CARD_MAX_APPS);
+ EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+ EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+ EXPECT_LT(cardStatus.imsSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+ LOG(DEBUG) << "getIccCardStatus finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPinForApp() for the response returned
+ */
+TEST_P(RadioSimTest, supplyIccPinForApp) {
+ LOG(DEBUG) << "supplyIccPinForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->supplyIccPinForApp(serial, std::string("test1"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ }
+ LOG(DEBUG) << "supplyIccPinForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPukForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPukForApp) {
+ LOG(DEBUG) << "supplyIccPukForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->supplyIccPukForApp(serial, std::string("test1"), std::string("test2"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT, RadioError::INVALID_SIM_STATE}));
+ }
+ }
+ LOG(DEBUG) << "supplyIccPukForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPin2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPin2ForApp) {
+ LOG(DEBUG) << "supplyIccPin2ForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->supplyIccPin2ForApp(serial, std::string("test1"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT,
+ RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_PUK2}));
+ }
+ }
+ LOG(DEBUG) << "supplyIccPin2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPuk2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPuk2ForApp) {
+ LOG(DEBUG) << "supplyIccPuk2ForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->supplyIccPuk2ForApp(serial, std::string("test1"), std::string("test2"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT, RadioError::INVALID_SIM_STATE}));
+ }
+ }
+ LOG(DEBUG) << "supplyIccPuk2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.changeIccPinForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, changeIccPinForApp) {
+ LOG(DEBUG) << "changeIccPinForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->changeIccPinForApp(serial, std::string("test1"), std::string("test2"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ }
+ LOG(DEBUG) << "changeIccPinForApp finished";
+}
+
+/*
+ * Test IRadioSim.changeIccPin2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, changeIccPin2ForApp) {
+ LOG(DEBUG) << "changeIccPin2ForApp";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+ // 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->changeIccPin2ForApp(serial, std::string("test1"), std::string("test2"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::PASSWORD_INCORRECT,
+ RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_PUK2}));
+ }
+ }
+ LOG(DEBUG) << "changeIccPin2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.getImsiForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, getImsiForApp) {
+ LOG(DEBUG) << "getImsiForApp";
+ serial = GetRandomSerialNumber();
+
+ // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+ cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+ radio_sim->getImsiForApp(serial, cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+
+ // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more than 15
+ if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+ EXPECT_NE(radioRsp_sim->imsi, std::string());
+ EXPECT_GE((int)(radioRsp_sim->imsi).size(), 6);
+ EXPECT_LE((int)(radioRsp_sim->imsi).size(), 15);
+ }
+ }
+ }
+ LOG(DEBUG) << "getImsiForApp finished";
+}
+
+/*
+ * Test IRadioSim.iccIoForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, iccIoForApp) {
+ LOG(DEBUG) << "iccIoForApp";
+ serial = GetRandomSerialNumber();
+
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ IccIo iccIo;
+ iccIo.command = 0xc0;
+ iccIo.fileId = 0x6f11;
+ iccIo.path = std::string("3F007FFF");
+ iccIo.p1 = 0;
+ iccIo.p2 = 0;
+ iccIo.p3 = 0;
+ iccIo.data = std::string();
+ iccIo.pin2 = std::string();
+ iccIo.aid = cardStatus.applications[i].aidPtr;
+
+ radio_sim->iccIoForApp(serial, iccIo);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ }
+ LOG(DEBUG) << "iccIoForApp finished";
+}
+
+/*
+ * Test IRadioSim.iccTransmitApduBasicChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccTransmitApduBasicChannel) {
+ LOG(DEBUG) << "iccTransmitApduBasicChannel";
+ serial = GetRandomSerialNumber();
+ SimApdu msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.data = std::string();
+
+ radio_sim->iccTransmitApduBasicChannel(serial, msg);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ LOG(DEBUG) << "iccTransmitApduBasicChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccOpenLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccOpenLogicalChannel) {
+ LOG(DEBUG) << "iccOpenLogicalChannel";
+ serial = GetRandomSerialNumber();
+ int p2 = 0x04;
+ // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ radio_sim->iccOpenLogicalChannel(serial, cardStatus.applications[i].aidPtr, p2);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ }
+ LOG(DEBUG) << "iccOpenLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccCloseLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccCloseLogicalChannel) {
+ LOG(DEBUG) << "iccCloseLogicalChannel";
+ serial = GetRandomSerialNumber();
+ // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
+ radio_sim->iccCloseLogicalChannel(serial, 0);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp_sim->rspInfo.error);
+ LOG(DEBUG) << "iccCloseLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccTransmitApduLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccTransmitApduLogicalChannel) {
+ LOG(DEBUG) << "iccTransmitApduLogicalChannel";
+ serial = GetRandomSerialNumber();
+ SimApdu msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.data = std::string();
+
+ radio_sim->iccTransmitApduLogicalChannel(serial, msg);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ LOG(DEBUG) << "iccTransmitApduLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.requestIccSimAuthentication() for the response returned.
+ */
+TEST_P(RadioSimTest, requestIccSimAuthentication) {
+ LOG(DEBUG) << "requestIccSimAuthentication";
+ serial = GetRandomSerialNumber();
+
+ // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
+ // or REQUEST_NOT_SUPPORTED returned as error.
+ for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+ radio_sim->requestIccSimAuthentication(serial, 0, std::string("test"),
+ cardStatus.applications[i].aidPtr);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "requestIccSimAuthentication finished";
+}
+
+/*
+ * Test IRadioSim.getFacilityLockForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, getFacilityLockForApp) {
+ serial = GetRandomSerialNumber();
+ std::string facility = "";
+ std::string password = "";
+ int32_t serviceClass = 1;
+ std::string appId = "";
+
+ radio_sim->getFacilityLockForApp(serial, facility, password, serviceClass, appId);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioSim.setFacilityLockForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, setFacilityLockForApp) {
+ serial = GetRandomSerialNumber();
+ std::string facility = "";
+ bool lockState = false;
+ std::string password = "";
+ int32_t serviceClass = 1;
+ std::string appId = "";
+
+ radio_sim->setFacilityLockForApp(serial, facility, lockState, password, serviceClass, appId);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioSim.getCdmaSubscription() for the response returned.
+ */
+TEST_P(RadioSimTest, getCdmaSubscription) {
+ LOG(DEBUG) << "getCdmaSubscription";
+ serial = GetRandomSerialNumber();
+
+ radio_sim->getCdmaSubscription(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+ }
+ LOG(DEBUG) << "getCdmaSubscription finished";
+}
+
+/*
+ * Test IRadioSim.getCdmaSubscriptionSource() for the response returned.
+ */
+TEST_P(RadioSimTest, getCdmaSubscriptionSource) {
+ LOG(DEBUG) << "getCdmaSubscriptionSource";
+ serial = GetRandomSerialNumber();
+
+ radio_sim->getCdmaSubscriptionSource(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+ }
+ LOG(DEBUG) << "getCdmaSubscriptionSource finished";
+}
+
+/*
+ * Test IRadioSim.setCdmaSubscriptionSource() for the response returned.
+ */
+TEST_P(RadioSimTest, setCdmaSubscriptionSource) {
+ LOG(DEBUG) << "setCdmaSubscriptionSource";
+ serial = GetRandomSerialNumber();
+
+ radio_sim->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setCdmaSubscriptionSource finished";
+}
+
+/*
+ * Test IRadioSim.setUiccSubscription() for the response returned.
+ */
+TEST_P(RadioSimTest, setUiccSubscription) {
+ LOG(DEBUG) << "setUiccSubscription";
+ serial = GetRandomSerialNumber();
+ SelectUiccSub item;
+ memset(&item, 0, sizeof(item));
+
+ radio_sim->setUiccSubscription(serial, item);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setUiccSubscription finished";
+}
+
+/*
+ * Test IRadioSim.sendEnvelope() for the response returned.
+ */
+TEST_P(RadioSimTest, sendEnvelope) {
+ LOG(DEBUG) << "sendEnvelope";
+ serial = GetRandomSerialNumber();
+
+ // Test with sending empty string
+ std::string content = "";
+
+ radio_sim->sendEnvelope(serial, content);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendEnvelope finished";
+}
+
+/*
+ * Test IRadioSim.sendTerminalResponseToSim() for the response returned.
+ */
+TEST_P(RadioSimTest, sendTerminalResponseToSim) {
+ LOG(DEBUG) << "sendTerminalResponseToSim";
+ serial = GetRandomSerialNumber();
+
+ // Test with sending empty string
+ std::string commandResponse = "";
+
+ radio_sim->sendTerminalResponseToSim(serial, commandResponse);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendTerminalResponseToSim finished";
+}
+
+/*
+ * Test IRadioSim.reportStkServiceIsRunning() for the response returned.
+ */
+TEST_P(RadioSimTest, reportStkServiceIsRunning) {
+ LOG(DEBUG) << "reportStkServiceIsRunning";
+ serial = GetRandomSerialNumber();
+
+ radio_sim->reportStkServiceIsRunning(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "reportStkServiceIsRunning finished";
+}
+
+/*
+ * Test IRadioSim.sendEnvelopeWithStatus() for the response returned with empty
+ * string.
+ */
+TEST_P(RadioSimTest, sendEnvelopeWithStatus) {
+ LOG(DEBUG) << "sendEnvelopeWithStatus";
+ serial = GetRandomSerialNumber();
+
+ // Test with sending empty string
+ std::string contents = "";
+
+ radio_sim->sendEnvelopeWithStatus(serial, contents);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_sim->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendEnvelopeWithStatus finished";
+}
diff --git a/radio/aidl/vts/radio_sim_utils.h b/radio/aidl/vts/radio_sim_utils.h
new file mode 100644
index 0000000..83f1cbc
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_utils.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/sim/BnRadioSimIndication.h>
+#include <aidl/android/hardware/radio/sim/BnRadioSimResponse.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::sim;
+
+class RadioSimTest;
+
+/* Callback class for radio SIM response */
+class RadioSimResponse : public BnRadioSimResponse {
+ protected:
+ RadioServiceTest& parent_sim;
+
+ public:
+ RadioSimResponse(RadioServiceTest& parent_sim);
+ virtual ~RadioSimResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ CarrierRestrictions carrierRestrictionsResp;
+ SimLockMultiSimPolicy multiSimPolicyResp;
+ bool canToggleUiccApplicationsEnablement;
+ bool areUiccApplicationsEnabled;
+ PhonebookCapacity capacity;
+ int32_t updatedRecordIndex;
+ std::string imsi;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus areUiccApplicationsEnabledResponse(const RadioResponseInfo& info,
+ bool enabled) override;
+
+ virtual ndk::ScopedAStatus changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus changeIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus enableUiccApplicationsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getAllowedCarriersResponse(
+ const RadioResponseInfo& info, const CarrierRestrictions& carriers,
+ const SimLockMultiSimPolicy multiSimPolicy) override;
+
+ virtual ndk::ScopedAStatus getCdmaSubscriptionResponse(
+ const RadioResponseInfo& info, const std::string& mdn, const std::string& hSid,
+ const std::string& hNid, const std::string& min, const std::string& prl) override;
+
+ virtual ndk::ScopedAStatus getCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& info, CdmaSubscriptionSource source) override;
+
+ virtual ndk::ScopedAStatus getFacilityLockForAppResponse(const RadioResponseInfo& info,
+ int32_t response) override;
+
+ virtual ndk::ScopedAStatus getIccCardStatusResponse(const RadioResponseInfo& info,
+ const CardStatus& cardStatus) override;
+
+ virtual ndk::ScopedAStatus getImsiForAppResponse(const RadioResponseInfo& info,
+ const std::string& imsi) override;
+
+ virtual ndk::ScopedAStatus getSimPhonebookCapacityResponse(
+ const RadioResponseInfo& info, const PhonebookCapacity& capacity) override;
+
+ virtual ndk::ScopedAStatus getSimPhonebookRecordsResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus iccCloseLogicalChannelResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus iccIoForAppResponse(const RadioResponseInfo& info,
+ const IccIoResult& iccIo) override;
+
+ virtual ndk::ScopedAStatus iccOpenLogicalChannelResponse(
+ const RadioResponseInfo& info, int32_t channelId,
+ const std::vector<uint8_t>& selectResponse) override;
+
+ virtual ndk::ScopedAStatus iccTransmitApduBasicChannelResponse(
+ const RadioResponseInfo& info, const IccIoResult& result) override;
+
+ virtual ndk::ScopedAStatus iccTransmitApduLogicalChannelResponse(
+ const RadioResponseInfo& info, const IccIoResult& result) override;
+
+ virtual ndk::ScopedAStatus reportStkServiceIsRunningResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus requestIccSimAuthenticationResponse(
+ const RadioResponseInfo& info, const IccIoResult& result) override;
+
+ virtual ndk::ScopedAStatus sendEnvelopeResponse(const RadioResponseInfo& info,
+ const std::string& commandResponse) override;
+
+ virtual ndk::ScopedAStatus sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+ const IccIoResult& iccIo) override;
+
+ virtual ndk::ScopedAStatus sendTerminalResponseToSimResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setAllowedCarriersResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCarrierInfoForImsiEncryptionResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCdmaSubscriptionSourceResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setFacilityLockForAppResponse(const RadioResponseInfo& info,
+ int32_t retry) override;
+
+ virtual ndk::ScopedAStatus setSimCardPowerResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setUiccSubscriptionResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus supplyIccPinForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus supplyIccPukForAppResponse(const RadioResponseInfo& info,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus supplySimDepersonalizationResponse(
+ const RadioResponseInfo& info, PersoSubstate persoType,
+ int32_t remainingRetries) override;
+
+ virtual ndk::ScopedAStatus updateSimPhonebookRecordsResponse(
+ const RadioResponseInfo& info, int32_t updatedRecordIndex) override;
+};
+
+/* Callback class for radio SIM indication */
+class RadioSimIndication : public BnRadioSimIndication {
+ protected:
+ RadioServiceTest& parent_sim;
+
+ public:
+ RadioSimIndication(RadioServiceTest& parent_sim);
+ virtual ~RadioSimIndication() = default;
+
+ virtual ndk::ScopedAStatus carrierInfoForImsiEncryption(RadioIndicationType info) override;
+
+ virtual ndk::ScopedAStatus cdmaSubscriptionSourceChanged(
+ RadioIndicationType type, CdmaSubscriptionSource cdmaSource) override;
+
+ virtual ndk::ScopedAStatus simPhonebookChanged(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus simPhonebookRecordsReceived(
+ RadioIndicationType type, PbReceivedStatus status,
+ const std::vector<PhonebookRecordInfo>& records) override;
+
+ virtual ndk::ScopedAStatus simRefresh(RadioIndicationType type,
+ const SimRefreshResult& refreshResult) override;
+
+ virtual ndk::ScopedAStatus simStatusChanged(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus stkEventNotify(RadioIndicationType type,
+ const std::string& cmd) override;
+
+ virtual ndk::ScopedAStatus stkProactiveCommand(RadioIndicationType type,
+ const std::string& cmd) override;
+
+ virtual ndk::ScopedAStatus stkSessionEnd(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus subscriptionStatusChanged(RadioIndicationType type,
+ bool activate) override;
+
+ virtual ndk::ScopedAStatus uiccApplicationsEnablementChanged(RadioIndicationType type,
+ bool enabled) override;
+};
+
+// The main test class for Radio AIDL SIM.
+class RadioSimTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+
+ /* Override updateSimCardStatus in RadioServiceTest to not call setResponseFunctions */
+ void updateSimCardStatus();
+
+ /* radio SIM service handle in RadioServiceTest */
+ /* radio SIM response handle */
+ std::shared_ptr<RadioSimResponse> radioRsp_sim;
+ /* radio SIM indication handle */
+ std::shared_ptr<RadioSimIndication> radioInd_sim;
+};
diff --git a/radio/aidl/vts/radio_voice_indication.cpp b/radio/aidl/vts/radio_voice_indication.cpp
new file mode 100644
index 0000000..3fee326
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_indication.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_voice_utils.h"
+
+RadioVoiceIndication::RadioVoiceIndication(RadioServiceTest& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceIndication::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+ const CdmaSignalInfoRecord& /*record*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::callStateChanged(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaCallWaiting(
+ RadioIndicationType /*type*/, const CdmaCallWaiting& /*callWaitingRecord*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaInfoRec(
+ RadioIndicationType /*type*/, const std::vector<CdmaInformationRecord>& /*records*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+ CdmaOtaProvisionStatus /*status*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::currentEmergencyNumberList(
+ RadioIndicationType /*type*/, const std::vector<EmergencyNumber>& /*emergencyNumberList*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::indicateRingbackTone(RadioIndicationType /*type*/,
+ bool /*start*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::onSupplementaryServiceIndication(
+ RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::onUssd(RadioIndicationType /*type*/,
+ UssdModeType /*modeType*/,
+ const std::string& /*msg*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::resendIncallMute(RadioIndicationType /*type*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::srvccStateNotify(RadioIndicationType /*type*/,
+ SrvccState /*state*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallControlAlphaNotify(RadioIndicationType /*type*/,
+ const std::string& /*alpha*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallSetup(RadioIndicationType /*type*/,
+ int64_t /*timeout*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_response.cpp b/radio/aidl/vts/radio_voice_response.cpp
new file mode 100644
index 0000000..dd7b1bf
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_response.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_voice_utils.h"
+
+RadioVoiceResponse::RadioVoiceResponse(RadioServiceTest& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceResponse::acceptCallResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::acknowledgeRequest(int32_t /*serial*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::cancelPendingUssdResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::conferenceResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::dialResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::emergencyDialResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::exitEmergencyCallbackModeResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::explicitCallTransferResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallForwardStatusResponse(
+ const RadioResponseInfo& info, const std::vector<CallForwardInfo>& /*callForwardInfos*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallWaitingResponse(const RadioResponseInfo& info,
+ bool /*enable*/,
+ int32_t /*serviceClass*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClipResponse(const RadioResponseInfo& info,
+ ClipStatus /*status*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClirResponse(const RadioResponseInfo& info, int32_t /*n*/,
+ int32_t /*m*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCurrentCallsResponse(const RadioResponseInfo& info,
+ const std::vector<Call>& calls) {
+ rspInfo = info;
+ currentCalls = calls;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getLastCallFailCauseResponse(
+ const RadioResponseInfo& info, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getMuteResponse(const RadioResponseInfo& info,
+ bool /*enable*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getPreferredVoicePrivacyResponse(
+ const RadioResponseInfo& info, bool /*enable*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getTtyModeResponse(const RadioResponseInfo& info,
+ TtyMode /*mode*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::handleStkCallSetupRequestFromSimResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupConnectionResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupForegroundResumeBackgroundResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupWaitingOrBackgroundResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::isVoNrEnabledResponse(const RadioResponseInfo& info,
+ bool /*enabled*/) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::rejectCallResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendBurstDtmfResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendCdmaFeatureCodeResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendDtmfResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendUssdResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::separateConnectionResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallForwardResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallWaitingResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setClirResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setMuteResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setPreferredVoicePrivacyResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setTtyModeResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setVoNrEnabledResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::startDtmfResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::stopDtmfResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::switchWaitingOrHoldingAndActiveResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_voice.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
new file mode 100644
index 0000000..249ee63
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/voice/EmergencyServiceCategory.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_voice_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioVoiceTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_voice = IRadioVoice::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_voice.get());
+
+ radioRsp_voice = ndk::SharedRefBase::make<RadioVoiceResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_voice.get());
+
+ count_ = 0;
+
+ radioInd_voice = ndk::SharedRefBase::make<RadioVoiceIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_voice.get());
+
+ radio_voice->setResponseFunctions(radioRsp_voice, radioInd_voice);
+
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+ // Assert IRadioConfig exists before testing
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+
+ if (isDsDsEnabled() || isTsTsEnabled()) {
+ radio_network = IRadioNetwork::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(
+ "android.hardware.radio.network.IRadioNetwork/slot1")));
+ ASSERT_NE(nullptr, radio_network.get());
+ radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+ radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+ radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+ }
+}
+
+ndk::ScopedAStatus RadioVoiceTest::clearPotentialEstablishedCalls() {
+ // Get the current call Id to hangup the established emergency call.
+ serial = GetRandomSerialNumber();
+ radio_voice->getCurrentCalls(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+
+ // Hang up to disconnect the established call channels.
+ for (const Call& call : radioRsp_voice->currentCalls) {
+ serial = GetRandomSerialNumber();
+ radio_voice->hangup(serial, call.index);
+ ALOGI("Hang up to disconnect the established call channel: %d", call.index);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ // Give some time for modem to disconnect the established call channel.
+ sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME);
+ }
+
+ // Verify there are no more current calls.
+ serial = GetRandomSerialNumber();
+ radio_voice->getCurrentCalls(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(0, radioRsp_voice->currentCalls.size());
+ return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() for the response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial) {
+ if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+ ALOGI("Skipping emergencyDial because voice call is not supported in device");
+ return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
+ } else {
+ ALOGI("Running emergencyDial because voice call is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ Dial dialInfo;
+ dialInfo.address = std::string("911");
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
+ std::vector<std::string> urns = {""};
+ EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+ ndk::ScopedAStatus res =
+ radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_voice->rspInfo.error).c_str());
+
+ RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+ // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+ // or Emergency_Only.
+ if (isDsDsEnabled() || isTsTsEnabled()) {
+ serial = GetRandomSerialNumber();
+ radio_network->getVoiceRegistrationState(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+ } else {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+
+ // Give some time for modem to establish the emergency call channel.
+ sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+ // Disconnect all the potential established calls to prevent them affecting other tests.
+ clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with specified service and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withServices) {
+ if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+ ALOGI("Skipping emergencyDial because voice call is not supported in device");
+ return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
+ } else {
+ ALOGI("Running emergencyDial because voice call is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ Dial dialInfo;
+ dialInfo.address = std::string("911");
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::AMBULANCE);
+ std::vector<std::string> urns = {"urn:service:sos.ambulance"};
+ EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+ ndk::ScopedAStatus res =
+ radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ALOGI("emergencyDial_withServices, rspInfo.error = %s\n",
+ toString(radioRsp_voice->rspInfo.error).c_str());
+ RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+ // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+ // or Emergency_Only.
+ if (isDsDsEnabled() || isTsTsEnabled()) {
+ serial = GetRandomSerialNumber();
+ radio_network->getVoiceRegistrationState(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+ } else {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+ // Give some time for modem to establish the emergency call channel.
+ sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+ // Disconnect all the potential established calls to prevent them affecting other tests.
+ clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with known emergency call routing and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withEmergencyRouting) {
+ if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+ ALOGI("Skipping emergencyDial because voice call is not supported in device");
+ return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
+ } else {
+ ALOGI("Running emergencyDial because voice call is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ Dial dialInfo;
+ dialInfo.address = std::string("911");
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
+ std::vector<std::string> urns = {""};
+ EmergencyCallRouting routing = EmergencyCallRouting::EMERGENCY;
+
+ ndk::ScopedAStatus res =
+ radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
+ toString(radioRsp_voice->rspInfo.error).c_str());
+ RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+ // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+ // or Emergency_Only.
+ if (isDsDsEnabled() || isTsTsEnabled()) {
+ serial = GetRandomSerialNumber();
+ radio_network->getVoiceRegistrationState(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+ } else {
+ EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+ }
+
+ // Give some time for modem to establish the emergency call channel.
+ sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+ // Disconnect all the potential established calls to prevent them affecting other tests.
+ clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.getCurrentCalls() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCurrentCalls) {
+ serial = GetRandomSerialNumber();
+ radio_voice->getCurrentCalls(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+}
+
+/*
+ * Test IRadioVoice.getClir() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getClir) {
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getClir(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioVoice.setClir() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setClir) {
+ serial = GetRandomSerialNumber();
+ int32_t status = 1;
+
+ radio_voice->setClir(serial, status);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+ }
+}
+
+/*
+ * Test IRadioVoice.getClip() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getClip) {
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getClip(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+}
+
+/*
+ * Test IRadioVoice.getTtyMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getTtyMode) {
+ LOG(DEBUG) << "getTtyMode";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getTtyMode(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+ }
+ LOG(DEBUG) << "getTtyMode finished";
+}
+
+/*
+ * Test IRadioVoice.setTtyMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setTtyMode) {
+ LOG(DEBUG) << "setTtyMode";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setTtyMode(serial, TtyMode::OFF);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+ }
+ LOG(DEBUG) << "setTtyMode finished";
+}
+
+/*
+ * Test IRadioVoice.setPreferredVoicePrivacy() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setPreferredVoicePrivacy) {
+ LOG(DEBUG) << "setPreferredVoicePrivacy";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setPreferredVoicePrivacy(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "setPreferredVoicePrivacy finished";
+}
+
+/*
+ * Test IRadioVoice.getPreferredVoicePrivacy() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getPreferredVoicePrivacy) {
+ LOG(DEBUG) << "getPreferredVoicePrivacy";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getPreferredVoicePrivacy(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+ LOG(DEBUG) << "getPreferredVoicePrivacy finished";
+}
+
+/*
+ * Test IRadioVoice.exitEmergencyCallbackMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, exitEmergencyCallbackMode) {
+ LOG(DEBUG) << "exitEmergencyCallbackMode";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->exitEmergencyCallbackMode(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+ }
+ LOG(DEBUG) << "exitEmergencyCallbackMode finished";
+}
+
+/*
+ * Test IRadioVoice.handleStkCallSetupRequestFromSim() for the response returned.
+ */
+TEST_P(RadioVoiceTest, handleStkCallSetupRequestFromSim) {
+ LOG(DEBUG) << "handleStkCallSetupRequestFromSim";
+ serial = GetRandomSerialNumber();
+ bool accept = false;
+
+ radio_voice->handleStkCallSetupRequestFromSim(serial, accept);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "handleStkCallSetupRequestFromSim finished";
+}
+
+/*
+ * Test IRadioVoice.dial() for the response returned.
+ */
+TEST_P(RadioVoiceTest, dial) {
+ LOG(DEBUG) << "dial";
+ serial = GetRandomSerialNumber();
+
+ Dial dialInfo;
+ memset(&dialInfo, 0, sizeof(dialInfo));
+ dialInfo.address = std::string("123456789");
+
+ radio_voice->dial(serial, dialInfo);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::CANCELLED, RadioError::DEVICE_IN_USE, RadioError::FDN_CHECK_FAILURE,
+ RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+ RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+ RadioError::NO_NETWORK_FOUND, RadioError::NO_SUBSCRIPTION,
+ RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "dial finished";
+}
+
+/*
+ * Test IRadioVoice.hangup() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangup) {
+ LOG(DEBUG) << "hangup";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->hangup(serial, 1);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "hangup finished";
+}
+
+/*
+ * Test IRadioVoice.hangupWaitingOrBackground() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangupWaitingOrBackground) {
+ LOG(DEBUG) << "hangupWaitingOrBackground";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->hangupWaitingOrBackground(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "hangupWaitingOrBackground finished";
+}
+
+/*
+ * Test IRadioVoice.hangupForegroundResumeBackground() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangupForegroundResumeBackground) {
+ LOG(DEBUG) << "hangupForegroundResumeBackground";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->hangupForegroundResumeBackground(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "hangupForegroundResumeBackground finished";
+}
+
+/*
+ * Test IRadioVoice.switchWaitingOrHoldingAndActive() for the response returned.
+ */
+TEST_P(RadioVoiceTest, switchWaitingOrHoldingAndActive) {
+ LOG(DEBUG) << "switchWaitingOrHoldingAndActive";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->switchWaitingOrHoldingAndActive(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "switchWaitingOrHoldingAndActive finished";
+}
+
+/*
+ * Test IRadioVoice.conference() for the response returned.
+ */
+TEST_P(RadioVoiceTest, conference) {
+ LOG(DEBUG) << "conference";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->conference(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "conference finished";
+}
+
+/*
+ * Test IRadioVoice.rejectCall() for the response returned.
+ */
+TEST_P(RadioVoiceTest, rejectCall) {
+ LOG(DEBUG) << "rejectCall";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->rejectCall(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "rejectCall finished";
+}
+
+/*
+ * Test IRadioVoice.getLastCallFailCause() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getLastCallFailCause) {
+ LOG(DEBUG) << "getLastCallFailCause";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getLastCallFailCause(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::NONE},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getLastCallFailCause finished";
+}
+
+/*
+ * Test IRadioVoice.getCallForwardStatus() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCallForwardStatus) {
+ LOG(DEBUG) << "getCallForwardStatus";
+ serial = GetRandomSerialNumber();
+ CallForwardInfo callInfo;
+ memset(&callInfo, 0, sizeof(callInfo));
+ callInfo.number = std::string();
+
+ radio_voice->getCallForwardStatus(serial, callInfo);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getCallForwardStatus finished";
+}
+
+/*
+ * Test IRadioVoice.setCallForward() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setCallForward) {
+ LOG(DEBUG) << "setCallForward";
+ serial = GetRandomSerialNumber();
+ CallForwardInfo callInfo;
+ memset(&callInfo, 0, sizeof(callInfo));
+ callInfo.number = std::string();
+
+ radio_voice->setCallForward(serial, callInfo);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setCallForward finished";
+}
+
+/*
+ * Test IRadioVoice.getCallWaiting() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCallWaiting) {
+ LOG(DEBUG) << "getCallWaiting";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getCallWaiting(serial, 1);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "getCallWaiting finished";
+}
+
+/*
+ * Test IRadioVoice.setCallWaiting() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setCallWaiting) {
+ LOG(DEBUG) << "setCallWaiting";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setCallWaiting(serial, true, 1);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setCallWaiting finished";
+}
+
+/*
+ * Test IRadioVoice.acceptCall() for the response returned.
+ */
+TEST_P(RadioVoiceTest, acceptCall) {
+ LOG(DEBUG) << "acceptCall";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->acceptCall(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "acceptCall finished";
+}
+
+/*
+ * Test IRadioVoice.separateConnection() for the response returned.
+ */
+TEST_P(RadioVoiceTest, separateConnection) {
+ LOG(DEBUG) << "separateConnection";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->separateConnection(serial, 1);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "separateConnection finished";
+}
+
+/*
+ * Test IRadioVoice.explicitCallTransfer() for the response returned.
+ */
+TEST_P(RadioVoiceTest, explicitCallTransfer) {
+ LOG(DEBUG) << "explicitCallTransfer";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->explicitCallTransfer(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "explicitCallTransfer finished";
+}
+
+/*
+ * Test IRadioVoice.sendCdmaFeatureCode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendCdmaFeatureCode) {
+ LOG(DEBUG) << "sendCdmaFeatureCode";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->sendCdmaFeatureCode(serial, std::string());
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::INVALID_CALL_ID, RadioError::INVALID_MODEM_STATE,
+ RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendCdmaFeatureCode finished";
+}
+
+/*
+ * Test IRadioVoice.sendDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendDtmf) {
+ LOG(DEBUG) << "sendDtmf";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->sendDtmf(serial, "1");
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+ RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.startDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, startDtmf) {
+ LOG(DEBUG) << "startDtmf";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->startDtmf(serial, "1");
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+ RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "startDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.stopDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, stopDtmf) {
+ LOG(DEBUG) << "stopDtmf";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->stopDtmf(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_CALL_ID,
+ RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "stopDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.setMute() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setMute) {
+ LOG(DEBUG) << "setMute";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setMute(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "setMute finished";
+}
+
+/*
+ * Test IRadioVoice.getMute() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getMute) {
+ LOG(DEBUG) << "getMute";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->getMute(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+ }
+ LOG(DEBUG) << "getMute finished";
+}
+
+/*
+ * Test IRadioVoice.sendBurstDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendBurstDtmf) {
+ LOG(DEBUG) << "sendBurstDtmf";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->sendBurstDtmf(serial, "1", 0, 0);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+ RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendBurstDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.sendUssd() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendUssd) {
+ LOG(DEBUG) << "sendUssd";
+ serial = GetRandomSerialNumber();
+ radio_voice->sendUssd(serial, std::string("test"));
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "sendUssd finished";
+}
+
+/*
+ * Test IRadioVoice.cancelPendingUssd() for the response returned.
+ */
+TEST_P(RadioVoiceTest, cancelPendingUssd) {
+ LOG(DEBUG) << "cancelPendingUssd";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->cancelPendingUssd(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_voice->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+ CHECK_GENERAL_ERROR));
+ }
+ LOG(DEBUG) << "cancelPendingUssd finished";
+}
+
+/*
+ * Test IRadioVoice.isVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, isVoNrEnabled) {
+ LOG(DEBUG) << "isVoNrEnabled";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->isVoNrEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ LOG(DEBUG) << "isVoNrEnabled finished";
+}
+
+/*
+ * Test IRadioVoice.setVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setVoNrEnabled) {
+ LOG(DEBUG) << "setVoNrEnabled";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setVoNrEnabled(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ LOG(DEBUG) << "setVoNrEnabled finished";
+}
diff --git a/radio/aidl/vts/radio_voice_utils.h b/radio/aidl/vts/radio_voice_utils.h
new file mode 100644
index 0000000..0c3df7f
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_utils.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceIndication.h>
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceResponse.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoice.h>
+
+#include "radio_aidl_hal_utils.h"
+#include "radio_network_utils.h"
+
+using namespace aidl::android::hardware::radio::voice;
+
+class RadioVoiceTest;
+
+/* Callback class for radio voice response */
+class RadioVoiceResponse : public BnRadioVoiceResponse {
+ protected:
+ RadioServiceTest& parent_voice;
+
+ public:
+ RadioVoiceResponse(RadioServiceTest& parent_voice);
+ virtual ~RadioVoiceResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ std::vector<Call> currentCalls;
+
+ virtual ndk::ScopedAStatus acceptCallResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+ virtual ndk::ScopedAStatus cancelPendingUssdResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus conferenceResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus dialResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus emergencyDialResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus exitEmergencyCallbackModeResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus explicitCallTransferResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getCallForwardStatusResponse(
+ const RadioResponseInfo& info,
+ const std::vector<CallForwardInfo>& call_forwardInfos) override;
+
+ virtual ndk::ScopedAStatus getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+ int32_t serviceClass) override;
+
+ virtual ndk::ScopedAStatus getClipResponse(const RadioResponseInfo& info,
+ ClipStatus status) override;
+
+ virtual ndk::ScopedAStatus getClirResponse(const RadioResponseInfo& info, int32_t n,
+ int32_t m) override;
+
+ virtual ndk::ScopedAStatus getCurrentCallsResponse(const RadioResponseInfo& info,
+ const std::vector<Call>& calls) override;
+
+ virtual ndk::ScopedAStatus getLastCallFailCauseResponse(
+ const RadioResponseInfo& info, const LastCallFailCauseInfo& failCauseInfo) override;
+
+ virtual ndk::ScopedAStatus getMuteResponse(const RadioResponseInfo& info, bool enable) override;
+
+ virtual ndk::ScopedAStatus getPreferredVoicePrivacyResponse(const RadioResponseInfo& info,
+ bool enable) override;
+
+ virtual ndk::ScopedAStatus getTtyModeResponse(const RadioResponseInfo& info,
+ TtyMode mode) override;
+
+ virtual ndk::ScopedAStatus handleStkCallSetupRequestFromSimResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus hangupConnectionResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus hangupForegroundResumeBackgroundResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus hangupWaitingOrBackgroundResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus isVoNrEnabledResponse(const RadioResponseInfo& info,
+ bool enable) override;
+
+ virtual ndk::ScopedAStatus rejectCallResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendBurstDtmfResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendCdmaFeatureCodeResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendDtmfResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendUssdResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus separateConnectionResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCallForwardResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setCallWaitingResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setClirResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setMuteResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setPreferredVoicePrivacyResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setTtyModeResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setVoNrEnabledResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus startDtmfResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus stopDtmfResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus switchWaitingOrHoldingAndActiveResponse(
+ const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio voice indication */
+class RadioVoiceIndication : public BnRadioVoiceIndication {
+ protected:
+ RadioServiceTest& parent_voice;
+
+ public:
+ RadioVoiceIndication(RadioServiceTest& parent_voice);
+ virtual ~RadioVoiceIndication() = default;
+
+ virtual ndk::ScopedAStatus callRing(RadioIndicationType type, bool isGsm,
+ const CdmaSignalInfoRecord& record) override;
+
+ virtual ndk::ScopedAStatus callStateChanged(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus cdmaCallWaiting(RadioIndicationType type,
+ const CdmaCallWaiting& callWaitingRecord) override;
+
+ virtual ndk::ScopedAStatus cdmaInfoRec(
+ RadioIndicationType type, const std::vector<CdmaInformationRecord>& records) override;
+
+ virtual ndk::ScopedAStatus cdmaOtaProvisionStatus(RadioIndicationType type,
+ CdmaOtaProvisionStatus status) override;
+
+ virtual ndk::ScopedAStatus currentEmergencyNumberList(
+ RadioIndicationType type,
+ const std::vector<EmergencyNumber>& emergencyNumberList) override;
+
+ virtual ndk::ScopedAStatus enterEmergencyCallbackMode(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus exitEmergencyCallbackMode(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus indicateRingbackTone(RadioIndicationType type, bool start) override;
+
+ virtual ndk::ScopedAStatus onSupplementaryServiceIndication(
+ RadioIndicationType type, const StkCcUnsolSsResult& ss) override;
+
+ virtual ndk::ScopedAStatus onUssd(RadioIndicationType type, UssdModeType modeType,
+ const std::string& msg) override;
+
+ virtual ndk::ScopedAStatus resendIncallMute(RadioIndicationType type) override;
+
+ virtual ndk::ScopedAStatus srvccStateNotify(RadioIndicationType type,
+ SrvccState state) override;
+
+ virtual ndk::ScopedAStatus stkCallControlAlphaNotify(RadioIndicationType type,
+ const std::string& alpha) override;
+
+ virtual ndk::ScopedAStatus stkCallSetup(RadioIndicationType type, int64_t timeout) override;
+};
+
+// The main test class for Radio AIDL Voice.
+class RadioVoiceTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ protected:
+ /* Clear Potential Established Calls */
+ virtual ndk::ScopedAStatus clearPotentialEstablishedCalls();
+ std::shared_ptr<network::IRadioNetwork> radio_network;
+ std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+ std::shared_ptr<RadioNetworkIndication> radioInd_network;
+
+ public:
+ virtual void SetUp() override;
+
+ /* radio voice service handle */
+ std::shared_ptr<IRadioVoice> radio_voice;
+ /* radio voice response handle */
+ std::shared_ptr<RadioVoiceResponse> radioRsp_voice;
+ /* radio voice indication handle */
+ std::shared_ptr<RadioVoiceIndication> radioInd_voice;
+};
diff --git a/rebootescrow/aidl/default/service.cpp b/rebootescrow/aidl/default/service.cpp
index 8a8086b..dc06c71 100644
--- a/rebootescrow/aidl/default/service.cpp
+++ b/rebootescrow/aidl/default/service.cpp
@@ -34,7 +34,7 @@
auto re = ndk::SharedRefBase::make<RebootEscrow>(rebootEscrowDevicePath);
const std::string instance = std::string() + RebootEscrow::descriptor + "/default";
binder_status_t status = AServiceManager_addService(re->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE;
diff --git a/security/dice/aidl/Android.bp b/security/dice/aidl/Android.bp
new file mode 100644
index 0000000..8c31e26
--- /dev/null
+++ b/security/dice/aidl/Android.bp
@@ -0,0 +1,55 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.security.dice",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/security/dice/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ enabled: false,
+ platform_apis: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ apps_enabled: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.compos",
+ ],
+ },
+ rust: {
+ enabled: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.compos",
+ ],
+ },
+ },
+ // versions: ["1"],
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl
new file mode 100644
index 0000000..5af7358
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Bcc {
+ byte[] data;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
new file mode 100644
index 0000000..8baca94
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable BccHandover {
+ byte[32] cdiAttest;
+ byte[32] cdiSeal;
+ android.hardware.security.dice.Bcc bcc;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl
new file mode 100644
index 0000000..78dd2f8
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Config {
+ byte[] desc;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl
new file mode 100644
index 0000000..383f4d1
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@SensitiveData @VintfStability
+interface IDiceDevice {
+ android.hardware.security.dice.Signature sign(in android.hardware.security.dice.InputValues[] id, in byte[] payload);
+ android.hardware.security.dice.Bcc getAttestationChain(in android.hardware.security.dice.InputValues[] inputValues);
+ android.hardware.security.dice.BccHandover derive(in android.hardware.security.dice.InputValues[] inputValues);
+ void demote(in android.hardware.security.dice.InputValues[] inputValues);
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
new file mode 100644
index 0000000..e43c429
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable InputValues {
+ byte[64] codeHash;
+ android.hardware.security.dice.Config config;
+ byte[64] authorityHash;
+ @nullable byte[] authorityDescriptor;
+ android.hardware.security.dice.Mode mode = android.hardware.security.dice.Mode.NOT_INITIALIZED;
+ byte[64] hidden;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl
new file mode 100644
index 0000000..295c32e
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Mode {
+ NOT_INITIALIZED = 0,
+ NORMAL = 1,
+ DEBUG = 2,
+ RECOVERY = 3,
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl
new file mode 100644
index 0000000..c13afa6
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+@Backing(type="int") @VintfStability
+enum ResponseCode {
+ PERMISSION_DENIED = 1,
+ SYSTEM_ERROR = 2,
+ NOT_IMPLEMENTED = 3,
+ DEMOTION_FAILED = 4,
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl
new file mode 100644
index 0000000..294170d
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Signature {
+ byte[] data;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Bcc.aidl b/security/dice/aidl/android/hardware/security/dice/Bcc.aidl
new file mode 100644
index 0000000..983915e
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Bcc.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+/**
+ * A DICE certificate chain following the Boot Certificate Chain (BCC) specification.
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable Bcc {
+ /**
+ * The DICE certificate chain CBOR encoded following the BCC specification. The CDDL
+ * specification for BCC can be found here [1].
+ *
+ * @see <a
+ * href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+ * BCC CDDL specification
+ * </a>
+ */
+ byte[] data;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
new file mode 100644
index 0000000..6ca862c
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+import android.hardware.security.dice.Bcc;
+
+/**
+ * Represents one set of DICE artifacts.
+ *
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable BccHandover {
+ /**
+ * CDI_attest. Must be exactly 32 bytes of data.
+ */
+ byte[32] cdiAttest;
+ /**
+ * CDI_seal. Must be exactly 32 bytes of data.
+ */
+ byte[32] cdiSeal;
+ /**
+ * CBOR encoded BCC.
+ *
+ * @see <a
+ * href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+ * BCC CDDL specification
+ * </a>
+ */
+ Bcc bcc;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Config.aidl b/security/dice/aidl/android/hardware/security/dice/Config.aidl
new file mode 100644
index 0000000..6decfc5
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Config.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+/**
+ * DICE config descriptor as described in at
+ * <a
+ * href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#input-values">
+ * input-values
+ * </a>
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable Config {
+ /**
+ * A free form descriptor. This should follow the BCC Configuration Descriptor.
+ * @see <a
+ * href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+ * BccPayload field -4670548
+ * </a>
+ */
+ byte[] desc;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl b/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl
new file mode 100644
index 0000000..709aede
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+import android.hardware.security.dice.Bcc;
+import android.hardware.security.dice.BccHandover;
+import android.hardware.security.dice.InputValues;
+import android.hardware.security.dice.Signature;
+
+/**
+ * IDiceDevice specifies an interface that allows access to the Android instance's DICE artifacts.
+ *
+ * <h2>Features</h2>
+ *
+ * The dice device provides access to the component's CDI_SEAL and CDI_ATTEST secrets as well
+ * as to its attestation certificate chain. The "component" is the Android instance running this
+ * HAL service and the secrets and attestation chain must include all boot stage components,
+ * the kernel, and the verified boot information (VBA).
+ *
+ * Implementations provide the following operations:
+ * <li> sign - Signing a payload with a key derived from CDI_ATTEST.
+ * <li> getAttestationChain - Retrieve the component's attestation certificate chain.
+ * <li> derive - Retrieve the component's DICE artifacts.
+ *
+ * @see <a
+ * href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md">
+ * Open-dice Specification
+ * </a>
+ * @see <a
+ * href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl">
+ * Boot Certificate Chain (BCC) CDDL specification
+ * </a>
+ * @hide
+ */
+@SensitiveData
+@VintfStability
+interface IDiceDevice {
+ /**
+ * Uses the a key derived from the component's, or a child's given by <code>inputValues</code>,
+ * attestation secret to sign the payload using RFC 8032 Pure Ed25519 and returns the
+ * signature. The payload is limited to 1024 bytes.
+ *
+ * @see <a href="https://datatracker.ietf.org/doc/html/rfc8032">RFC 8032</a>
+ */
+ Signature sign(in InputValues[] id, in byte[] payload);
+
+ /**
+ * Returns the attestation chain of the component if <code>inputValues</code> is empty or the
+ * chain to the given child of the component identified by the <code>inputValues</code> vector.
+ *
+ * ## Error as service specific exception:
+ * ResponseCode::PERMISSION_DENIED if the caller is not sufficiently privileged.
+ */
+ Bcc getAttestationChain(in InputValues[] inputValues);
+
+ /**
+ * This function allows a client to become a resident node. A resident node is a node that
+ * manages its own dice secrets as opposed to using them by proxy, i.e., by calling sign
+ * and getAttestationChain. Called with empty <code>inputValues</code> vectors, an
+ * implementation returns the component's DICE secrets. If the <code>inputValues</code> vector
+ * is given the appropriate derivations are performed starting from the component's level.
+ *
+ * ## Error as service specific exception:
+ * ResponseCode::PERMISSION_DENIED if the implementation does not allow resident nodes
+ * at the client's level.
+ */
+ BccHandover derive(in InputValues[] inputValues);
+
+ /**
+ * This demotes the implementation of this interface.
+ * When called, the implementation performs appropriate derivation steps using
+ * <code>inputValues</code>, traversing the vector in ascending order. Then it replaces its
+ * stored DICE artifacts with the newly derived ones.
+ *
+ * IMPORTANT: When the function returns, all remnants of the previous DICE artifacts must
+ * have been purged from memory.
+ *
+ * This operation is not reversible until the next reboot. Further demotion is always
+ * possible.
+ *
+ * ## Error as service specific exception:
+ * ResponseCode::DEMOTION_FAILED if the implementation failed to demote itself
+ * or was unable to purge previous DICE artifacts from memory.
+ */
+ void demote(in InputValues[] inputValues);
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
new file mode 100644
index 0000000..711d523
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+import android.hardware.security.dice.Config;
+import android.hardware.security.dice.Mode;
+
+/**
+ * DICE input values for certificate and CDI generation.
+ *
+ * @see <a
+ * href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#input-values">
+ * Open-dice input-values
+ * </a>
+ * @hide
+ */
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+@VintfStability
+parcelable InputValues {
+ /**
+ * The target code hash. Must be exactly 64 bytes.
+ */
+ byte[64] codeHash;
+ /**
+ * The configuration data.
+ */
+ Config config;
+ /**
+ * The authority hash. Must be exactly 64 bytes. Must be all zero if unused.
+ */
+ byte[64] authorityHash;
+ /**
+ * Optional free form authorityDescriptor.
+ */
+ @nullable byte[] authorityDescriptor;
+ /**
+ * The mode of operation. Normal, Debug, Maintenance, or not initialized.
+ */
+ Mode mode = Mode.NOT_INITIALIZED;
+ /**
+ * Optional hidden values. Must be exactly 64 bytes. Must be all zero if unused.
+ */
+ byte[64] hidden;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Mode.aidl b/security/dice/aidl/android/hardware/security/dice/Mode.aidl
new file mode 100644
index 0000000..3b3bfdc
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Mode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+/**
+ * DICE mode values as defined at
+ *
+ * @see <a
+ * href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#mode-value-details">
+ * open-dice mode-value-details
+ * </a>
+ * @hide
+ */
+@Backing(type="int")
+@VintfStability
+enum Mode {
+ NOT_INITIALIZED = 0,
+ NORMAL = 1,
+ DEBUG = 2,
+ /**
+ * The recovery mode is also referred to as "maintenance" mode.
+ */
+ RECOVERY = 3,
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/ResponseCode.aidl b/security/dice/aidl/android/hardware/security/dice/ResponseCode.aidl
new file mode 100644
index 0000000..3e77cf7
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/ResponseCode.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.security.dice;
+
+@Backing(type="int")
+/**
+ * These response codes are used as service specific exception codes by
+ * IDiceDevice.
+ * @hide
+ */
+@VintfStability
+enum ResponseCode {
+ /**
+ * The caller has insufficient privilege to access the DICE API.
+ */
+ PERMISSION_DENIED = 1,
+ /**
+ * An unexpected error occurred, likely with IO or IPC.
+ */
+ SYSTEM_ERROR = 2,
+ /**
+ * Returned if the called function is not implemented.
+ */
+ NOT_IMPLEMENTED = 3,
+ /**
+ * An attempt to demote the implementation failed.
+ */
+ DEMOTION_FAILED = 4,
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Signature.aidl b/security/dice/aidl/android/hardware/security/dice/Signature.aidl
new file mode 100644
index 0000000..ea3594f
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Signature.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.dice;
+
+/**
+ * This parcelable represents a Signature. It is used as return value of IDiceNode::sign.
+ *
+ * @hide
+ */
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+@VintfStability
+parcelable Signature {
+ /**
+ * The RFC 8032 PureEd25519 signature.
+ * @see <a href="https://datatracker.ietf.org/doc/html/rfc8032">RFC 8032</a>
+ */
+ byte[] data;
+}
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 3cf6ff2..c9ee1b3 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -20,7 +20,6 @@
backend: {
java: {
platform_apis: true,
- srcs_available: true,
},
ndk: {
vndk: {
@@ -45,14 +44,21 @@
cc_defaults {
name: "keymint_use_latest_hal_aidl_ndk_static",
static_libs: [
- "android.hardware.security.keymint-V1-ndk",
+ "android.hardware.security.keymint-V2-ndk",
],
}
cc_defaults {
name: "keymint_use_latest_hal_aidl_ndk_shared",
shared_libs: [
- "android.hardware.security.keymint-V1-ndk",
+ "android.hardware.security.keymint-V2-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "keymint_use_latest_hal_aidl_cpp_static",
+ static_libs: [
+ "android.hardware.security.keymint-V2-cpp",
],
}
@@ -62,6 +68,6 @@
rust_defaults {
name: "keymint_use_latest_hal_aidl_rust",
rustlibs: [
- "android.hardware.security.keymint-V1-rust",
+ "android.hardware.security.keymint-V2-rust",
],
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
index 6b4a9ae..ffc7efe 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
@@ -39,4 +39,5 @@
P_256 = 1,
P_384 = 2,
P_521 = 3,
+ CURVE_25519 = 4,
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index fa643fc..dcc22c4 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -49,5 +49,8 @@
void earlyBootEnded();
byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
android.hardware.security.keymint.KeyCharacteristics[] getKeyCharacteristics(in byte[] keyBlob, in byte[] appId, in byte[] appData);
+ byte[16] getRootOfTrustChallenge();
+ byte[] getRootOfTrust(in byte[16] challenge);
+ void sendRootOfTrust(in byte[] rootOfTrust);
const int AUTH_TOKEN_MAC_LENGTH = 32;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
index 06bce19..5ff45f8 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -38,6 +38,7 @@
int versionNumber;
@utf8InCpp String rpcAuthorName;
int supportedEekCurve = 0;
+ @nullable @utf8InCpp String uniqueId;
const int CURVE_NONE = 0;
const int CURVE_P256 = 1;
const int CURVE_25519 = 2;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index b0761bf..abb2a7b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -27,29 +27,29 @@
@VintfStability
parcelable DeviceInfo {
/**
- * DeviceInfo is a CBOR Map structure described by the following CDDL.
+ * DeviceInfo is a CBOR Map structure described by the following CDDL. DeviceInfo must be
+ * canonicalized according to the specification in RFC 7049. The ordering presented here is
+ * non-canonical to group similar entries semantically.
*
* DeviceInfo = {
- * ? "brand" : tstr,
- * ? "manufacturer" : tstr,
- * ? "product" : tstr,
- * ? "model" : tstr,
- * ? "board" : tstr,
- * ? "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values
- * ? "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values
- * ? "vbmeta_digest": bstr, // Taken from the AVB values
- * ? "os_version" : tstr, // Same as android.os.Build.VERSION.release
- * ? "system_patch_level" : uint, // YYYYMMDD
- * ? "boot_patch_level" : uint, // YYYYMMDD
- * ? "vendor_patch_level" : uint, // YYYYMMDD
- * "version" : 1, // The CDDL schema version.
- * "security_level" : "tee" / "strongbox"
- * "att_id_state": "locked" / "open", // Attestation IDs State. If "locked", this
- * // indicates a device's attestable IDs are
- * // factory-locked and immutable. If "open",
- * // this indicates the device is still in a
- * // provisionable state and the attestable IDs
- * // are not yet frozen.
+ * "brand" : tstr,
+ * "manufacturer" : tstr,
+ * "product" : tstr,
+ * "model" : tstr,
+ * "device" : tstr,
+ * "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values
+ * "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values
+ * "vbmeta_digest": bstr, // Taken from the AVB values
+ * ? "os_version" : tstr, // Same as
+ * // android.os.Build.VERSION.release
+ * // Not optional for TEE.
+ * "system_patch_level" : uint, // YYYYMMDD
+ * "boot_patch_level" : uint, // YYYYMMDD
+ * "vendor_patch_level" : uint, // YYYYMMDD
+ * "version" : 2, // The CDDL schema version.
+ * "security_level" : "tee" / "strongbox",
+ * "fused": 1 / 0, // 1 if secure boot is enforced for the processor that the IRPC
+ * // implementation is contained in. 0 otherwise.
* }
*/
byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
index 5b1c10c..e9f81d8 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
@@ -27,4 +27,5 @@
P_256 = 1,
P_384 = 2,
P_521 = 3,
+ CURVE_25519 = 4,
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index cd8cfc5..da02d54 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -93,6 +93,13 @@
* 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.
+ * - TRUSTED_ENVRIONMENT IKeyMintDevices must support curve 25519 for Purpose::SIGN (Ed25519,
+ * as specified in RFC 8032), Purpose::ATTEST_KEY (Ed25519) or for KeyPurpose::AGREE_KEY
+ * (X25519, as specified in RFC 7748). However, a key must have exactly one of these
+ * purpose values; the same key cannot be used for multiple purposes. Signing operations
+ * (Purpose::SIGN) have a message size limit of 16 KiB; operations on messages longer than
+ * this limit must fail with ErrorCode::INVALID_INPUT_LENGTH.
+ * STRONGBOX IKeyMintDevices do not support curve 25519.
*
* o AES
*
@@ -287,7 +294,7 @@
* 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 implementations must support all Digest values (see digest.aidl) for RSA
+ * IKeyMintDevice implementations 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
@@ -298,13 +305,24 @@
* == ECDSA Keys ==
*
* Tag::EC_CURVE must be provided to generate an ECDSA key. If it is not provided, generateKey
- * must return ErrorCode::UNSUPPORTED_KEY_SIZE. TEE IKeyMintDevice implementations must support
- * all curves. StrongBox implementations must support P_256.
-
+ * must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE. TEE
+ * IKeyMintDevice implementations must support all required curves. StrongBox implementations
+ * must support P_256 and no other curves.
+ *
* Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER must be provided to specify the
* valid date range for the returned X.509 certificate holding the public key. If omitted,
* generateKey must return ErrorCode::MISSING_NOT_BEFORE or ErrorCode::MISSING_NOT_AFTER.
*
+ * Keys with EC_CURVE of EcCurve::CURVE_25519 must have exactly one purpose in the set
+ * {KeyPurpose::SIGN, KeyPurpose::ATTEST_KEY, KeyPurpose::AGREE_KEY}. Key generation with more
+ * than one purpose should be rejected with ErrorCode::INCOMPATIBLE_PURPOSE.
+ * StrongBox implementation do not support CURVE_25519.
+ *
+ * Tag::DIGEST specifies digest algorithms that may be used with the new key. TEE
+ * IKeyMintDevice implementations must support all Digest values (see Digest.aidl) for ECDSA
+ * keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice implementations must
+ * support SHA_2_256.
+ *
* == AES Keys ==
*
* Only Tag::KEY_SIZE is required to generate an AES key. If omitted, generateKey must return
@@ -833,4 +851,82 @@
*/
KeyCharacteristics[] getKeyCharacteristics(
in byte[] keyBlob, in byte[] appId, in byte[] appData);
+
+ /**
+ * Returns a 16-byte random challenge nonce, used to prove freshness when exchanging root of
+ * trust data.
+ *
+ * This method may only be implemented by StrongBox KeyMint. TEE KeyMint implementations must
+ * return ErrorCode::UNIMPLEMENTED. StrongBox KeyMint implementations MAY return UNIMPLEMENTED,
+ * to indicate that they have an alternative mechanism for getting the data. If the StrongBox
+ * implementation returns UNIMPLEMENTED, the client should not call `getRootofTrust()` or
+ * `sendRootOfTrust()`.
+ */
+ byte[16] getRootOfTrustChallenge();
+
+ /**
+ * Returns the TEE KeyMint Root of Trust data.
+ *
+ * This method is required for TEE KeyMint. StrongBox KeyMint implementations MUST return
+ * ErrorCode::UNIMPLEMENTED.
+ *
+ * The returned data is an encoded COSE_Mac0 structure, denoted MacedRootOfTrust in the
+ * following CDDL schema. Note that K_mac is the shared HMAC key used for auth tokens, etc.:
+ *
+ * MacedRootOfTrust = [ ; COSE_Mac0 (untagged)
+ * protected: bstr .cbor {
+ * 1 : 5, ; Algorithm : HMAC-256
+ * },
+ * unprotected : {},
+ * payload : bstr .cbor RootOfTrust,
+ * tag : bstr HMAC-256(K_mac, MAC_structure)
+ * ]
+ *
+ * MAC_structure = [
+ * context : "MAC0",
+ * protected : bstr .cbor {
+ * 1 : 5, ; Algorithm : HMAC-256
+ * },
+ * external_aad : bstr .size 16 ; Value of challenge argument
+ * payload : bstr .cbor RootOfTrust,
+ * ]
+ *
+ * RootOfTrust = [
+ * verifiedBootKey : bstr .size 32,
+ * deviceLocked : bool,
+ * verifiedBootState : &VerifiedBootState,
+ * verifiedBootHash : bstr .size 32,
+ * bootPatchLevel : int, ; See Tag::BOOT_PATCHLEVEL
+ * ]
+ *
+ * VerifiedBootState = (
+ * Verified : 0,
+ * SelfSigned : 1,
+ * Unverified : 2,
+ * Failed : 3
+ * )
+ */
+ byte[] getRootOfTrust(in byte[16] challenge);
+
+ /**
+ * Delivers the TEE KeyMint Root of Trust data to StrongBox KeyMint. See `getRootOfTrust()`
+ * above for specification of the data format and cryptographic security structure.
+ *
+ * The implementation must verify the MAC on the RootOfTrust data. If it is valid, and if this
+ * is the first time since reboot that StrongBox KeyMint has received this data, it must store
+ * the RoT data for use in key attestation requests, then return ErrorCode::ERROR_OK.
+ *
+ * If the MAC on the Root of Trust data and challenge is incorrect, the implementation must
+ * return ErrorCode::VERIFICATION_FAILED.
+ *
+ * If the RootOfTrust data has already been received since the last boot, the implementation
+ * must validate the data and return ErrorCode::VERIFICATION_FAILED or ErrorCode::ERROR_OK
+ * according to the result, but must not store the data for use in key attestation requests,
+ * even if verification succeeds. On success, the challenge is invalidated and a new challenge
+ * must be requested before the RootOfTrust data may be sent again.
+ *
+ * This method is optional for StrongBox KeyMint, which MUST return ErrorCode::UNIMPLEMENTED if
+ * not implemented. TEE KeyMint implementations must return ErrorCode::UNIMPLEMENTED.
+ */
+ void sendRootOfTrust(in byte[] rootOfTrust);
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index ce83044..ca89555 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -227,7 +227,8 @@
* 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 params
* 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.
+ * generation function and the digest specified with Tag:DIGEST in params on begin() must also
+ * be used as the MGF1 digest algorithm.
*
* -- ECDSA keys --
*
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index fd6bf65..16bbc5c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -122,9 +122,9 @@
* straightforward translation of the KeyMint tag/value parameter lists to ASN.1.
*
* KeyDescription ::= SEQUENCE {
- * attestationVersion INTEGER, # Value 100
+ * attestationVersion INTEGER, # Value 200
* attestationSecurityLevel SecurityLevel, # See below
- * keyMintVersion INTEGER, # Value 100
+ * keyMintVersion INTEGER, # Value 200
* keymintSecurityLevel SecurityLevel, # See below
* attestationChallenge OCTET_STRING, # Tag::ATTESTATION_CHALLENGE from attestParams
* uniqueId OCTET_STRING, # Empty unless key has Tag::INCLUDE_UNIQUE_ID
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
index da3d521..3faef38 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
@@ -25,8 +25,10 @@
enum KeyFormat {
/** X.509 certificate format, for public key export. */
X509 = 0,
- /** PCKS#8 format, asymmetric key pair import. */
+ /** PKCS#8 format, asymmetric key pair import. */
PKCS8 = 1,
- /** Raw bytes, for symmetric key import. */
+ /**
+ * Raw bytes, for symmetric key import, and for import of raw asymmetric keys for curve 25519.
+ */
RAW = 3,
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
index e141e55..fd103ef 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
@@ -44,6 +44,10 @@
AGREE_KEY = 6,
/* Usable as an attestation signing key. Keys with this purpose must not have any other
- * purpose. */
+ * purpose; if they do, key generation/import must be rejected with
+ * ErrorCode::INCOMPATIBLE_PURPOSE. (Rationale: If key also included KeyPurpose::SIGN, then
+ * it could be used to sign arbitrary data, including any tbsCertificate, and so an
+ * attestation produced by the key would have no security properties.)
+ */
ATTEST_KEY = 7,
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index 62a48e9..ad97443 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -37,10 +37,10 @@
*
* PublicKey = { // COSE_Key
* 1 : 2, // Key type : EC2
- * 3 : -8 // Algorithm : ES256
- * -1 : 6, // Curve : P256
- * -2 : bstr // X coordinate, little-endian
- * -3 : bstr // Y coordinate, little-endian
+ * 3 : -7, // Algorithm : ES256
+ * -1 : 1, // Curve : P256
+ * -2 : bstr, // X coordinate, little-endian
+ * -3 : bstr, // Y coordinate, little-endian
* ? -70000 : nil // Presence indicates this is a test key. If set, K_mac is
* // all zeros.
* },
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 24cdbc1..a14fc88 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -169,7 +169,6 @@
* PubKeyEd25519 = { // COSE_Key
* 1 : 1, // Key type : octet key pair
* 3 : AlgorithmEdDSA, // Algorithm : EdDSA
- * 4 : 2, // Ops: Verify
* -1 : 6, // Curve : Ed25519
* -2 : bstr // X coordinate, little-endian
* }
@@ -184,7 +183,6 @@
* PubKeyECDSA256 = { // COSE_Key
* 1 : 2, // Key type : EC2
* 3 : AlgorithmES256, // Algorithm : ECDSA w/ SHA-256
- * 4 : 2, // Ops: Verify
* -1 : 1, // Curve: P256
* -2 : bstr, // X coordinate
* -3 : bstr // Y coordinate
diff --git a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
index d297f87..3a4c233 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -53,4 +53,21 @@
* a passing implementation does not provide CURVE_NONE.
*/
int supportedEekCurve = CURVE_NONE;
+
+ /**
+ * uniqueId is an opaque identifier for this IRemotelyProvisionedComponent implementation. The
+ * client should NOT interpret the content of the identifier in any way. The client can only
+ * compare identifiers to determine if two IRemotelyProvisionedComponents share the same
+ * implementation. Each IRemotelyProvisionedComponent implementation must have a distinct
+ * identifier from all other implementations on the same device.
+ *
+ * This identifier must be consistent across reboots, as it is used to store and track
+ * provisioned keys in a persistent, on-device database.
+ *
+ * uniqueId may not be empty, and must not be any longer than 32 characters.
+ *
+ * This field was added in API version 2.
+ *
+ */
+ @nullable @utf8InCpp String uniqueId;
}
diff --git a/security/keymint/aidl/default/TEST_MAPPING b/security/keymint/aidl/default/TEST_MAPPING
new file mode 100644
index 0000000..2400ccd
--- /dev/null
+++ b/security/keymint/aidl/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit" : [
+ {
+ "name" : "vts_treble_vintf_framework_test"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index 4aa05ef..a4d0302 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,10 +1,12 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.security.keymint</name>
+ <version>2</version>
<fqname>IKeyMintDevice/default</fqname>
</hal>
<hal format="aidl">
<name>android.hardware.security.keymint</name>
+ <version>2</version>
<fqname>IRemotelyProvisionedComponent/default</fqname>
</hal>
</manifest>
diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp
index 8092e34..dc0c618 100644
--- a/security/keymint/aidl/default/service.cpp
+++ b/security/keymint/aidl/default/service.cpp
@@ -39,7 +39,7 @@
LOG(INFO) << "adding keymint service instance: " << instanceName;
binder_status_t status =
AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
return ser;
}
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 2d2d701..ef5b0bd 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -50,10 +50,14 @@
defaults: [
"keymint_vts_defaults",
],
+ tidy_timeout_srcs: [
+ "KeyMintTest.cpp",
+ ],
srcs: [
"AttestKeyTest.cpp",
"DeviceUniqueAttestationTest.cpp",
"KeyMintTest.cpp",
+ "SecureElementProvisioningTest.cpp",
],
static_libs: [
"libkeymint_vts_test_utils",
@@ -69,12 +73,18 @@
defaults: [
"keymint_vts_defaults",
],
+ tidy_timeout_srcs: [
+ "KeyMintAidlTestBase.cpp",
+ ],
srcs: [
"KeyMintAidlTestBase.cpp",
],
export_include_dirs: [
".",
],
+ export_static_lib_headers: [
+ "libkeymint_support",
+ ],
static_libs: [
"libgmock_ndk",
],
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 64550ef..8a26b3c 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -81,7 +81,8 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -113,7 +114,8 @@
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo2", "bar2", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
+ hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -154,12 +156,13 @@
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
// The client-specified CREATION_DATETIME should be in sw_enforced.
- // Its presence will also trigger verify_attestation_record() to check that it
- // is in the attestation extension with a matching value.
+ // Its presence will also trigger verify_attestation_record() to check that
+ // it is in the attestation extension with a matching value.
EXPECT_TRUE(sw_enforced.Contains(TAG_CREATION_DATETIME, timestamp))
<< "expected CREATION_TIMESTAMP in sw_enforced:" << sw_enforced
<< " not in hw_enforced:" << hw_enforced;
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -175,6 +178,24 @@
}
/*
+ * AttestKeyTest.RsaAttestKeyMultiPurposeFail
+ *
+ * This test attempts to create an RSA attestation key that also allows signing.
+ */
+TEST_P(AttestKeyTest, RsaAttestKeyMultiPurposeFail) {
+ vector<uint8_t> attest_key_blob;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key_blob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+}
+
+/*
* AttestKeyTest.RsaAttestedAttestKeys
*
* This test creates an RSA attestation key signed by factory keys, and varifies it can be
@@ -198,18 +219,22 @@
AttestationKey attest_key;
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- {} /* attestation signing key */, &attest_key.keyBlob,
- &attest_key_characteristics, &attest_key_cert_chain));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
EXPECT_GT(attest_key_cert_chain.size(), 1);
verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -217,7 +242,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attest_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attest_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
attest_key_cert_chain[0].encodedCertificate));
@@ -252,7 +277,8 @@
AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced2, hw_enforced2, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
+ SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -297,23 +323,28 @@
attest_key_opt = attest_key;
}
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
cert_chain_list[i][0].encodedCertificate));
if (i > 0) {
@@ -369,23 +400,28 @@
attest_key_opt = attest_key;
}
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaKey(EcCurve::P_256)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
cert_chain_list[i][0].encodedCertificate));
if (i > 0) {
@@ -412,6 +448,24 @@
}
/*
+ * AttestKeyTest.EcAttestKeyMultiPurposeFail
+ *
+ * This test attempts to create an EC attestation key that also allows signing.
+ */
+TEST_P(AttestKeyTest, EcAttestKeyMultiPurposeFail) {
+ vector<uint8_t> attest_key_blob;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key_blob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+}
+
+/*
* AttestKeyTest.AlternateAttestKeyChaining
*
* This test creates a chain of multiple attest keys, in the order Ec - RSA - Ec - RSA ....
@@ -442,39 +496,43 @@
attest_key.keyBlob = key_blob_list[i - 1];
attest_key_opt = attest_key;
}
-
+ ErrorCode result;
if ((i & 0x1) == 1) {
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaKey(EcCurve::P_256)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
} else {
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
}
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
cert_chain_list[i][0].encodedCertificate));
if (i > 0) {
@@ -583,11 +641,13 @@
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
CheckedDeleteKey(&attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -612,12 +672,14 @@
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
CheckedDeleteKey(&attested_key_blob);
CheckedDeleteKey(&attest_key.keyBlob);
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
// Attestation by itself is not valid (last entry is not self-signed).
@@ -722,8 +784,8 @@
// attestation extension should contain them, so make sure the extra tag is added.
hw_enforced.push_back(tag);
- EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
- SecLevel(),
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
}
CheckedDeleteKey(&attest_key.keyBlob);
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index 3cbffbf..1dc5df3 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -52,8 +52,9 @@
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_, /* strict_issuer_check= */ false));
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
- SecLevel(), cert_chain_[0].encodedCertificate));
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
}
};
@@ -79,6 +80,7 @@
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -108,6 +110,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -138,6 +141,7 @@
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -196,6 +200,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -263,6 +268,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
@@ -335,6 +341,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .SetDefaultValidity()
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 6140df1..c17a0b8 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -25,6 +25,7 @@
#include <cppbor_parse.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
+#include <openssl/evp.h>
#include <openssl/mem.h>
#include <remote_prov/remote_prov_utils.h>
@@ -127,6 +128,16 @@
return attest_rec;
}
+void check_attestation_version(uint32_t attestation_version, int32_t aidl_version) {
+ // Version numbers in attestation extensions should be a multiple of 100.
+ EXPECT_EQ(attestation_version % 100, 0);
+
+ // The multiplier should never be higher than the AIDL version, but can be less
+ // (for example, if the implementation is from an earlier version but the HAL service
+ // uses the default libraries and so reports the current AIDL version).
+ EXPECT_TRUE((attestation_version / 100) <= aidl_version);
+}
+
bool avb_verification_enabled() {
char value[PROPERTY_VALUE_MAX];
return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
@@ -196,6 +207,21 @@
return boot_patch_level(key_characteristics_);
}
+bool KeyMintAidlTestBase::Curve25519Supported() {
+ // Strongbox never supports curve 25519.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ return false;
+ }
+
+ // Curve 25519 was included in version 2 of the KeyMint interface.
+ int32_t version = 0;
+ auto status = keymint_->getInterfaceVersion(&version);
+ if (!status.isOk()) {
+ ADD_FAILURE() << "Failed to determine interface version";
+ }
+ return version >= 2;
+}
+
ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
if (result.isOk()) return ErrorCode::OK;
@@ -223,6 +249,15 @@
vendor_patch_level_ = getVendorPatchlevel();
}
+int32_t KeyMintAidlTestBase::AidlVersion() {
+ int32_t version = 0;
+ auto status = keymint_->getInterfaceVersion(&version);
+ if (!status.isOk()) {
+ ADD_FAILURE() << "Failed to determine interface version";
+ }
+ return version;
+}
+
void KeyMintAidlTestBase::SetUp() {
if (AServiceManager_isDeclared(GetParam().c_str())) {
::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
@@ -518,10 +553,18 @@
Status result;
if (!output) return ErrorCode::UNEXPECTED_NULL_POINTER;
+ EXPECT_NE(op_, nullptr);
+ if (!op_) return ErrorCode::UNEXPECTED_NULL_POINTER;
+
std::vector<uint8_t> o_put;
result = op_->update(vector<uint8_t>(input.begin(), input.end()), {}, {}, &o_put);
- if (result.isOk()) output->append(o_put.begin(), o_put.end());
+ if (result.isOk()) {
+ output->append(o_put.begin(), o_put.end());
+ } else {
+ // Failure always terminates the operation.
+ op_ = {};
+ }
return GetReturnErrorCode(result);
}
@@ -622,6 +665,78 @@
AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
}
+void KeyMintAidlTestBase::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+ int message_size) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .BlockMode(block_mode)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ for (int increment = 1; increment <= message_size; ++increment) {
+ string message(message_size, 'a');
+ auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
+ if (block_mode == BlockMode::GCM) {
+ params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+ }
+
+ AuthorizationSet output_params;
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+ string ciphertext;
+ string to_send;
+ for (size_t i = 0; i < message.size(); i += increment) {
+ EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
+ }
+ EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
+ << "Error sending " << to_send << " with block mode " << block_mode;
+
+ 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) << "No IV for block mode " << block_mode;
+ EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+ params.push_back(TAG_NONCE, iv->get());
+ break;
+
+ case BlockMode::ECB:
+ EXPECT_FALSE(iv) << "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) {
+ EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
+ }
+ 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;
+ }
+ }
+}
+
void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
Digest digest, const string& expected_mac) {
SCOPED_TRACE("CheckHmacTestVector");
@@ -718,6 +833,19 @@
if (digest == Digest::NONE) {
switch (EVP_PKEY_id(pub_key.get())) {
+ case EVP_PKEY_ED25519: {
+ ASSERT_EQ(64, signature.size());
+ uint8_t pub_keydata[32];
+ size_t pub_len = sizeof(pub_keydata);
+ ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(pub_key.get(), pub_keydata, &pub_len));
+ ASSERT_EQ(sizeof(pub_keydata), pub_len);
+ ASSERT_EQ(1, ED25519_verify(reinterpret_cast<const uint8_t*>(message.data()),
+ message.size(),
+ reinterpret_cast<const uint8_t*>(signature.data()),
+ pub_keydata));
+ break;
+ }
+
case EVP_PKEY_EC: {
vector<uint8_t> data((EVP_PKEY_bits(pub_key.get()) + 7) / 8);
size_t data_size = std::min(data.size(), message.size());
@@ -790,6 +918,7 @@
if (padding == 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);
+ EXPECT_GT(EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, md), 0);
}
ASSERT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx,
@@ -1143,16 +1272,39 @@
vector<EcCurve> KeyMintAidlTestBase::ValidCurves() {
if (securityLevel_ == SecurityLevel::STRONGBOX) {
return {EcCurve::P_256};
+ } else if (Curve25519Supported()) {
+ return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521,
+ EcCurve::CURVE_25519};
} else {
- return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+ return {
+ EcCurve::P_224,
+ EcCurve::P_256,
+ EcCurve::P_384,
+ EcCurve::P_521,
+ };
}
}
vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
if (SecLevel() == SecurityLevel::STRONGBOX) {
- return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+ // Curve 25519 is not supported, either because:
+ // - KeyMint v1: it's an unknown enum value
+ // - KeyMint v2+: it's not supported by StrongBox.
+ return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521, EcCurve::CURVE_25519};
} else {
- return {};
+ if (Curve25519Supported()) {
+ return {};
+ } else {
+ return {EcCurve::CURVE_25519};
+ }
+ }
+}
+
+vector<uint64_t> KeyMintAidlTestBase::ValidExponents() {
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ return {65537};
+ } else {
+ return {3, 65537};
}
}
@@ -1304,7 +1456,8 @@
verify_subject(cert.get(), subject, self_signed);
}
-bool verify_attestation_record(const string& challenge, //
+bool verify_attestation_record(int32_t aidl_version, //
+ const string& challenge, //
const string& app_id, //
AuthorizationSet expected_sw_enforced, //
AuthorizationSet expected_hw_enforced, //
@@ -1342,7 +1495,7 @@
EXPECT_EQ(ErrorCode::OK, error);
if (error != ErrorCode::OK) return false;
- EXPECT_EQ(att_attestation_version, 100U);
+ check_attestation_version(att_attestation_version, aidl_version);
vector<uint8_t> appId(app_id.begin(), app_id.end());
// check challenge and app id only if we expects a non-fake certificate
@@ -1353,7 +1506,7 @@
expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
}
- EXPECT_EQ(att_keymint_version, 100U);
+ check_attestation_version(att_keymint_version, aidl_version);
EXPECT_EQ(security_level, att_keymint_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 7b3b9d4..e59443c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -73,12 +73,15 @@
void InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint);
IKeyMintDevice& keyMint() { return *keymint_; }
+ int32_t AidlVersion();
uint32_t os_version() { return os_version_; }
uint32_t os_patch_level() { return os_patch_level_; }
uint32_t vendor_patch_level() { return vendor_patch_level_; }
uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
uint32_t boot_patch_level();
+ bool Curve25519Supported();
+
ErrorCode GetReturnErrorCode(const Status& result);
ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
@@ -166,6 +169,8 @@
string MacMessage(const string& message, Digest digest, size_t mac_length);
+ void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
void CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac);
@@ -250,7 +255,10 @@
.SetDefaultValidity();
tagModifier(&rsaBuilder);
errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
- EXPECT_EQ(expectedReturn, errorCode);
+ if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+ ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+ EXPECT_EQ(expectedReturn, errorCode);
+ }
/* ECDSA */
KeyData ecdsaKeyData;
@@ -262,7 +270,10 @@
.SetDefaultValidity();
tagModifier(&ecdsaBuilder);
errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
- EXPECT_EQ(expectedReturn, errorCode);
+ if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+ ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+ EXPECT_EQ(expectedReturn, errorCode);
+ }
return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
}
bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; }
@@ -279,6 +290,7 @@
vector<EcCurve> InvalidCurves();
vector<Digest> ValidDigests(bool withNone, bool withMD5);
+ vector<uint64_t> ValidExponents();
static vector<string> build_params() {
auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
@@ -333,7 +345,8 @@
const uint64_t expected_serial, //
const string& subject, bool self_signed);
-bool verify_attestation_record(const string& challenge, //
+bool verify_attestation_record(int aidl_version, //
+ const string& challenge, //
const string& app_id, //
AuthorizationSet expected_sw_enforced, //
AuthorizationSet expected_hw_enforced, //
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 2a7911c..c734c37 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -22,6 +22,7 @@
#include <algorithm>
#include <iostream>
+#include <openssl/curve25519.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
@@ -69,6 +70,9 @@
namespace {
+// Maximum supported Ed25519 message size.
+const size_t MAX_ED25519_MSG_SIZE = 16 * 1024;
+
// Whether to check that BOOT_PATCHLEVEL is populated.
bool check_boot_pl = true;
@@ -415,6 +419,126 @@
// } end SEQUENCE (PrivateKeyInfo)
);
+/**
+ * Ed25519 key pair generated as follows:
+ * ```
+ * % openssl req -x509 -newkey ED25519 -days 700 -nodes \
+ * -keyout ed25519_priv.key -out ed25519.pem * -subj "/CN=fake.ed25519.com"
+ * Generating a ED25519 private key writing new private key to
+ * 'ed25519_priv.key'
+ * -----
+ * % cat ed25519_priv.key
+ * -----BEGIN PRIVATE KEY-----
+ * MC4CAQAwBQYDK2VwBCIEIKl3A5quNywcj1P+0XI9SBalFPIvO52NxceMLRH6dVmR
+ * -----END PRIVATE KEY-----
+ * % der2ascii -pem -i ed25519_priv.key
+ * SEQUENCE {
+ * INTEGER { 0 }
+ * SEQUENCE {
+ * # ed25519
+ * OBJECT_IDENTIFIER { 1.3.101.112 }
+ * }
+ * OCTET_STRING {
+ * OCTET_STRING { `a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991` }
+ * }
+ * }
+ * % cat ed25519.pem
+ * -----BEGIN CERTIFICATE-----
+ * MIIBSjCB/aADAgECAhR0Jron3eKcdgqyecv/eEfGWAzn8DAFBgMrZXAwGzEZMBcG
+ * A1UEAwwQZmFrZS5lZDI1NTE5LmNvbTAeFw0yMTEwMjAwODI3NDJaFw0yMzA5MjAw
+ * ODI3NDJaMBsxGTAXBgNVBAMMEGZha2UuZWQyNTUxOS5jb20wKjAFBgMrZXADIQDv
+ * uwHz+3TaQ69D2digxlz0fFfsZg0rPqgQae3jBPRWkaNTMFEwHQYDVR0OBBYEFN9O
+ * od30SY4JTs66ZR403UPya+iXMB8GA1UdIwQYMBaAFN9Ood30SY4JTs66ZR403UPy
+ * a+iXMA8GA1UdEwEB/wQFMAMBAf8wBQYDK2VwA0EAKjVrYQjuE/gEL2j/ABpDbFjV
+ * Ilg5tJ6MN/P3psAv3Cs7f0X1lFqdlt15nJ/6aj2cmGCwNRXt5wcyYDKNu+v2Dw==
+ * -----END CERTIFICATE-----
+ * % openssl x509 -in ed25519.pem -text -noout
+ * Certificate:
+ * Data:
+ * Version: 3 (0x2)
+ * Serial Number:
+ * 74:26:ba:27:dd:e2:9c:76:0a:b2:79:cb:ff:78:47:c6:58:0c:e7:f0
+ * Signature Algorithm: ED25519
+ * Issuer: CN = fake.ed25519.com
+ * Validity
+ * Not Before: Oct 20 08:27:42 2021 GMT
+ * Not After : Sep 20 08:27:42 2023 GMT
+ * Subject: CN = fake.ed25519.com
+ * Subject Public Key Info:
+ * Public Key Algorithm: ED25519
+ * ED25519 Public-Key:
+ * pub:
+ * ef:bb:01:f3:fb:74:da:43:af:43:d9:d8:a0:c6:5c:
+ * f4:7c:57:ec:66:0d:2b:3e:a8:10:69:ed:e3:04:f4:
+ * 56:91
+ * X509v3 extensions:
+ * X509v3 Subject Key Identifier:
+ * DF:4E:A1:DD:F4:49:8E:09:4E:CE:BA:65:1E:34:DD:43:F2:6B:E8:97
+ * X509v3 Authority Key Identifier:
+ * keyid:DF:4E:A1:DD:F4:49:8E:09:4E:CE:BA:65:1E:34:DD:43:F2:6B:E8:97
+ *
+ * X509v3 Basic Constraints: critical
+ * CA:TRUE
+ * Signature Algorithm: ED25519
+ * 2a:35:6b:61:08:ee:13:f8:04:2f:68:ff:00:1a:43:6c:58:d5:
+ * 22:58:39:b4:9e:8c:37:f3:f7:a6:c0:2f:dc:2b:3b:7f:45:f5:
+ * 94:5a:9d:96:dd:79:9c:9f:fa:6a:3d:9c:98:60:b0:35:15:ed:
+ * e7:07:32:60:32:8d:bb:eb:f6:0f
+ * ```
+ */
+string ed25519_key = hex2str("a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991");
+string ed25519_pkcs8_key = hex2str(
+ // RFC 5208 s5
+ "302e" // SEQUENCE length 0x2e (PrivateKeyInfo) {
+ "0201" // INTEGER length 1 (Version)
+ "00" // version 0
+ "3005" // SEQUENCE length 05 (AlgorithmIdentifier) {
+ "0603" // OBJECT IDENTIFIER length 3 (algorithm)
+ "2b6570" // 1.3.101.112 (id-Ed125519 RFC 8410 s3)
+ // } end SEQUENCE (AlgorithmIdentifier)
+ "0422" // OCTET STRING length 0x22 (PrivateKey)
+ "0420" // OCTET STRING length 0x20 (RFC 8410 s7)
+ "a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991"
+ // } end SEQUENCE (PrivateKeyInfo)
+);
+string ed25519_pubkey = hex2str("efbb01f3fb74da43af43d9d8a0c65cf47c57ec660d2b3ea81069ede304f45691");
+
+/**
+ * X25519 key pair generated as follows:
+ * ```
+ * % openssl genpkey -algorithm X25519 > x25519_priv.key
+ * % cat x25519_priv.key
+ * -----BEGIN PRIVATE KEY-----
+ * MC4CAQAwBQYDK2VuBCIEIGgPwF3NLwQx/Sfwr2nfJvXitwlDNh3Skzh+TISN/y1C
+ * -----END PRIVATE KEY-----
+ * % der2ascii -pem -i x25519_priv.key
+ * SEQUENCE {
+ * INTEGER { 0 }
+ * SEQUENCE {
+ * # x25519
+ * OBJECT_IDENTIFIER { 1.3.101.110 }
+ * }
+ * OCTET_STRING {
+ * OCTET_STRING { `680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42` }
+ * }
+ * }
+ * ```
+ */
+
+string x25519_key = hex2str("680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42");
+string x25519_pkcs8_key = hex2str(
+ // RFC 5208 s5
+ "302e" // SEQUENCE length 0x2e (PrivateKeyInfo) {
+ "0201" // INTEGER length 1 (Version)
+ "00" // version 0
+ "3005" // SEQUENCE length 05 (AlgorithmIdentifier) {
+ "0603" // OBJECT IDENTIFIER length 3 (algorithm)
+ "2b656e" // 1.3.101.110 (id-X125519 RFC 8410 s3)
+ "0422" // OCTET STRING length 0x22 (PrivateKey)
+ "0420" // OCTET STRING length 0x20 (RFC 8410 s7)
+ "680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42");
+string x25519_pubkey = hex2str("be46925a857f17831d6d454b9d3d36a4a30166edf80eb82b684661c3e258f768");
+
struct RSA_Delete {
void operator()(RSA* p) { RSA_free(p); }
};
@@ -894,6 +1018,37 @@
}
/*
+ * NewKeyGenerationTest.RsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithMissingValidity) {
+ // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+ // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+ constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+ kUndefinedExpirationDateTime),
+ &key_blob, &key_characteristics));
+
+ ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+ &key_blob, &key_characteristics));
+}
+
+/*
* NewKeyGenerationTest.RsaWithAttestation
*
* Verifies that keymint can generate all required RSA key sizes with attestation, and that the
@@ -912,18 +1067,21 @@
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -942,7 +1100,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
@@ -1045,17 +1203,21 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 65537)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
AuthorizationSet auths;
@@ -1093,7 +1255,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
@@ -1157,15 +1319,19 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
}
/*
@@ -1275,19 +1441,23 @@
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1315,7 +1485,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
@@ -1374,7 +1544,7 @@
/*
* NewKeyGenerationTest.Ecdsa
*
- * Verifies that keymint can generate all required EC key sizes, and that the resulting keys
+ * Verifies that keymint can generate all required EC curves, and that the resulting keys
* have correct characteristics.
*/
TEST_P(NewKeyGenerationTest, Ecdsa) {
@@ -1400,6 +1570,94 @@
}
/*
+ * NewKeyGenerationTest.EcdsaCurve25519
+ *
+ * Verifies that keymint can generate a curve25519 key, and that the resulting key
+ * has correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaCurve25519) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(key_blob.size(), 0U);
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
+
+ CheckedDeleteKey(&key_blob);
+}
+
+/*
+ * NewKeyGenerationTest.EcCurve25519MultiPurposeFail
+ *
+ * Verifies that KeyMint rejects an attempt to generate a curve 25519 key for both
+ * SIGN and AGREE_KEY.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaCurve25519MultiPurposeFail) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ ASSERT_EQ(result, ErrorCode::INCOMPATIBLE_PURPOSE);
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaWithMissingValidity) {
+ // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+ // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+ constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+ kUndefinedExpirationDateTime),
+ &key_blob, &key_characteristics));
+
+ ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+ GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+ &key_blob, &key_characteristics));
+}
+
+/*
* NewKeyGenerationTest.EcdsaAttestation
*
* Verifies that for all Ecdsa key sizes, if challenge and app id is provided,
@@ -1418,17 +1676,21 @@
for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(curve)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1444,7 +1706,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
@@ -1453,6 +1715,62 @@
}
/*
+ * NewKeyGenerationTest.EcdsaAttestationCurve25519
+ *
+ * Verifies that for a curve 25519 key, if challenge and app id is provided,
+ * an attestation will be generated.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationCurve25519) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ auto subject = "cert subj 2";
+ vector<uint8_t> subject_der(make_name_from_str(subject));
+
+ uint64_t serial_int = 0xFFFFFFFFFFFFFFFF;
+ vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ ASSERT_EQ(ErrorCode::OK, result);
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+ verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
+ sw_enforced, hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+}
+
+/*
* NewKeyGenerationTest.EcdsaAttestationTags
*
* Verifies that creation of an attested ECDSA key includes various tags in the
@@ -1506,6 +1824,10 @@
// Tag not required to be supported by all KeyMint implementations.
continue;
}
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_EQ(result, ErrorCode::OK);
ASSERT_GT(key_blob.size(), 0U);
@@ -1523,8 +1845,9 @@
// Verifying the attestation record will check for the specific tag because
// it's included in the authorizations.
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
- SecLevel(), cert_chain_[0].encodedCertificate));
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+ hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
CheckedDeleteKey(&key_blob);
}
@@ -1600,6 +1923,10 @@
AuthorizationSetBuilder builder = base_builder;
builder.push_back(tag);
auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
if (result == ErrorCode::CANNOT_ATTEST_IDS) {
// Device ID attestation is optional; KeyMint may not support it at all.
continue;
@@ -1621,8 +1948,9 @@
// Verifying the attestation record will check for the specific tag because
// it's included in the authorizations.
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
- SecLevel(), cert_chain_[0].encodedCertificate));
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+ hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
CheckedDeleteKey(&key_blob);
}
@@ -1668,9 +1996,9 @@
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics_);
// Check that the unique ID field in the extension is non-empty.
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
- SecLevel(), cert_chain_[0].encodedCertificate,
- unique_id));
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+ hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate, unique_id));
EXPECT_GT(unique_id->size(), 0);
CheckedDeleteKey();
};
@@ -1756,6 +2084,10 @@
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
.SetDefaultValidity(),
&key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_EQ(result, ErrorCode::OK);
ASSERT_GT(key_blob.size(), 0U);
@@ -1765,8 +2097,9 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, attest_app_id, sw_enforced, hw_enforced,
- SecLevel(), cert_chain_[0].encodedCertificate));
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, attest_app_id, sw_enforced,
+ hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
// Check that the app id is not in the cert.
string app_id = "clientid";
@@ -1834,13 +2167,17 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
}
/*
@@ -1897,14 +2234,19 @@
const string app_id(length, 'a');
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1919,7 +2261,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
- EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
cert_chain_[0].encodedCertificate));
@@ -1981,20 +2323,22 @@
}
/*
- * NewKeyGenerationTest.EcdsaInvalidSize
+ * NewKeyGenerationTest.EcdsaInvalidCurve
*
- * Verifies that specifying an invalid key size for EC key generation returns
+ * Verifies that specifying an invalid curve for EC key generation returns
* UNSUPPORTED_KEY_SIZE.
*/
-TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
+TEST_P(NewKeyGenerationTest, EcdsaInvalidCurve) {
for (auto curve : InvalidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(curve)
- .Digest(Digest::NONE)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
+ result == ErrorCode::UNSUPPORTED_EC_CURVE);
}
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
@@ -2805,15 +3149,19 @@
/*
* SigningOperationsTest.EcdsaAllDigestsAndCurves
*
- * Verifies ECDSA signature/verification for all digests and curves.
+ * Verifies ECDSA signature/verification for all digests and required curves.
*/
TEST_P(SigningOperationsTest, EcdsaAllDigestsAndCurves) {
- auto digests = ValidDigests(true /* withNone */, false /* withMD5 */);
string message = "1234567890";
string corrupt_message = "2234567890";
for (auto curve : ValidCurves()) {
SCOPED_TRACE(testing::Message() << "Curve::" << curve);
+ // Ed25519 only allows Digest::NONE.
+ auto digests = (curve == EcCurve::CURVE_25519)
+ ? std::vector<Digest>(1, Digest::NONE)
+ : ValidDigests(true /* withNone */, false /* withMD5 */);
+
ErrorCode error = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(curve)
@@ -2838,25 +3186,141 @@
/*
* SigningOperationsTest.EcdsaAllCurves
*
- * Verifies that ECDSA operations succeed with all possible curves.
+ * Verifies that ECDSA operations succeed with all required curves.
*/
TEST_P(SigningOperationsTest, EcdsaAllCurves) {
for (auto curve : ValidCurves()) {
+ Digest digest = (curve == EcCurve::CURVE_25519 ? Digest::NONE : Digest::SHA_2_256);
+ SCOPED_TRACE(testing::Message() << "Curve::" << curve);
ErrorCode error = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(curve)
- .Digest(Digest::SHA_2_256)
+ .Digest(digest)
.SetDefaultValidity());
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));
+ SignMessage(message, AuthorizationSetBuilder().Digest(digest));
CheckedDeleteKey();
}
}
/*
+ * SigningOperationsTest.EcdsaCurve25519
+ *
+ * Verifies that ECDSA operations succeed with curve25519.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity());
+ ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+ string message(1024, 'a');
+ SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE));
+ CheckedDeleteKey();
+}
+
+/*
+ * SigningOperationsTest.EcdsaCurve25519MaxSize
+ *
+ * Verifies that EDDSA operations with curve25519 under the maximum message size succeed.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519MaxSize) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity());
+ ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+ auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+
+ for (size_t msg_size : {MAX_ED25519_MSG_SIZE - 1, MAX_ED25519_MSG_SIZE}) {
+ SCOPED_TRACE(testing::Message() << "-msg-size=" << msg_size);
+ string message(msg_size, 'a');
+
+ // Attempt to sign via Begin+Finish.
+ AuthorizationSet out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+ EXPECT_TRUE(out_params.empty());
+ string signature;
+ auto result = Finish(message, &signature);
+ EXPECT_EQ(result, ErrorCode::OK);
+ LocalVerifyMessage(message, signature, params);
+
+ // Attempt to sign via Begin+Update+Finish
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+ EXPECT_TRUE(out_params.empty());
+ string output;
+ result = Update(message, &output);
+ EXPECT_EQ(result, ErrorCode::OK);
+ EXPECT_EQ(output.size(), 0);
+ string signature2;
+ EXPECT_EQ(ErrorCode::OK, Finish({}, &signature2));
+ LocalVerifyMessage(message, signature2, params);
+ }
+
+ CheckedDeleteKey();
+}
+
+/*
+ * SigningOperationsTest.EcdsaCurve25519MaxSizeFail
+ *
+ * Verifies that EDDSA operations with curve25519 fail when message size is too large.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519MaxSizeFail) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ EcCurve curve = EcCurve::CURVE_25519;
+ ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity());
+ ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+ auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+
+ for (size_t msg_size : {MAX_ED25519_MSG_SIZE + 1, MAX_ED25519_MSG_SIZE * 2}) {
+ SCOPED_TRACE(testing::Message() << "-msg-size=" << msg_size);
+ string message(msg_size, 'a');
+
+ // Attempt to sign via Begin+Finish.
+ AuthorizationSet out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+ EXPECT_TRUE(out_params.empty());
+ string signature;
+ auto result = Finish(message, &signature);
+ EXPECT_EQ(result, ErrorCode::INVALID_INPUT_LENGTH);
+
+ // Attempt to sign via Begin+Update (but never get to Finish)
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+ EXPECT_TRUE(out_params.empty());
+ string output;
+ result = Update(message, &output);
+ EXPECT_EQ(result, ErrorCode::INVALID_INPUT_LENGTH);
+ }
+
+ CheckedDeleteKey();
+}
+
+/*
* SigningOperationsTest.EcdsaNoDigestHugeData
*
* Verifies that ECDSA operations support very large messages, even without digesting. This
@@ -3151,6 +3615,58 @@
CheckedDeleteKey(&verification_key);
}
+/*
+ * VerificationOperationsTest.HmacVerificationFailsForCorruptSignature
+ *
+ * Verifies HMAC signature verification should fails if message or signature is corrupted.
+ */
+TEST_P(VerificationOperationsTest, HmacVerificationFailsForCorruptSignature) {
+ string key_material = "HelloThisIsAKey";
+
+ vector<uint8_t> signing_key, verification_key;
+ vector<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));
+
+ AuthorizationSet begin_out_params;
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY, verification_key,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+ string corruptMessage = "This is b message."; // Corrupted message
+ string output;
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corruptMessage, signature, &output));
+
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::VERIFY, verification_key,
+ AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+ signature[0] += 1; // Corrupt a signature
+ EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, signature, &output));
+
+ CheckedDeleteKey(&signing_key);
+ CheckedDeleteKey(&verification_key);
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
typedef KeyMintAidlTestBase ExportKeyTest;
@@ -3300,6 +3816,26 @@
}
/*
+ * ImportKeyTest.RsaAttestMultiPurposeFail
+ *
+ * Verifies that importing an RSA key pair with purpose ATTEST_KEY+SIGN fails.
+ */
+TEST_P(ImportKeyTest, RsaAttestMultiPurposeFail) {
+ uint32_t key_size = 2048;
+ string key = rsa_2048_key;
+
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(key_size, 65537)
+ .AttestKey()
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PSS)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, key));
+}
+
+/*
* ImportKeyTest.EcdsaSuccess
*
* Verifies that importing and using an ECDSA P-256 key pair works correctly.
@@ -3418,6 +3954,271 @@
}
/*
+ * ImportKeyTest.EcdsaAttestMultiPurposeFail
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair with purpose ATTEST_KEY+SIGN fails.
+ */
+TEST_P(ImportKeyTest, EcdsaAttestMultiPurposeFail) {
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .Digest(Digest::SHA_2_256)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519RawSuccess
+ *
+ * Verifies that importing and using a raw Ed25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, Ed25519RawSuccess) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, ed25519_key));
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+ CheckOrigin();
+
+ // The returned cert should hold the correct public key.
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_NE(kmKeyCert, nullptr);
+ EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(kmPubKey.get(), nullptr);
+ size_t kmPubKeySize = 32;
+ uint8_t kmPubKeyData[32];
+ ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+ ASSERT_EQ(kmPubKeySize, 32);
+ EXPECT_EQ(string(kmPubKeyData, kmPubKeyData + 32), ed25519_pubkey);
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+ string signature = SignMessage(message, params);
+ LocalVerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ed25519Pkcs8Success
+ *
+ * Verifies that importing and using a PKCS#8-encoded Ed25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, Ed25519Pkcs8Success) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, ed25519_pkcs8_key));
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+ CheckOrigin();
+
+ // The returned cert should hold the correct public key.
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_NE(kmKeyCert, nullptr);
+ EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(kmPubKey.get(), nullptr);
+ size_t kmPubKeySize = 32;
+ uint8_t kmPubKeyData[32];
+ ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+ ASSERT_EQ(kmPubKeySize, 32);
+ EXPECT_EQ(string(kmPubKeyData, kmPubKeyData + 32), ed25519_pubkey);
+
+ string message(32, 'a');
+ auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+ string signature = SignMessage(message, params);
+ LocalVerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ed25519CurveMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with a curve that doesn't match the key fails in
+ * the correct way.
+ */
+TEST_P(ImportKeyTest, Ed25519CurveMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_NE(ErrorCode::OK,
+ ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, ed25519_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519FormatMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, Ed25519FormatMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, ed25519_key));
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, ed25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519PurposeMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with an invalid purpose fails.
+ */
+TEST_P(ImportKeyTest, Ed25519PurposeMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ // Can't have both SIGN and ATTEST_KEY
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, ed25519_key));
+ // AGREE_KEY is for X25519 (but can only tell the difference if the import key is in
+ // PKCS#8 format and so includes an OID).
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, ed25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.X25519RawSuccess
+ *
+ * Verifies that importing and using a raw X25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, X25519RawSuccess) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, x25519_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+ CheckOrigin();
+}
+
+/*
+ * ImportKeyTest.X25519Pkcs8Success
+ *
+ * Verifies that importing and using a PKCS#8-encoded X25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, X25519Pkcs8Success) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, x25519_pkcs8_key));
+
+ CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+ CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+ CheckOrigin();
+}
+
+/*
+ * ImportKeyTest.X25519CurveMismatch
+ *
+ * Verifies that importing an X25519 key with a curve that doesn't match the key fails in
+ * the correct way.
+ */
+TEST_P(ImportKeyTest, X25519CurveMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_224 /* Doesn't match key */)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, x25519_key));
+}
+
+/*
+ * ImportKeyTest.X25519FormatMismatch
+ *
+ * Verifies that importing an X25519 key with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, X25519FormatMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, x25519_key));
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::RAW, x25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.X25519PurposeMismatch
+ *
+ * Verifies that importing an X25519 key pair with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, X25519PurposeMismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, x25519_pkcs8_key));
+ ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, x25519_pkcs8_key));
+}
+
+/*
* ImportKeyTest.AesSuccess
*
* Verifies that importing and using an AES key works.
@@ -3945,7 +4746,7 @@
* Verifies that raw RSA decryption works.
*/
TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
- for (uint64_t exponent : {3, 65537}) {
+ for (uint64_t exponent : ValidExponents()) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaEncryptionKey(2048, exponent)
@@ -4517,8 +5318,10 @@
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');
+ for (size_t i = 0; i <= 48; i++) {
+ SCOPED_TRACE(testing::Message() << "i = " << i);
+ // Edge case: '\t' (0x09) is also a valid PKCS7 padding character.
+ string message(i, '\t');
string ciphertext = EncryptMessage(message, params);
EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
string plaintext = DecryptMessage(ciphertext, params);
@@ -4542,7 +5345,7 @@
auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
// Try various message lengths; all should fail
- for (size_t i = 0; i < 32; ++i) {
+ for (size_t i = 0; i <= 48; i++) {
string message(i, 'a');
EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
}
@@ -4638,89 +5441,39 @@
}
/*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
*
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
*/
-TEST_P(EncryptionOperationsTest, AesIncremental) {
- auto block_modes = {
- BlockMode::ECB,
- BlockMode::CBC,
- BlockMode::CTR,
- BlockMode::GCM,
- };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
- 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)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
- 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);
- if (block_mode == BlockMode::GCM) {
- params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
- }
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
- AuthorizationSet output_params;
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
- string ciphertext;
- string to_send;
- for (size_t i = 0; i < message.size(); i += increment) {
- EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
- }
- EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
- << "Error sending " << to_send << " with block mode " << block_mode;
-
- 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) << "No IV for block mode " << block_mode;
- EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
- params.push_back(TAG_NONCE, iv->get());
- break;
-
- case BlockMode::ECB:
- EXPECT_FALSE(iv) << "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) {
- EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
- }
- 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;
- }
- }
- }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+ CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
}
struct AesCtrSp80038aTestVector {
@@ -5684,8 +6437,8 @@
ASSERT_GT(key_blob_.size(), 0U);
- // Two-block message.
- string message = "1234567890123456";
+ // Four-block message.
+ string message = "12345678901234561234567890123456";
vector<uint8_t> iv1;
string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv1);
EXPECT_EQ(message.size(), ciphertext1.size());
@@ -5845,8 +6598,10 @@
.Padding(PaddingMode::PKCS7)));
// Try various message lengths; all should work.
- for (size_t i = 0; i < 32; ++i) {
- string message(i, 'a');
+ for (size_t i = 0; i <= 32; i++) {
+ SCOPED_TRACE(testing::Message() << "i = " << i);
+ // Edge case: '\t' (0x09) is also a valid PKCS7 padding character, albeit not for 3DES.
+ string message(i, '\t');
vector<uint8_t> iv;
string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
@@ -5868,7 +6623,7 @@
.Padding(PaddingMode::NONE)));
// Try various message lengths; all should fail.
- for (size_t i = 0; i < 32; ++i) {
+ 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));
@@ -5899,6 +6654,7 @@
.Authorization(TAG_NONCE, iv);
for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+ SCOPED_TRACE(testing::Message() << "i = " << i);
++ciphertext[ciphertext.size() / 2];
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
string plaintext;
@@ -6503,7 +7259,7 @@
size_t i;
for (i = 0; i < max_operations; i++) {
- result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+ result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
if (ErrorCode::OK != result) {
break;
}
@@ -6511,12 +7267,12 @@
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));
+ Begin(KeyPurpose::DECRYPT, 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));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
AbortIfNeeded();
}
@@ -6564,9 +7320,7 @@
INSTANTIATE_KEYMINT_AIDL_TEST(TransportLimitTest);
-typedef KeyMintAidlTestBase KeyAgreementTest;
-
-int CurveToOpenSslCurveName(EcCurve curve) {
+static int EcdhCurveToOpenSslCurveName(EcCurve curve) {
switch (curve) {
case EcCurve::P_224:
return NID_secp224r1;
@@ -6576,13 +7330,113 @@
return NID_secp384r1;
case EcCurve::P_521:
return NID_secp521r1;
+ case EcCurve::CURVE_25519:
+ return NID_X25519;
}
}
+class KeyAgreementTest : public KeyMintAidlTestBase {
+ protected:
+ void GenerateLocalEcKey(EcCurve localCurve, EVP_PKEY_Ptr* localPrivKey,
+ std::vector<uint8_t>* localPublicKey) {
+ // Generate EC key locally (with access to private key material)
+ if (localCurve == EcCurve::CURVE_25519) {
+ uint8_t privKeyData[32];
+ uint8_t pubKeyData[32];
+ X25519_keypair(pubKeyData, privKeyData);
+ *localPublicKey = vector<uint8_t>(pubKeyData, pubKeyData + 32);
+ *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new_raw_private_key(
+ EVP_PKEY_X25519, nullptr, privKeyData, sizeof(privKeyData)));
+ } else {
+ auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+ int curveName = EcdhCurveToOpenSslCurveName(localCurve);
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curveName));
+ ASSERT_NE(group, nullptr);
+ ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
+ ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
+ *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new());
+ ASSERT_EQ(EVP_PKEY_set1_EC_KEY(localPrivKey->get(), ecKey.get()), 1);
+
+ // Get encoded form of the public part of the locally generated key...
+ unsigned char* p = nullptr;
+ int localPublicKeySize = i2d_PUBKEY(localPrivKey->get(), &p);
+ ASSERT_GT(localPublicKeySize, 0);
+ *localPublicKey =
+ vector<uint8_t>(reinterpret_cast<const uint8_t*>(p),
+ reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
+ OPENSSL_free(p);
+ }
+ }
+
+ void GenerateKeyMintEcKey(EcCurve curve, EVP_PKEY_Ptr* kmPubKey) {
+ vector<uint8_t> challenge = {0x41, 0x42};
+ ErrorCode result =
+ GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_EC_CURVE, curve)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62})
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+ .SetDefaultValidity());
+ ASSERT_EQ(ErrorCode::OK, result) << "Failed to generate key";
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_NE(kmKeyCert, nullptr);
+ // Check that keyAgreement (bit 4) is set in KeyUsage
+ EXPECT_TRUE((X509_get_key_usage(kmKeyCert.get()) & X509v3_KU_KEY_AGREEMENT) != 0);
+ *kmPubKey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(*kmPubKey, nullptr);
+ if (dump_Attestations) {
+ for (size_t n = 0; n < cert_chain_.size(); n++) {
+ std::cout << bin2hex(cert_chain_[n].encodedCertificate) << std::endl;
+ }
+ }
+ }
+
+ void CheckAgreement(EVP_PKEY_Ptr kmPubKey, EVP_PKEY_Ptr localPrivKey,
+ const std::vector<uint8_t>& localPublicKey) {
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+ string ZabFromKeyMintStr;
+ ASSERT_EQ(ErrorCode::OK,
+ Finish(string(localPublicKey.begin(), localPublicKey.end()), &ZabFromKeyMintStr));
+ vector<uint8_t> ZabFromKeyMint(ZabFromKeyMintStr.begin(), ZabFromKeyMintStr.end());
+ vector<uint8_t> ZabFromTest;
+
+ if (EVP_PKEY_id(kmPubKey.get()) == EVP_PKEY_X25519) {
+ size_t kmPubKeySize = 32;
+ uint8_t kmPubKeyData[32];
+ ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+ ASSERT_EQ(kmPubKeySize, 32);
+
+ uint8_t localPrivKeyData[32];
+ size_t localPrivKeySize = 32;
+ ASSERT_EQ(1, EVP_PKEY_get_raw_private_key(localPrivKey.get(), localPrivKeyData,
+ &localPrivKeySize));
+ ASSERT_EQ(localPrivKeySize, 32);
+
+ uint8_t sharedKey[32];
+ ASSERT_EQ(1, X25519(sharedKey, localPrivKeyData, kmPubKeyData));
+ ZabFromTest = std::vector<uint8_t>(sharedKey, sharedKey + 32);
+ } else {
+ // Perform local ECDH between the two keys so we can check if we get the same Zab..
+ auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(localPrivKey.get(), nullptr));
+ ASSERT_NE(ctx, nullptr);
+ ASSERT_EQ(EVP_PKEY_derive_init(ctx.get()), 1);
+ ASSERT_EQ(EVP_PKEY_derive_set_peer(ctx.get(), kmPubKey.get()), 1);
+ size_t ZabFromTestLen = 0;
+ ASSERT_EQ(EVP_PKEY_derive(ctx.get(), nullptr, &ZabFromTestLen), 1);
+ ZabFromTest.resize(ZabFromTestLen);
+ ASSERT_EQ(EVP_PKEY_derive(ctx.get(), ZabFromTest.data(), &ZabFromTestLen), 1);
+ }
+ EXPECT_EQ(ZabFromKeyMint, ZabFromTest);
+ }
+};
+
/*
* KeyAgreementTest.Ecdh
*
- * Verifies that ECDH works for all curves
+ * Verifies that ECDH works for all required curves
*/
TEST_P(KeyAgreementTest, Ecdh) {
// Because it's possible to use this API with keys on different curves, we
@@ -6596,49 +7450,13 @@
for (auto curve : ValidCurves()) {
for (auto localCurve : ValidCurves()) {
// Generate EC key locally (with access to private key material)
- auto ecKey = EC_KEY_Ptr(EC_KEY_new());
- int curveName = CurveToOpenSslCurveName(localCurve);
- auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curveName));
- ASSERT_NE(group, nullptr);
- ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
- ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
- auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
- ASSERT_EQ(EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()), 1);
-
- // Get encoded form of the public part of the locally generated key...
- unsigned char* p = nullptr;
- int encodedPublicKeySize = i2d_PUBKEY(pkey.get(), &p);
- ASSERT_GT(encodedPublicKeySize, 0);
- vector<uint8_t> encodedPublicKey(
- reinterpret_cast<const uint8_t*>(p),
- reinterpret_cast<const uint8_t*>(p + encodedPublicKeySize));
- OPENSSL_free(p);
+ EVP_PKEY_Ptr localPrivKey;
+ vector<uint8_t> localPublicKey;
+ GenerateLocalEcKey(localCurve, &localPrivKey, &localPublicKey);
// Generate EC key in KeyMint (only access to public key material)
- vector<uint8_t> challenge = {0x41, 0x42};
- EXPECT_EQ(
- ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_EC_CURVE, curve)
- .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
- .Authorization(TAG_ALGORITHM, Algorithm::EC)
- .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62})
- .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
- .SetDefaultValidity()))
- << "Failed to generate key";
- ASSERT_GT(cert_chain_.size(), 0);
- X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
- ASSERT_NE(kmKeyCert, nullptr);
- // Check that keyAgreement (bit 4) is set in KeyUsage
- EXPECT_TRUE((X509_get_key_usage(kmKeyCert.get()) & X509v3_KU_KEY_AGREEMENT) != 0);
- auto kmPkey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
- ASSERT_NE(kmPkey, nullptr);
- if (dump_Attestations) {
- for (size_t n = 0; n < cert_chain_.size(); n++) {
- std::cout << bin2hex(cert_chain_[n].encodedCertificate) << std::endl;
- }
- }
+ EVP_PKEY_Ptr kmPubKey;
+ GenerateKeyMintEcKey(curve, &kmPubKey);
// Now that we have the two keys, we ask KeyMint to perform ECDH...
if (curve != localCurve) {
@@ -6647,30 +7465,12 @@
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
string ZabFromKeyMintStr;
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
- Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
+ Finish(string(localPublicKey.begin(), localPublicKey.end()),
&ZabFromKeyMintStr));
} else {
// Otherwise if the keys are using the same curve, it should work.
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
- string ZabFromKeyMintStr;
- EXPECT_EQ(ErrorCode::OK,
- Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
- &ZabFromKeyMintStr));
- vector<uint8_t> ZabFromKeyMint(ZabFromKeyMintStr.begin(), ZabFromKeyMintStr.end());
-
- // Perform local ECDH between the two keys so we can check if we get the same Zab..
- auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(pkey.get(), nullptr));
- ASSERT_NE(ctx, nullptr);
- ASSERT_EQ(EVP_PKEY_derive_init(ctx.get()), 1);
- ASSERT_EQ(EVP_PKEY_derive_set_peer(ctx.get(), kmPkey.get()), 1);
- size_t ZabFromTestLen = 0;
- ASSERT_EQ(EVP_PKEY_derive(ctx.get(), nullptr, &ZabFromTestLen), 1);
- vector<uint8_t> ZabFromTest;
- ZabFromTest.resize(ZabFromTestLen);
- ASSERT_EQ(EVP_PKEY_derive(ctx.get(), ZabFromTest.data(), &ZabFromTestLen), 1);
-
- EXPECT_EQ(ZabFromKeyMint, ZabFromTest);
+ CheckAgreement(std::move(kmPubKey), std::move(localPrivKey), localPublicKey);
}
CheckedDeleteKey();
@@ -6678,6 +7478,140 @@
}
}
+/*
+ * KeyAgreementTest.EcdhCurve25519
+ *
+ * Verifies that ECDH works for curve25519. This is also covered by the general
+ * KeyAgreementTest.Ecdh case, but is pulled out separately here because this curve was added after
+ * KeyMint 1.0.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ // Generate EC key in KeyMint (only access to public key material)
+ EcCurve curve = EcCurve::CURVE_25519;
+ EVP_PKEY_Ptr kmPubKey = nullptr;
+ GenerateKeyMintEcKey(curve, &kmPubKey);
+
+ // Generate EC key on same curve locally (with access to private key material).
+ EVP_PKEY_Ptr privKey;
+ vector<uint8_t> encodedPublicKey;
+ GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+ // Agree on a key between local and KeyMint and check it.
+ CheckAgreement(std::move(kmPubKey), std::move(privKey), encodedPublicKey);
+
+ CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519Imported
+ *
+ * Verifies that ECDH works for an imported curve25519 key.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519Imported) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ // Import x25519 key into KeyMint.
+ EcCurve curve = EcCurve::CURVE_25519;
+ ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .SetDefaultValidity(),
+ KeyFormat::PKCS8, x25519_pkcs8_key));
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_NE(kmKeyCert, nullptr);
+ EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(kmPubKey.get(), nullptr);
+
+ // Expect the import to emit corresponding public key data.
+ size_t kmPubKeySize = 32;
+ uint8_t kmPubKeyData[32];
+ ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+ ASSERT_EQ(kmPubKeySize, 32);
+ EXPECT_EQ(bin2hex(std::vector<uint8_t>(kmPubKeyData, kmPubKeyData + 32)),
+ bin2hex(std::vector<uint8_t>(x25519_pubkey.begin(), x25519_pubkey.end())));
+
+ // Generate EC key on same curve locally (with access to private key material).
+ EVP_PKEY_Ptr privKey;
+ vector<uint8_t> encodedPublicKey;
+ GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+ // Agree on a key between local and KeyMint and check it.
+ CheckAgreement(std::move(kmPubKey), std::move(privKey), encodedPublicKey);
+
+ CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519InvalidSize
+ *
+ * Verifies that ECDH fails for curve25519 if the wrong size of public key is provided.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519InvalidSize) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ // Generate EC key in KeyMint (only access to public key material)
+ EcCurve curve = EcCurve::CURVE_25519;
+ EVP_PKEY_Ptr kmPubKey = nullptr;
+ GenerateKeyMintEcKey(curve, &kmPubKey);
+
+ // Generate EC key on same curve locally (with access to private key material).
+ EVP_PKEY_Ptr privKey;
+ vector<uint8_t> encodedPublicKey;
+ GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+ string ZabFromKeyMintStr;
+ // Send in an incomplete public key.
+ ASSERT_NE(ErrorCode::OK, Finish(string(encodedPublicKey.begin(), encodedPublicKey.end() - 1),
+ &ZabFromKeyMintStr));
+
+ CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519Mismatch
+ *
+ * Verifies that ECDH fails between curve25519 and other curves.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519Mismatch) {
+ if (!Curve25519Supported()) {
+ GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+ }
+
+ // Generate EC key in KeyMint (only access to public key material)
+ EcCurve curve = EcCurve::CURVE_25519;
+ EVP_PKEY_Ptr kmPubKey = nullptr;
+ GenerateKeyMintEcKey(curve, &kmPubKey);
+
+ for (auto localCurve : ValidCurves()) {
+ if (localCurve == curve) {
+ continue;
+ }
+ // Generate EC key on a different curve locally (with access to private key material).
+ EVP_PKEY_Ptr privKey;
+ vector<uint8_t> encodedPublicKey;
+ GenerateLocalEcKey(localCurve, &privKey, &encodedPublicKey);
+
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+ string ZabFromKeyMintStr;
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
+ Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
+ &ZabFromKeyMintStr));
+ }
+
+ CheckedDeleteKey();
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(KeyAgreementTest);
using DestroyAttestationIdsTest = KeyMintAidlTestBase;
@@ -6727,14 +7661,23 @@
});
for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ // Strongbox may not support factory attestation. Key creation might fail with
+ // ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED
+ if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) {
+ continue;
+ }
ASSERT_GT(keyData.blob.size(), 0U);
AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
}
CheckedDeleteKey(&aesKeyData.blob);
CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
+ if (rsaKeyData.blob.size() != 0U) {
+ CheckedDeleteKey(&rsaKeyData.blob);
+ }
+ if (ecdsaKeyData.blob.size() != 0U) {
+ CheckedDeleteKey(&ecdsaKeyData.blob);
+ }
}
/*
diff --git a/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
new file mode 100644
index 0000000..6f13867
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_2_se_provisioning_test"
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include <cppbor_parse.h>
+#include <keymaster/cppcose/cppcose.h>
+#include <keymint_support/key_param_output.h>
+
+#include "KeyMintAidlTestBase.h"
+
+namespace aidl::android::hardware::security::keymint::test {
+
+using std::array;
+using std::map;
+using std::shared_ptr;
+using std::vector;
+
+class SecureElementProvisioningTest : public testing::Test {
+ protected:
+ static void SetUpTestSuite() {
+ auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+ for (auto& param : params) {
+ ASSERT_TRUE(AServiceManager_isDeclared(param.c_str()))
+ << "IKeyMintDevice instance " << param << " found but not declared.";
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService(param.c_str()));
+ auto keymint = IKeyMintDevice::fromBinder(binder);
+ ASSERT_NE(keymint, nullptr) << "Failed to get IKeyMintDevice instance " << param;
+
+ KeyMintHardwareInfo info;
+ ASSERT_TRUE(keymint->getHardwareInfo(&info).isOk());
+ ASSERT_EQ(keymints_.count(info.securityLevel), 0)
+ << "There must be exactly one IKeyMintDevice with security level "
+ << info.securityLevel;
+
+ keymints_[info.securityLevel] = std::move(keymint);
+ }
+ }
+
+ static map<SecurityLevel, shared_ptr<IKeyMintDevice>> keymints_;
+};
+
+map<SecurityLevel, shared_ptr<IKeyMintDevice>> SecureElementProvisioningTest::keymints_;
+
+TEST_F(SecureElementProvisioningTest, ValidConfigurations) {
+ if (keymints_.empty()) {
+ GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+ }
+ // TEE is required
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ // StrongBox is optional
+ ASSERT_LE(keymints_.count(SecurityLevel::STRONGBOX), 1);
+}
+
+TEST_F(SecureElementProvisioningTest, TeeOnly) {
+ if (keymints_.empty()) {
+ GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+ }
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+ ASSERT_NE(tee, nullptr);
+
+ array<uint8_t, 16> challenge1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ array<uint8_t, 16> challenge2 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ vector<uint8_t> rootOfTrust1;
+ Status result = tee->getRootOfTrust(challenge1, &rootOfTrust1);
+
+ // TODO: Remove the next line to require TEEs to succeed.
+ if (!result.isOk()) return;
+
+ ASSERT_TRUE(result.isOk());
+
+ // TODO: Parse and validate rootOfTrust1 here
+
+ vector<uint8_t> rootOfTrust2;
+ result = tee->getRootOfTrust(challenge2, &rootOfTrust2);
+ ASSERT_TRUE(result.isOk());
+
+ // TODO: Parse and validate rootOfTrust2 here
+
+ ASSERT_NE(rootOfTrust1, rootOfTrust2);
+
+ vector<uint8_t> rootOfTrust3;
+ result = tee->getRootOfTrust(challenge1, &rootOfTrust3);
+ ASSERT_TRUE(result.isOk());
+
+ ASSERT_EQ(rootOfTrust1, rootOfTrust3);
+
+ // TODO: Parse and validate rootOfTrust3 here
+}
+
+TEST_F(SecureElementProvisioningTest, TeeDoesNotImplementStrongBoxMethods) {
+ if (keymints_.empty()) {
+ GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+ }
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+ ASSERT_NE(tee, nullptr);
+
+ array<uint8_t, 16> challenge;
+ Status result = tee->getRootOfTrustChallenge(&challenge);
+ ASSERT_FALSE(result.isOk());
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+
+ result = tee->sendRootOfTrust({});
+ ASSERT_FALSE(result.isOk());
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, StrongBoxDoesNotImplementTeeMethods) {
+ if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+ // Need a StrongBox to provision.
+ GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+ }
+
+ auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+ ASSERT_NE(sb, nullptr);
+
+ vector<uint8_t> rootOfTrust;
+ Status result = sb->getRootOfTrust({}, &rootOfTrust);
+ ASSERT_FALSE(result.isOk());
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, UnimplementedTest) {
+ if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+ // Need a StrongBox to provision.
+ GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+ }
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+ ASSERT_NE(tee, nullptr);
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+ auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+ ASSERT_NE(sb, nullptr);
+
+ array<uint8_t, 16> challenge;
+ Status result = sb->getRootOfTrustChallenge(&challenge);
+ if (!result.isOk()) {
+ // Strongbox does not have to implement this feature if it has uses an alternative mechanism
+ // to provision the root of trust. In that case it MUST return UNIMPLEMENTED, both from
+ // getRootOfTrustChallenge() and from sendRootOfTrust().
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+ ErrorCode::UNIMPLEMENTED);
+
+ result = sb->sendRootOfTrust({});
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+ ErrorCode::UNIMPLEMENTED);
+
+ SUCCEED() << "This Strongbox implementation does not use late root of trust delivery.";
+ return;
+ }
+}
+
+TEST_F(SecureElementProvisioningTest, ChallengeQualityTest) {
+ if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+ // Need a StrongBox to provision.
+ GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+ }
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+ auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+ ASSERT_NE(sb, nullptr);
+
+ array<uint8_t, 16> challenge1;
+ Status result = sb->getRootOfTrustChallenge(&challenge1);
+ if (!result.isOk()) return;
+
+ array<uint8_t, 16> challenge2;
+ result = sb->getRootOfTrustChallenge(&challenge2);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_NE(challenge1, challenge2);
+
+ // TODO: When we add entropy testing in other relevant places in these tests, add it here, too,
+ // to verify that challenges appear to have adequate entropy.
+}
+
+TEST_F(SecureElementProvisioningTest, ProvisioningTest) {
+ if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+ // Need a StrongBox to provision.
+ GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+ }
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+ ASSERT_NE(tee, nullptr);
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+ auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+ ASSERT_NE(sb, nullptr);
+
+ array<uint8_t, 16> challenge;
+ Status result = sb->getRootOfTrustChallenge(&challenge);
+ if (!result.isOk()) return;
+
+ vector<uint8_t> rootOfTrust;
+ result = tee->getRootOfTrust(challenge, &rootOfTrust);
+ ASSERT_TRUE(result.isOk());
+
+ // TODO: Verify COSE_Mac0 structure and content here.
+
+ result = sb->sendRootOfTrust(rootOfTrust);
+ ASSERT_TRUE(result.isOk());
+
+ // Sending again must fail, because a new challenge is required.
+ result = sb->sendRootOfTrust(rootOfTrust);
+ ASSERT_FALSE(result.isOk());
+}
+
+TEST_F(SecureElementProvisioningTest, InvalidProvisioningTest) {
+ if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+ // Need a StrongBox to provision.
+ GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+ }
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+ auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+ ASSERT_NE(tee, nullptr);
+
+ ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+ auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+ ASSERT_NE(sb, nullptr);
+
+ array<uint8_t, 16> challenge;
+ Status result = sb->getRootOfTrustChallenge(&challenge);
+ if (!result.isOk()) return;
+
+ result = sb->sendRootOfTrust({});
+ ASSERT_FALSE(result.isOk());
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+ ErrorCode::VERIFICATION_FAILED);
+
+ vector<uint8_t> rootOfTrust;
+ result = tee->getRootOfTrust(challenge, &rootOfTrust);
+ ASSERT_TRUE(result.isOk());
+
+ vector<uint8_t> corruptedRootOfTrust = rootOfTrust;
+ corruptedRootOfTrust[corruptedRootOfTrust.size() / 2]++;
+ result = sb->sendRootOfTrust(corruptedRootOfTrust);
+ ASSERT_FALSE(result.isOk());
+ ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+ ErrorCode::VERIFICATION_FAILED);
+
+ // Now try the correct RoT
+ result = sb->sendRootOfTrust(rootOfTrust);
+ ASSERT_TRUE(result.isOk());
+}
+
+} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 76fb79b..2e90e78 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -20,6 +20,7 @@
#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
#include <cppbor_parse.h>
#include <gmock/gmock.h>
#include <keymaster/cppcose/cppcose.h>
@@ -29,6 +30,7 @@
#include <openssl/ec_key.h>
#include <openssl/x509.h>
#include <remote_prov/remote_prov_utils.h>
+#include <set>
#include <vector>
#include "KeyMintAidlTestBase.h"
@@ -40,6 +42,8 @@
namespace {
+constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
+
#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
INSTANTIATE_TEST_SUITE_P( \
@@ -47,11 +51,28 @@
testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
::android::PrintInstanceNameToString)
+using ::android::sp;
using bytevec = std::vector<uint8_t>;
using testing::MatchesRegex;
using namespace remote_prov;
using namespace keymaster;
+std::set<std::string> getAllowedVbStates() {
+ return {"green", "yellow", "orange"};
+}
+
+std::set<std::string> getAllowedBootloaderStates() {
+ return {"locked", "unlocked"};
+}
+
+std::set<std::string> getAllowedSecurityLevels() {
+ return {"tee", "strongbox"};
+}
+
+std::set<std::string> getAllowedAttIdStates() {
+ return {"locked", "open"};
+}
+
bytevec string_to_bytevec(const char* s) {
const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
return bytevec(p, p + strlen(s));
@@ -164,6 +185,7 @@
provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
}
ASSERT_NE(provisionable_, nullptr);
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
}
static vector<string> build_params() {
@@ -173,8 +195,70 @@
protected:
std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
+ RpcHardwareInfo rpcHardwareInfo;
};
+/**
+ * Verify that every implementation reports a different unique id.
+ */
+TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
+ std::set<std::string> uniqueIds;
+ for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
+ ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
+ std::shared_ptr<IRemotelyProvisionedComponent> rpc =
+ IRemotelyProvisionedComponent::fromBinder(binder);
+ ASSERT_NE(rpc, nullptr);
+
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
+
+ int32_t version;
+ ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
+ if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
+ ASSERT_TRUE(hwInfo.uniqueId);
+ auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
+ EXPECT_TRUE(wasInserted);
+ } else {
+ ASSERT_FALSE(hwInfo.uniqueId);
+ }
+ }
+}
+
+using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
+
+INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
+
+/**
+ * Verify that a valid curve is reported by the implementation.
+ */
+TEST_P(GetHardwareInfoTests, supportsValidCurve) {
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+
+ const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
+ ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
+ << "Invalid curve: " << hwInfo.supportedEekCurve;
+}
+
+/**
+ * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
+ */
+TEST_P(GetHardwareInfoTests, uniqueId) {
+ int32_t version;
+ ASSERT_TRUE(provisionable_->getInterfaceVersion(&version).isOk());
+
+ if (version < VERSION_WITH_UNIQUE_ID_SUPPORT) {
+ return;
+ }
+
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+ ASSERT_TRUE(hwInfo.uniqueId);
+ EXPECT_GE(hwInfo.uniqueId->size(), 1);
+ EXPECT_LE(hwInfo.uniqueId->size(), 32);
+}
+
using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
@@ -236,9 +320,11 @@
vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
EXPECT_EQ(attested_key_cert_chain.size(), 1);
+ int32_t aidl_version = 0;
+ ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced,
+ EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
info.securityLevel,
attested_key_cert_chain[0].encodedCertificate));
@@ -273,11 +359,10 @@
class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
protected:
CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
- generateTestEekChain(3);
}
void generateTestEekChain(size_t eekLength) {
- auto chain = generateEekChain(eekLength, eekId_);
+ auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
EXPECT_TRUE(chain) << chain.message();
if (chain) testEekChain_ = chain.moveValue();
testEekLength_ = eekLength;
@@ -298,6 +383,17 @@
}
}
+ ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
+ if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
+ rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
+ return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+ senderPubkey->first, false /* senderIsA */);
+ } else {
+ return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+ senderPubkey->first, false /* senderIsA */);
+ }
+ }
+
void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
const bytevec& keysToSignMac, const ProtectedData& protectedData,
std::vector<BccEntryData>* bccOutput = nullptr) {
@@ -310,9 +406,7 @@
ASSERT_TRUE(senderPubkey) << senderPubkey.message();
EXPECT_EQ(senderPubkey->second, eekId_);
- auto sessionKey =
- x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
- senderPubkey->first, false /* senderIsA */);
+ auto sessionKey = getSessionKey(senderPubkey);
ASSERT_TRUE(sessionKey) << sessionKey.message();
auto protectedDataPayload =
@@ -322,7 +416,8 @@
auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
ASSERT_TRUE(parsedPayload->asArray());
- EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
+ // Strongbox may contain additional certificate chain.
+ EXPECT_LE(parsedPayload->asArray()->size(), 3U);
auto& signedMac = parsedPayload->asArray()->get(0);
auto& bcc = parsedPayload->asArray()->get(1);
@@ -338,6 +433,8 @@
ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
ASSERT_TRUE(deviceInfoMap->asMap());
+ checkDeviceInfo(deviceInfoMap->asMap(), deviceInfo.deviceInfo);
+
auto& signingKey = bccContents->back().pubKey;
auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
cppbor::Array() // SignedMacAad
@@ -364,6 +461,80 @@
}
}
+ void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
+ const auto& val = devInfo->get(entryName);
+ ASSERT_TRUE(val) << entryName << " does not exist";
+ ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
+ switch (majorType) {
+ case cppbor::TSTR:
+ ASSERT_GT(val->asTstr()->value().size(), 0);
+ break;
+ case cppbor::BSTR:
+ ASSERT_GT(val->asBstr()->value().size(), 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void checkDeviceInfo(const cppbor::Map* deviceInfo, bytevec deviceInfoBytes) {
+ const auto& version = deviceInfo->get("version");
+ ASSERT_TRUE(version);
+ ASSERT_TRUE(version->asUint());
+ RpcHardwareInfo info;
+ provisionable_->getHardwareInfo(&info);
+ ASSERT_EQ(version->asUint()->value(), info.versionNumber);
+ std::set<std::string> allowList;
+ switch (version->asUint()->value()) {
+ // These fields became mandated in version 2.
+ case 2:
+ checkType(deviceInfo, cppbor::TSTR, "brand");
+ checkType(deviceInfo, cppbor::TSTR, "manufacturer");
+ checkType(deviceInfo, cppbor::TSTR, "product");
+ checkType(deviceInfo, cppbor::TSTR, "model");
+ checkType(deviceInfo, cppbor::TSTR, "device");
+ // TODO: Refactor the KeyMint code that validates these fields and include it here.
+ checkType(deviceInfo, cppbor::TSTR, "vb_state");
+ allowList = getAllowedVbStates();
+ ASSERT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
+ allowList.end());
+ checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
+ allowList = getAllowedBootloaderStates();
+ ASSERT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
+ allowList.end());
+ checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
+ checkType(deviceInfo, cppbor::UINT, "system_patch_level");
+ checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
+ checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
+ checkType(deviceInfo, cppbor::UINT, "fused");
+ ASSERT_LT(deviceInfo->get("fused")->asUint()->value(), 2); // Must be 0 or 1.
+ checkType(deviceInfo, cppbor::TSTR, "security_level");
+ allowList = getAllowedSecurityLevels();
+ ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
+ allowList.end());
+ if (deviceInfo->get("security_level")->asTstr()->value() == "tee") {
+ checkType(deviceInfo, cppbor::TSTR, "os_version");
+ }
+ break;
+ case 1:
+ checkType(deviceInfo, cppbor::TSTR, "security_level");
+ allowList = getAllowedSecurityLevels();
+ ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
+ allowList.end());
+ if (version->asUint()->value() == 1) {
+ checkType(deviceInfo, cppbor::TSTR, "att_id_state");
+ allowList = getAllowedAttIdStates();
+ ASSERT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
+ allowList.end());
+ }
+ break;
+ default:
+ FAIL() << "Unrecognized version: " << version->asUint()->value();
+ }
+ ASSERT_EQ(deviceInfo->clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
+ << "DeviceInfo ordering is non-canonical.";
+ }
+
bytevec eekId_;
size_t testEekLength_;
EekChain testEekChain_;
@@ -406,6 +577,7 @@
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
+ generateTestEekChain(3);
auto status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
@@ -445,8 +617,8 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
- &protectedData, &keysToSignMac);
+ testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+ challenge_, &deviceInfo, &protectedData, &keysToSignMac);
EXPECT_TRUE(status.isOk());
}
@@ -486,8 +658,8 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
- &keysToSignMac);
+ testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
+ &deviceInfo, &protectedData, &keysToSignMac);
EXPECT_TRUE(status.isOk());
}
@@ -502,6 +674,7 @@
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
+ generateTestEekChain(3);
auto status = provisionable_->generateCertificateRequest(
testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
@@ -521,8 +694,8 @@
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
- testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
- &protectedData, &keysToSignMac);
+ testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+ challenge_, &deviceInfo, &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk()) << status.getMessage();
EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}
@@ -535,7 +708,7 @@
bool testMode = false;
generateKeys(testMode, 4 /* numKeys */);
- auto prodEekChain = getProdEekChain();
+ auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
ASSERT_NE(parsedChain, nullptr) << parseErr;
ASSERT_NE(parsedChain->asArray(), nullptr);
@@ -566,7 +739,7 @@
// Build an EEK chain that omits the first self-signed cert.
auto truncatedChain = cppbor::Array();
- auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
+ auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
ASSERT_TRUE(chain);
auto eekChain = chain->asArray();
ASSERT_NE(eekChain, nullptr);
@@ -594,6 +767,7 @@
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
+ generateTestEekChain(3);
auto status = provisionable_->generateCertificateRequest(
true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
@@ -612,6 +786,7 @@
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
+ generateTestEekChain(3);
auto status = provisionable_->generateCertificateRequest(
false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
&protectedData, &keysToSignMac);
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 36969bb..bf2ab02 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -60,11 +60,15 @@
export_include_dirs: [
"include",
],
+ defaults: [
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ ],
shared_libs: [
"libbase",
"libcppbor_external",
"libcppcose_rkp",
"libcrypto",
+ "libkeymaster_portable",
"libjsoncpp",
],
}
@@ -76,6 +80,9 @@
"libgmock",
"libgtest_main",
],
+ defaults: [
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ ],
shared_libs: [
"libbase",
"libcppbor_external",
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index 406b7a9..1d3abe5 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -52,6 +52,34 @@
0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2,
0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
+// The Google ECDSA P256 root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256RootCert[] = {
+ 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+ 0x58, 0x20, 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3,
+ 0x75, 0x1f, 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54,
+ 0xf2, 0xad, 0x22, 0x58, 0x20, 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13,
+ 0x37, 0xfd, 0x0f, 0xa1, 0xc8, 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77,
+ 0x86, 0xc3, 0x2d, 0xaf, 0x8f, 0x58, 0x40, 0x2f, 0x97, 0x8e, 0x42, 0xfb, 0xbe, 0x07, 0x2d, 0x95,
+ 0x47, 0x85, 0x47, 0x93, 0x40, 0xb0, 0x1f, 0xd4, 0x9b, 0x47, 0xa4, 0xc4, 0x44, 0xa9, 0xf2, 0xa1,
+ 0x07, 0x87, 0x10, 0xc7, 0x9f, 0xcb, 0x11, 0xf4, 0xbf, 0x9f, 0xe8, 0x3b, 0xe0, 0xe7, 0x34, 0x4c,
+ 0x15, 0xfc, 0x7b, 0xc3, 0x7e, 0x33, 0x05, 0xf4, 0xd1, 0x34, 0x3c, 0xed, 0x02, 0x04, 0x60, 0x7a,
+ 0x15, 0xe0, 0x79, 0xd3, 0x8a, 0xff, 0x24};
+
+// The Google ECDSA P256 Endpoint Encryption Key certificate, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = {
+ 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x71, 0xa6, 0x01, 0x02, 0x02, 0x58, 0x20, 0x35, 0x73,
+ 0xb7, 0x3f, 0xa0, 0x8a, 0x80, 0x89, 0xb1, 0x26, 0x67, 0xe9, 0xcb, 0x7c, 0x75, 0xa1, 0xaf, 0x02,
+ 0x61, 0xfc, 0x6e, 0x65, 0x03, 0x91, 0x3b, 0xd3, 0x4b, 0x7d, 0x14, 0x94, 0x3e, 0x46, 0x03, 0x38,
+ 0x18, 0x20, 0x01, 0x21, 0x58, 0x20, 0xe0, 0x41, 0xcf, 0x2f, 0x0f, 0x34, 0x0f, 0x1c, 0x33, 0x2c,
+ 0x41, 0xb0, 0xcf, 0xd7, 0x0c, 0x30, 0x55, 0x35, 0xd2, 0x1e, 0x6a, 0x47, 0x13, 0x4b, 0x2e, 0xd1,
+ 0x48, 0x96, 0x7e, 0x24, 0x9c, 0x68, 0x22, 0x58, 0x20, 0x1f, 0xce, 0x45, 0xc5, 0xfb, 0x61, 0xba,
+ 0x81, 0x21, 0xf9, 0xe5, 0x05, 0x9b, 0x9b, 0x39, 0x0e, 0x76, 0x86, 0x86, 0x47, 0xb8, 0x1e, 0x2f,
+ 0x45, 0xf1, 0xce, 0xaf, 0xda, 0x3f, 0x80, 0x68, 0xdb, 0x58, 0x40, 0x8c, 0xb3, 0xba, 0x7e, 0x20,
+ 0x3e, 0x32, 0xb0, 0x68, 0xdf, 0x60, 0xd1, 0x1d, 0x7d, 0xf0, 0xac, 0x38, 0x8e, 0x51, 0xbc, 0xff,
+ 0x6c, 0xe1, 0x67, 0x3b, 0x4a, 0x79, 0xbc, 0x56, 0x78, 0xb3, 0x99, 0xd8, 0x7c, 0x8a, 0x07, 0xd8,
+ 0xda, 0xb5, 0xb5, 0x7f, 0x71, 0xf4, 0xd8, 0x6b, 0xdf, 0x33, 0x27, 0x34, 0x7b, 0x65, 0xd1, 0x2a,
+ 0xeb, 0x86, 0x99, 0x98, 0xab, 0x3a, 0xb4, 0x80, 0xaa, 0xbd, 0x50};
+
/**
* Generates random bytes.
*/
@@ -64,15 +92,15 @@
};
/**
- * Generates an X25518 EEK with the specified eekId and an Ed25519 chain of the
- * specified length. All keys are generated randomly.
+ * Based on the supportedEekCurve, Generates an X25519/ECDH with the specified eekId
+ * and an Ed25519/ECDSA chain of the specified length. All keys are generated randomly.
*/
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId);
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length, const bytevec& eekId);
/**
* Returns the CBOR-encoded, production Google Endpoint Encryption Key chain.
*/
-bytevec getProdEekChain();
+bytevec getProdEekChain(int32_t supportedEekCurve);
struct BccEntryData {
bytevec pubKey;
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0cbee51..0776282 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -17,15 +17,186 @@
#include <iterator>
#include <tuple>
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
#include <android-base/properties.h>
#include <cppbor.h>
#include <json/json.h>
+#include <keymaster/km_openssl/ec_key.h>
+#include <keymaster/km_openssl/ecdsa_operation.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
#include <openssl/base64.h>
+#include <openssl/evp.h>
#include <openssl/rand.h>
#include <remote_prov/remote_prov_utils.h>
namespace aidl::android::hardware::security::keymint::remote_prov {
+constexpr uint32_t kBccPayloadIssuer = 1;
+constexpr uint32_t kBccPayloadSubject = 2;
+constexpr int32_t kBccPayloadSubjPubKey = -4670552;
+constexpr int32_t kBccPayloadKeyUsage = -4670553;
+constexpr int kP256AffinePointSize = 32;
+
+using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
+using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
+using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
+
+ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
+ // Extract private key.
+ const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
+ if (bignum == nullptr) {
+ return "Error getting bignum from private key";
+ }
+ // Pad with zeros in case the length is lesser than 32.
+ bytevec privKey(32, 0);
+ BN_bn2binpad(bignum, privKey.data(), privKey.size());
+ return privKey;
+}
+
+ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey) {
+ // Extract public key.
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ if (group.get() == nullptr) {
+ return "Error creating EC group by curve name";
+ }
+ const EC_POINT* point = EC_KEY_get0_public_key(ecKey);
+ if (point == nullptr) return "Error getting ecpoint from public key";
+
+ int size =
+ EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
+ if (size == 0) {
+ return "Error generating public key encoding";
+ }
+
+ bytevec publicKey;
+ publicKey.resize(size);
+ EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+ publicKey.size(), nullptr);
+ return publicKey;
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> getAffineCoordinates(const bytevec& pubKey) {
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ if (group.get() == nullptr) {
+ return "Error creating EC group by curve name";
+ }
+ auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+ if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), pubKey.size(), nullptr) != 1) {
+ return "Error decoding publicKey";
+ }
+ BIGNUM_Ptr x(BN_new());
+ BIGNUM_Ptr y(BN_new());
+ BN_CTX_Ptr ctx(BN_CTX_new());
+ if (!ctx.get()) return "Failed to create BN_CTX instance";
+
+ if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(),
+ ctx.get())) {
+ return "Failed to get affine coordinates from ECPoint";
+ }
+ bytevec pubX(kP256AffinePointSize);
+ bytevec pubY(kP256AffinePointSize);
+ if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+ return "Error in converting absolute value of x coordinate to big-endian";
+ }
+ if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+ return "Error in converting absolute value of y coordinate to big-endian";
+ }
+ return std::make_tuple(std::move(pubX), std::move(pubY));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
+ auto ec_key = EC_KEY_Ptr(EC_KEY_new());
+ if (ec_key.get() == nullptr) {
+ return "Failed to allocate ec key";
+ }
+
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ if (group.get() == nullptr) {
+ return "Error creating EC group by curve name";
+ }
+
+ if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+ EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+ return "Error generating key";
+ }
+
+ auto privKey = ecKeyGetPrivateKey(ec_key.get());
+ if (!privKey) return privKey.moveMessage();
+
+ auto pubKey = ecKeyGetPublicKey(ec_key.get());
+ if (!pubKey) return pubKey.moveMessage();
+
+ return std::make_tuple(pubKey.moveValue(), privKey.moveValue());
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateX25519KeyPair() {
+ /* Generate X25519 key pair */
+ bytevec pubKey(X25519_PUBLIC_VALUE_LEN);
+ bytevec privKey(X25519_PRIVATE_KEY_LEN);
+ X25519_keypair(pubKey.data(), privKey.data());
+ return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateED25519KeyPair() {
+ /* Generate ED25519 key pair */
+ bytevec pubKey(ED25519_PUBLIC_KEY_LEN);
+ bytevec privKey(ED25519_PRIVATE_KEY_LEN);
+ ED25519_keypair(pubKey.data(), privKey.data());
+ return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateKeyPair(int32_t supportedEekCurve, bool isEek) {
+ switch (supportedEekCurve) {
+ case RpcHardwareInfo::CURVE_25519:
+ if (isEek) {
+ return generateX25519KeyPair();
+ }
+ return generateED25519KeyPair();
+ case RpcHardwareInfo::CURVE_P256:
+ return generateEc256KeyPair();
+ default:
+ return "Unknown EEK Curve.";
+ }
+}
+
+ErrMsgOr<bytevec> constructCoseKey(int32_t supportedEekCurve, const bytevec& eekId,
+ const bytevec& pubKey) {
+ CoseKeyType keyType;
+ CoseKeyAlgorithm algorithm;
+ CoseKeyCurve curve;
+ bytevec pubX;
+ bytevec pubY;
+ switch (supportedEekCurve) {
+ case RpcHardwareInfo::CURVE_25519:
+ keyType = OCTET_KEY_PAIR;
+ algorithm = (eekId.empty()) ? EDDSA : ECDH_ES_HKDF_256;
+ curve = (eekId.empty()) ? ED25519 : cppcose::X25519;
+ pubX = pubKey;
+ break;
+ case RpcHardwareInfo::CURVE_P256: {
+ keyType = EC2;
+ algorithm = (eekId.empty()) ? ES256 : ECDH_ES_HKDF_256;
+ curve = P256;
+ auto affineCoordinates = getAffineCoordinates(pubKey);
+ if (!affineCoordinates) return affineCoordinates.moveMessage();
+ std::tie(pubX, pubY) = affineCoordinates.moveValue();
+ } break;
+ default:
+ return "Unknown EEK Curve.";
+ }
+ cppbor::Map coseKey = cppbor::Map()
+ .add(CoseKey::KEY_TYPE, keyType)
+ .add(CoseKey::ALGORITHM, algorithm)
+ .add(CoseKey::CURVE, curve)
+ .add(CoseKey::PUBKEY_X, pubX);
+
+ if (!pubY.empty()) coseKey.add(CoseKey::PUBKEY_Y, pubY);
+ if (!eekId.empty()) coseKey.add(CoseKey::KEY_ID, eekId);
+
+ return coseKey.canonicalize().encode();
+}
+
bytevec kTestMacKey(32 /* count */, 0 /* byte value */);
bytevec randomBytes(size_t numBytes) {
@@ -34,7 +205,17 @@
return retval;
}
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) {
+ErrMsgOr<cppbor::Array> constructCoseSign1(int32_t supportedEekCurve, const bytevec& key,
+ const bytevec& payload, const bytevec& aad) {
+ if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+ return constructECDSACoseSign1(key, {} /* protectedParams */, payload, aad);
+ } else {
+ return cppcose::constructCoseSign1(key, payload, aad);
+ }
+}
+
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length,
+ const bytevec& eekId) {
if (length < 2) {
return "EEK chain must contain at least 2 certs.";
}
@@ -43,59 +224,74 @@
bytevec prev_priv_key;
for (size_t i = 0; i < length - 1; ++i) {
- bytevec pub_key(ED25519_PUBLIC_KEY_LEN);
- bytevec priv_key(ED25519_PRIVATE_KEY_LEN);
-
- ED25519_keypair(pub_key.data(), priv_key.data());
+ auto keyPair = generateKeyPair(supportedEekCurve, false);
+ if (!keyPair) keyPair.moveMessage();
+ auto [pub_key, priv_key] = keyPair.moveValue();
// The first signing key is self-signed.
if (prev_priv_key.empty()) prev_priv_key = priv_key;
- auto coseSign1 = constructCoseSign1(prev_priv_key,
- cppbor::Map() /* payload CoseKey */
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::ALGORITHM, EDDSA)
- .add(CoseKey::CURVE, ED25519)
- .add(CoseKey::PUBKEY_X, pub_key)
- .canonicalize()
- .encode(),
- {} /* AAD */);
+ auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key);
+ if (!coseKey) return coseKey.moveMessage();
+
+ auto coseSign1 =
+ constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
if (!coseSign1) return coseSign1.moveMessage();
eekChain.add(coseSign1.moveValue());
prev_priv_key = priv_key;
}
+ auto keyPair = generateKeyPair(supportedEekCurve, true);
+ if (!keyPair) keyPair.moveMessage();
+ auto [pub_key, priv_key] = keyPair.moveValue();
- bytevec pub_key(X25519_PUBLIC_VALUE_LEN);
- bytevec priv_key(X25519_PRIVATE_KEY_LEN);
- X25519_keypair(pub_key.data(), priv_key.data());
+ auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key);
+ if (!coseKey) return coseKey.moveMessage();
- auto coseSign1 = constructCoseSign1(prev_priv_key,
- cppbor::Map() /* payload CoseKey */
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::KEY_ID, eekId)
- .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256)
- .add(CoseKey::CURVE, cppcose::X25519)
- .add(CoseKey::PUBKEY_X, pub_key)
- .canonicalize()
- .encode(),
- {} /* AAD */);
+ auto coseSign1 =
+ constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
if (!coseSign1) return coseSign1.moveMessage();
eekChain.add(coseSign1.moveValue());
+ if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+ // convert ec public key to x and y co-ordinates.
+ auto affineCoordinates = getAffineCoordinates(pub_key);
+ if (!affineCoordinates) return affineCoordinates.moveMessage();
+ auto [pubX, pubY] = affineCoordinates.moveValue();
+ pub_key.clear();
+ pub_key.insert(pub_key.begin(), pubX.begin(), pubX.end());
+ pub_key.insert(pub_key.end(), pubY.begin(), pubY.end());
+ }
+
return EekChain{eekChain.encode(), pub_key, priv_key};
}
-bytevec getProdEekChain() {
- bytevec prodEek;
- prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert));
+bytevec getProdEekChain(int32_t supportedEekCurve) {
+ cppbor::Array chain;
+ if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256RootCert),
+ std::end(kCoseEncodedEcdsa256RootCert))));
+ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256GeekCert),
+ std::end(kCoseEncodedEcdsa256GeekCert))));
+ } else {
+ chain.add(cppbor::EncodedItem(
+ bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
+ chain.add(cppbor::EncodedItem(
+ bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
+ }
+ return chain.encode();
+}
- // In CBOR encoding, 0x82 indicates an array of two items
- prodEek.push_back(0x82);
- prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert));
- prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert));
-
- return prodEek;
+ErrMsgOr<bytevec> validatePayloadAndFetchPubKey(const cppbor::Map* payload) {
+ const auto& issuer = payload->get(kBccPayloadIssuer);
+ if (!issuer || !issuer->asTstr()) return "Issuer is not present or not a tstr.";
+ const auto& subject = payload->get(kBccPayloadSubject);
+ if (!subject || !subject->asTstr()) return "Subject is not present or not a tstr.";
+ const auto& keyUsage = payload->get(kBccPayloadKeyUsage);
+ if (!keyUsage || !keyUsage->asBstr()) return "Key usage is not present or not a bstr.";
+ const auto& serializedKey = payload->get(kBccPayloadSubjPubKey);
+ if (!serializedKey || !serializedKey->asBstr()) return "Key is not present or not a bstr.";
+ return serializedKey->asBstr()->value();
}
ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1,
@@ -122,33 +318,53 @@
}
auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
- if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) {
+ if (!algorithm || !algorithm->asInt() ||
+ (algorithm->asInt()->value() != EDDSA && algorithm->asInt()->value() != ES256)) {
return "Unsupported signature algorithm";
}
- // TODO(jbires): Handle CWTs as the CoseSign1 payload in a less hacky way. Since the CWT payload
- // is extremely remote provisioning specific, probably just make a separate
- // function there.
auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(payload);
if (!parsedPayload) return payloadErrMsg + " when parsing key";
if (!parsedPayload->asMap()) return "CWT must be a map";
- auto serializedKey = parsedPayload->asMap()->get(-4670552)->clone();
- if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry";
-
- bool selfSigned = signingCoseKey.empty();
- auto key =
- CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey);
- if (!key) return "Bad signing key: " + key.moveMessage();
-
- bytevec signatureInput =
- cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
-
- if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
- key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
- return "Signature verification failed";
+ auto serializedKey = validatePayloadAndFetchPubKey(parsedPayload->asMap());
+ if (!serializedKey) {
+ return "CWT validation failed: " + serializedKey.moveMessage();
}
- return serializedKey->asBstr()->value();
+ bool selfSigned = signingCoseKey.empty();
+ bytevec signatureInput =
+ cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
+
+ if (algorithm->asInt()->value() == EDDSA) {
+ auto key = CoseKey::parseEd25519(selfSigned ? *serializedKey : signingCoseKey);
+
+ if (!key) return "Bad signing key: " + key.moveMessage();
+
+ if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
+ key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
+ return "Signature verification failed";
+ }
+ } else { // P256
+ auto key = CoseKey::parseP256(selfSigned ? *serializedKey : signingCoseKey);
+ if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() ||
+ key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) {
+ return "Bad signing key: " + key.moveMessage();
+ }
+ auto publicKey = key->getEcPublicKey();
+ if (!publicKey) return publicKey.moveMessage();
+
+ auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value());
+ if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage();
+
+ // convert public key to uncompressed form.
+ publicKey->insert(publicKey->begin(), 0x04);
+
+ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) {
+ return "Signature verification failed";
+ }
+ }
+
+ return serializedKey.moveValue();
}
ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc) {
@@ -156,8 +372,11 @@
std::vector<BccEntryData> result;
+ const auto& devicePubKey = bcc->get(0);
+ if (!devicePubKey->asMap()) return "Invalid device public key at the 1st entry in the BCC";
+
bytevec prevKey;
- // TODO(jbires): Actually process the pubKey at the start of the new bcc entry
+
for (size_t i = 1; i < bcc->size(); ++i) {
const cppbor::Array* entry = bcc->get(i)->asArray();
if (!entry || entry->size() != kCoseSign1EntryCount) {
@@ -177,6 +396,13 @@
// This entry's public key is the signing key for the next entry.
prevKey = payload.moveValue();
+ if (i == 1) {
+ auto [parsedRootKey, _, errMsg] = cppbor::parse(prevKey);
+ if (!parsedRootKey || !parsedRootKey->asMap()) return "Invalid payload entry in BCC.";
+ if (*parsedRootKey != *devicePubKey) {
+ return "Device public key doesn't match BCC root.";
+ }
+ }
}
return result;
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
index 8697c51..e1c4467 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -14,8 +14,12 @@
* limitations under the License.
*/
+#include "cppbor.h"
+#include "keymaster/cppcose/cppcose.h"
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
#include <android-base/properties.h>
#include <cppbor_parse.h>
+#include <cstdint>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <keymaster/android_keymaster_utils.h>
@@ -23,25 +27,120 @@
#include <keymaster/remote_provisioning_utils.h>
#include <openssl/curve25519.h>
#include <remote_prov/remote_prov_utils.h>
-#include <cstdint>
-#include "cppbor.h"
-#include "keymaster/cppcose/cppcose.h"
namespace aidl::android::hardware::security::keymint::remote_prov {
namespace {
using ::keymaster::KeymasterBlob;
-using ::keymaster::validateAndExtractEekPubAndId;
+using ::keymaster::kStatusFailed;
+using ::keymaster::kStatusInvalidEek;
+using ::keymaster::StatusOr;
using ::testing::ElementsAreArray;
+using byte_view = std::basic_string_view<uint8_t>;
+
+struct KeyInfoEcdsa {
+ CoseKeyCurve curve;
+ byte_view pubKeyX;
+ byte_view pubKeyY;
+
+ bool operator==(const KeyInfoEcdsa& other) const {
+ return curve == other.curve && pubKeyX == other.pubKeyX && pubKeyY == other.pubKeyY;
+ }
+};
+
+// The production root signing key for Google ECDSA P256 Endpoint Encryption Key cert chains.
+inline constexpr uint8_t kEcdsa256GeekRootX[] = {
+ 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3, 0x75, 0x1f,
+ 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54, 0xf2, 0xad};
+
+inline constexpr uint8_t kEcdsa256GeekRootY[] = {
+ 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13, 0x37, 0xfd, 0x0f, 0xa1, 0xc8,
+ 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77, 0x86, 0xc3, 0x2d, 0xaf, 0x8f};
+
+// Hard-coded set of acceptable public COSE_Keys that can act as roots of EEK chains.
+inline constexpr KeyInfoEcdsa kAuthorizedEcdsa256EekRoots[] = {
+ {CoseKeyCurve::P256, byte_view(kEcdsa256GeekRootX, sizeof(kEcdsa256GeekRootX)),
+ byte_view(kEcdsa256GeekRootY, sizeof(kEcdsa256GeekRootY))},
+};
+
+static ErrMsgOr<CoseKey> parseEcdh256(const bytevec& coseKey) {
+ auto key = CoseKey::parse(coseKey, EC2, ECDH_ES_HKDF_256, P256);
+ if (!key) return key;
+
+ auto& pubkey_x = key->getMap().get(cppcose::CoseKey::PUBKEY_X);
+ auto& pubkey_y = key->getMap().get(cppcose::CoseKey::PUBKEY_Y);
+ if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() ||
+ pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) {
+ return "Invalid P256 public key";
+ }
+
+ return key;
+}
+
+StatusOr<std::tuple<std::vector<uint8_t> /* EEK pubX */, std::vector<uint8_t> /* EEK pubY */,
+ std::vector<uint8_t> /* EEK ID */>>
+validateAndExtractEcdsa256EekPubAndId(bool testMode,
+ const KeymasterBlob& endpointEncryptionCertChain) {
+ auto [item, newPos, errMsg] =
+ cppbor::parse(endpointEncryptionCertChain.begin(), endpointEncryptionCertChain.end());
+ if (!item || !item->asArray()) {
+ return kStatusFailed;
+ }
+ const cppbor::Array* certArr = item->asArray();
+ std::vector<uint8_t> lastPubKey;
+ for (size_t i = 0; i < certArr->size(); ++i) {
+ auto cosePubKey =
+ verifyAndParseCoseSign1(certArr->get(i)->asArray(), lastPubKey, {} /* AAD */);
+ if (!cosePubKey) {
+ return kStatusInvalidEek;
+ }
+ lastPubKey = *std::move(cosePubKey);
+
+ // In prod mode the first pubkey should match a well-known Google public key.
+ if (!testMode && i == 0) {
+ auto parsedPubKey = CoseKey::parse(lastPubKey);
+ if (!parsedPubKey) {
+ return kStatusFailed;
+ }
+ auto curve = parsedPubKey->getIntValue(CoseKey::CURVE);
+ if (!curve) {
+ return kStatusInvalidEek;
+ }
+ auto rawPubX = parsedPubKey->getBstrValue(CoseKey::PUBKEY_X);
+ if (!rawPubX) {
+ return kStatusInvalidEek;
+ }
+ auto rawPubY = parsedPubKey->getBstrValue(CoseKey::PUBKEY_Y);
+ if (!rawPubY) {
+ return kStatusInvalidEek;
+ }
+ KeyInfoEcdsa matcher = {static_cast<CoseKeyCurve>(*curve),
+ byte_view(rawPubX->data(), rawPubX->size()),
+ byte_view(rawPubY->data(), rawPubY->size())};
+ if (std::find(std::begin(kAuthorizedEcdsa256EekRoots),
+ std::end(kAuthorizedEcdsa256EekRoots),
+ matcher) == std::end(kAuthorizedEcdsa256EekRoots)) {
+ return kStatusInvalidEek;
+ }
+ }
+ }
+ auto eek = parseEcdh256(lastPubKey);
+ if (!eek) {
+ return kStatusInvalidEek;
+ }
+ return std::make_tuple(eek->getBstrValue(CoseKey::PUBKEY_X).value(),
+ eek->getBstrValue(CoseKey::PUBKEY_Y).value(),
+ eek->getBstrValue(CoseKey::KEY_ID).value());
+}
TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) {
- ASSERT_FALSE(generateEekChain(1, /*eekId=*/{}));
+ ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_25519, 1, /*eekId=*/{}));
}
TEST(RemoteProvUtilsTest, GenerateEekChain) {
bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
for (size_t length : {2, 3, 31}) {
- auto get_eek_result = generateEekChain(length, kTestEekId);
+ auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_25519, length, kTestEekId);
ASSERT_TRUE(get_eek_result) << get_eek_result.message();
auto& [chain, pubkey, privkey] = *get_eek_result;
@@ -57,7 +156,7 @@
}
TEST(RemoteProvUtilsTest, GetProdEekChain) {
- auto chain = getProdEekChain();
+ auto chain = getProdEekChain(RpcHardwareInfo::CURVE_25519);
auto validation_result = validateAndExtractEekPubAndId(
/*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
@@ -97,5 +196,57 @@
ASSERT_EQ(json, expected);
}
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChainInvalidLength) {
+ ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_P256, 1, /*eekId=*/{}));
+}
+
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChain) {
+ bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
+ for (size_t length : {2, 3, 31}) {
+ auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_P256, length, kTestEekId);
+ ASSERT_TRUE(get_eek_result) << get_eek_result.message();
+
+ auto& [chain, pubkey, privkey] = *get_eek_result;
+
+ auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+ /*testMode=*/true, KeymasterBlob(chain.data(), chain.size()));
+ ASSERT_TRUE(validation_result.isOk());
+
+ auto& [eekPubX, eekPubY, eekId] = *validation_result;
+ bytevec eekPub;
+ eekPub.insert(eekPub.begin(), eekPubX.begin(), eekPubX.end());
+ eekPub.insert(eekPub.end(), eekPubY.begin(), eekPubY.end());
+ EXPECT_THAT(eekId, ElementsAreArray(kTestEekId));
+ EXPECT_THAT(eekPub, ElementsAreArray(pubkey));
+ }
+}
+
+TEST(RemoteProvUtilsTest, GetProdEcdsaEekChain) {
+ auto chain = getProdEekChain(RpcHardwareInfo::CURVE_P256);
+
+ auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+ /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
+ ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError();
+
+ auto& [eekPubX, eekPubY, eekId] = *validation_result;
+
+ auto [geekCert, ignoredNewPos, error] =
+ cppbor::parse(kCoseEncodedEcdsa256GeekCert, sizeof(kCoseEncodedEcdsa256GeekCert));
+ ASSERT_NE(geekCert, nullptr) << "Error: " << error;
+ ASSERT_NE(geekCert->asArray(), nullptr);
+
+ auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload);
+ ASSERT_NE(encodedGeekCoseKey, nullptr);
+ ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr);
+
+ auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value());
+ ASSERT_TRUE(geek) << "Error: " << geek.message();
+
+ const std::vector<uint8_t> empty;
+ EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty)));
+ EXPECT_THAT(eekPubX, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty)));
+ EXPECT_THAT(eekPubY, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_Y).value_or(empty)));
+}
+
} // namespace
} // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index 5235dd5..00a6ba3 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -17,7 +17,6 @@
backend: {
java: {
platform_apis: true,
- srcs_available: true,
},
ndk: {
vndk: {
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 9a92fb3..274cfa7 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
name: "VtsHalSensorsV1_0TargetTest",
cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "VtsHalSensorsV1_0TargetTest.cpp",
+ ],
srcs: [
"SensorsHidlEnvironmentV1_0.cpp",
"VtsHalSensorsV1_0TargetTest.cpp",
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index cf7c9fa..c4ec866 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
name: "VtsHalSensorsV2_0TargetTest",
cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "VtsHalSensorsV2_0TargetTest.cpp",
+ ],
srcs: [
"VtsHalSensorsV2_0TargetTest.cpp",
],
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 23c9803..fd701fd 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -59,10 +59,10 @@
}
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 (samplingPeriodNs < mSensorInfo.minDelay * 1000LL) {
+ samplingPeriodNs = mSensorInfo.minDelay * 1000LL;
+ } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000LL) {
+ samplingPeriodNs = mSensorInfo.maxDelay * 1000LL;
}
if (mSamplingPeriodNs != samplingPeriodNs) {
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index f5fc066..ccc4172 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -250,8 +250,8 @@
Result currRes = mSubHalList[i]->initialize(this, this, i);
if (currRes != Result::OK) {
result = currRes;
- ALOGE("Subhal '%s' failed to initialize.", mSubHalList[i]->getName().c_str());
- break;
+ ALOGE("Subhal '%s' failed to initialize with reason %" PRId32 ".",
+ mSubHalList[i]->getName().c_str(), static_cast<int32_t>(currRes));
}
}
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index d8e7ce6..21d1d77 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -99,6 +99,9 @@
cc_test {
name: "android.hardware.sensors@2.X-halproxy-unit-tests",
+ tidy_timeout_srcs: [
+ "HalProxy_test.cpp",
+ ],
srcs: [
"HalProxy_test.cpp",
"ScopedWakelock_test.cpp",
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index a63ffbc..f743ade 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -22,16 +22,26 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
+filegroup {
+ name: "android.hardware.thermal@2.0-service.xml",
+ srcs: ["android.hardware.thermal@2.0-service.xml"],
+}
+
+filegroup {
+ name: "android.hardware.thermal@2.0-service.rc",
+ srcs: ["android.hardware.thermal@2.0-service.rc"],
+}
+
cc_binary {
name: "android.hardware.thermal@2.0-service.mock",
defaults: ["hidl_defaults"],
relative_install_path: "hw",
vendor: true,
- init_rc: ["android.hardware.thermal@2.0-service.rc"],
- vintf_fragments: ["android.hardware.thermal@2.0-service.xml"],
+ init_rc: [":android.hardware.thermal@2.0-service.rc"],
+ vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
srcs: [
"Thermal.cpp",
- "service.cpp"
+ "service.cpp",
],
shared_libs: [
"libbase",
diff --git a/thermal/2.0/default/apex/Android.bp b/thermal/2.0/default/apex/Android.bp
new file mode 100644
index 0000000..914a3a8
--- /dev/null
+++ b/thermal/2.0/default/apex/Android.bp
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+ name: "com.android.hardware.thermal.key",
+ public_key: "com.android.hardware.thermal.avbpubkey",
+ private_key: "com.android.hardware.thermal.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.thermal.certificate",
+ certificate: "com.android.hardware.thermal",
+}
+
+genrule {
+ name: "com.android.hardware.thermal.rc-gen",
+ srcs: [":android.hardware.thermal@2.0-service.rc"],
+ out: ["com.android.hardware.thermal.rc"],
+ cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.thermal.mock/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "com.android.hardware.thermal.rc",
+ src: ":com.android.hardware.thermal.rc-gen",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.thermal.mock",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.thermal.key",
+ certificate: ":com.android.hardware.thermal.certificate",
+ use_vndk_as_stable: true,
+ updatable: false,
+ soc_specific: true,
+ binaries: ["android.hardware.thermal@2.0-service.mock"],
+ prebuilts: ["com.android.hardware.thermal.rc"],
+ vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
+}
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
new file mode 100644
index 0000000..8f7cf72
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
new file mode 100644
index 0000000..4ea6e85
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEApXL2prEKqnU/xHlYeZB55x5EOrVAsfBuyHN5xOgUY877UuDC
+xoX+DOYAkCDSwMPmBj/Q9E70lId1PXMeI3y0obgYpdFubqRsoGNcEq2zG811tr6J
+BAE/7mAI0a4VVFWtauBNTiP5G31hsRpZNTE/dyZxs20GEVQqdvtBlEAuebCt7VIb
+fCwXnPCXSiYQ9WyjU0dwHoZPuy02qBuq3v9NYt5J6lYiPDqTWmpYBFm+SIZvth/j
+HUcaU3p+BlUad0qLhA8HYTPPBwJq2uHbTXeFrWXngt+UPCdzYubyUjG4WmgHIfee
+zSvoTjud2Gaofnd4/PcE5jFTMYUJuz0D4E+8StZArw+xegfxGcvqFZ4gfKAO1Vha
+eQBhw94P2eieUfh9metQEyKZ+A24sxG0awtAUOgcwr/WNv2TgJoN8+56DhuPXOuO
+U2qeIZuIrmE5xmyzrzJsCx+5vRQA7A3kpxRo1ZCgbJlzMgdAQaRTe2rqxyyoeFQR
+HbxUdsM7ZwDLE62UlaTTZFoJ1wzvZmsIJdkdRg97zcc3R3kYnVehCxAZ1KdAKzq6
+bhrw/kNAVA0zUHhlhHWGDnJQ/rkGfjQ9GGhS51IJYgKEoQc5M9hSgZD3idic8hso
+63r/P2Wn4S78gwLigfpzsGD7RrusTbMIRkebwpHwAYpB8qIykrtUKfunLtMCAwEA
+AQKCAgEAjiKbv0ytaw9bfwD4f0cdUu5vkzgPok55/f8mh4ERs0UoKGUrL74BKTeX
+GDr6k9w4CvpcGuaRu+A7WlVBeR8zVxN/KUUo6CidoZR6jxlmm+YA0MQTlbs1Hyal
+rO0vKcqJNx4Hi6/f3Dv0519JcCck7Mm8OHbbFZwG9zyXdDNHOggNA6rcLer7Rjpy
+3qKhQxbXoT3oFnEwog8Pu5A5VWZjJyLswULKGo//81cU0nf+vvOvmPj/9jEVbs32
+4p3OJNmHziXTIzCNFOqAvhX2fzDFSNgY8hf9k0gZGshpOS+5vwFLz2SZqo2j/0G8
+MyLOcgdVi4zzSobpf8tZNuAOKnCVwxteV3Ddl0o+qAf4cQCAXtuEkJvFWpAxrX4m
+J7nDDuvcTjKMlnchlm6XxmP27YNTKA2w5uNfrJQV5LR3IDs77PFpNiKOwERka6MU
+WE1LnjAFTCDxujT29NfIjC9z0iOY45TYut4okesaK7woe6pfK2H0ouvE6mZ+Lb7Y
+qZphPb4e4DZZZAVoELVvWflm/VC/xmBMA9vtzpjuvRXD+iYjgxbHaiG2UANLWmTd
+vADLqBadlbp10AvyrjKxHUhAiZnJgaVKRXtw5qk8YrwZOwypEHCQjY41fJuRScWF
+pD58/PYOLtSdwewzTijXSVwwPeqL1JMdJ+KWFk5zI410DtmHwoECggEBANM5dHEj
+L4ZOCcgHVG7aCLah7f/0Za7BBiPsZFD0uRIzWFTd77st3v8ulMw1JQiO3+xmpL7e
+iOP+onuSEMKgNQqeX9WCnv6pL+mjg0of2IEcGnvCpmfUZRA2x/MlyJRrQ1vHGqkV
+oBIIWgCGmIAWuFbHPmkNYx7mAJymAfzShkVtMw29oiGYyubqx9cTjD0odeyScbhZ
+LuMt72O5QeNsPREX4SsSRAL+vZbz1+8iRI8Fon89csZym3hos3DA4QSml+FNHnLe
+YFD6AfU7pdn79YhhNkn4jE0BxLaEkXhMs8RRTU2Q3o990ZxrAZGQz4zqOm5sOIQT
+JaXFXxGvOwEysrMCggEBAMiFaTzkhJSLEmLEu0T3gNEC2d3jE9kt4Olv4mQmzD00
+AzDtkrkArLQCeG3CMn55oFcJRwr8gAEk7/f2mvJSoZQnw0J0tRI+QiHJG4zwdsQC
+UszqN89X8ef0yoobwVa31ZoWxK4/NvLO4GZQ6UUd9uni10jfYVWmwEwKBU61ihvT
+ntcZIXvROR6khxzLeXtglnsznnYcdYMPJUeN+cfK9/rL3V3jk1jes8y8XwYfxkUa
+99nEe1NkRCUznzKxvkRwnKunlMCEkZ5z4nNMlqEqiOlVEYgwKwNCP+qM7ZKUJg7t
+uOL91bqWFPj2qdzyUh0uP5V/dg2odnu0xSblKWhxI2ECggEBAKbZttJ8Idlsoath
+pt+d2c4yoadTLlNZ5HjSDfgpKFxpNLhtTCbGuGVJLX8V5/gXrGi4OCER9n5rMXx9
+SEIFfYCy1C77bI7rpI5hfJ88ArESOxVSEFLqYx7otw+p5AThqibAY533GCfGcxoB
+OEvOJrVd1D31tju9IfSb6ewFfM0w0mhjSMRTRswb39pUda4F3QkQMUaXJEOOkJBs
+0dBNOvvaqiJ03kajZa3tVsBuiEuV/uOV7ak29Pqrcjt6EQW0dzsgyRGh+eFda9iE
+0qEbt7uQVusdq+5UnEg09hhaNpK4SmEgM76Te9WcbXPIOTst9xQs5oPmABIvk8aL
+bgenPaMCggEAX9EAHIzFnYVm37NKGQZ7k2RdXt2nGlwF4QYJk/nGFmjILZUYSza7
+T7jueuQU5MKRj4VrYSCOuf1AfahlGe3KL9VgRF0oOPNu/l3uwEYXOkox7qDs0jMf
+8MrUDXJ9zEZD10GR8gFa7GNWbw2yqchLuC8g2D2FcTwhHzSanKW6vNk+SWJE0bmE
+JdRQi73e6smYnn5n9eBbdqjCE5MQDBw8qqbHvJmGSyz/lZFdhrugLl1YmcJ9e7ep
+qG0mYT71wBZfhtapCeVO//w39Qhf4dtFWNnBauY5Z3E8wYNd8nDATtnhQvYwLtyQ
+YPbc7CsOecsjrvgdHSGmnC4hFxjh1HpbgQKCAQBzEr35CFQpUfGsu06SqRrxp7mb
+BfQzLmqnt+ZLu21H/YjVbamMXNjbJFSdtFLxAK/s9vFGQzEWWEYia2pRZejlCXhQ
+RO+TREJ4rm4Erfdh+zS9z8MZlxe2ybIMs260XxjZ0gEltRtJ6P14zLBlChi/rQEY
+tGrOpfjvLc1Lryaucwj7snDLtMfyqvemAUmuJNn/6IEMuG4DcdtJ3Whh7t3xKfO0
+Hc71Oh7F30okQQ6Ctiwp1T77Y1EXlRJrUtpf1sLxeItP6/r3WXLNaiFdKqGJxiCM
+Gw11oUcBA9bvfAzeJIpVVbLtGPNOp4J1XpkgFcWzsTM+ZpxWwbj4yJL6rSN2
+-----END RSA PRIVATE KEY-----
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8 b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
new file mode 100644
index 0000000..3e5bf69
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
new file mode 100644
index 0000000..048e69a
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8UCFFWeg2KJX/fyAqZPcKaFS61/a3GiMA0GCSqGSIb3DQEBCwUAMIGp
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
+LmFuZHJvaWQuaGFyZHdhcmUudGhlcm1hbDAgFw0yMTExMTcxODE3MjRaGA80NzU5
+MTAxNDE4MTcyNFowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
+MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
+VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5oYXJkd2FyZS50aGVybWFsMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2W8QhCKX0WoS5jhIWbWBoKulD6XhKASA
+CL0oU6Uci0U6id2m++ou/T0aHSlliS9kT1NEABNwbLeTDa9h1qg1lbajRzXbvzEz
+EvZYT+dlgYFNZ9zaVCIlMapoiN+nrM/Rs24UBjJrZu1B39+IcE5ciQz69PgrLKWF
+vFEdYzxWI246azOVr3fvdelQg+CyPgiGObVAGOHhAidvsjg4FssKnADzn+JNlTt6
+b9P65xUQErut8hz9YdLtfZ096iwe8eEpsMOQwCNdKNXVCcNjQWkOwRaU+0awHoH1
+4mArvF7yyvJxqzkNaR03BPqXAHPIAPu6xdfA19+HVIiz6bLEZ1mfCM6edXByCWZu
+K8o54OZph71r15ncv4DVd+cnBjNvBvfdlJSeGjSreFkUo5NkfAwqdmLfZx6CedHI
+sLx7X8vPYolQnR4UEvaX6yeNN0gs8Dd6ePMqOEiwWFVASD+cbpcUrp09uzlDStGV
+1DPx/9J2kw8eXPMqOSGThkLWuUMUFojyh7bNlL16oYmEeZW6/OOXCOXzAQgJ7NIs
+DA1/H2w1HMHWgSfF4y+Es2CiqcgVFOIU/07b31Edw4v56pjx1CUpRpJZjDA1JJNo
+A4YCnpA6JWTxzUTmv21fEYyY+poA3CuzvCfZ80z9h/UFW98oM9GawGvK0i2pLudS
+RaZXWeil08cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAj2gpn/IpAHQLDlI52WwL
+IDc5uzlf1BGseLZ8M8uuMiwvN00nOjunQQZEIbhH7+03GYyMzRhTTI3nWwmX4Fnq
+vC5sR68yNlu9gOAMXaAHo/Rw73ak7sv8xGbb2FeQsHaMKDQ2nqxP17SWdQ0xWa1u
+5qNurPOdAPOw77noZcT7yYX7lcrOKxPIekPJxyeOlp4bQSmabSRgYr70B7GybPlv
+K1gkgCBxl5RiVjVxLo+7ESHSAaGLy0S7F2v6PJ9oj15TovWQ0py2iBKZ6HReB7s/
+umnQqkwXDLudlNmoXIsgIYn8vKFTYpy1GSNJqhRSLfvLR6NtuU0iCTvg/X7oPmS1
+dWUdjVeO7ZVvIpO3gLLEe4maBEYF2sOlt3bRmzIHydORJtkfTt5tiZ4wR9RfJbkj
+iBiDbNiX010bZPTAXmgMbuJzQXZEXCBy0qKeS1cHwf9M8FDoiLajXepfZIp+6syt
+D4lZk4eAV141JL5PfABfdZWwT3cTgFIqCYpqrMQJIu+GHEjUwD2yNPi0I1/ydFCW
+CPDnzWjYCi6yVB8hss3ZFbvhfyJzdm3LivNVbLGK0+TG0EOAz6d2aQ0UjESgMD1A
+U8hLzQt7MiFSG0bt2cVx6SgCHeYUqMntbFELEAURWrhAfPLMJtAvFgKbEiZEAkkW
+pdDVh603aIp4LjVCfTYp/mQ=
+-----END CERTIFICATE-----
diff --git a/thermal/2.0/default/apex/file_contexts b/thermal/2.0/default/apex/file_contexts
new file mode 100644
index 0000000..e0d87c7
--- /dev/null
+++ b/thermal/2.0/default/apex/file_contexts
@@ -0,0 +1,5 @@
+(/.*)? u:object_r:vendor_file:s0
+# Permission XMLs
+/etc/permissions(/.*)? u:object_r:vendor_configs_file:s0
+# binary
+/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_exec:s0
diff --git a/thermal/2.0/default/apex/manifest.json b/thermal/2.0/default/apex/manifest.json
new file mode 100644
index 0000000..ee44dc1
--- /dev/null
+++ b/thermal/2.0/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.thermal.mock",
+ "version": 1
+}
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
index f26c1af..29dffcb 100644
--- a/thermal/2.0/vts/functional/Android.bp
+++ b/thermal/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
cc_test {
name: "VtsHalThermalV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
static_libs: [
"android.hardware.thermal@1.0",
diff --git a/tv/Android.mk b/tv/Android.mk
new file mode 100644
index 0000000..d78614a
--- /dev/null
+++ b/tv/Android.mk
@@ -0,0 +1,2 @@
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_0.xml))
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_1.xml))
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index ba21189..599abfb 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -204,6 +204,7 @@
void DvrCallback::stopRecordThread() {
mKeepReadingRecordFMQ = false;
mRecordThreadRunning = false;
+ android::Mutex::Autolock autoLock(mRecordThreadLock);
}
AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
diff --git a/update-base-files.sh b/update-base-files.sh
index d01847d..bf7f6e4 100755
--- a/update-base-files.sh
+++ b/update-base-files.sh
@@ -45,8 +45,11 @@
-o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_common-base.h \
android.hardware.audio.common@7.0
hidl-gen $options \
- -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base.h \
+ -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.0.h \
android.hardware.audio@7.0
hidl-gen $options \
+ -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.1.h \
+ android.hardware.audio@7.1
+hidl-gen $options \
-o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_effect-base.h \
android.hardware.audio.effect@7.0
diff --git a/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
index 8402853..4c40bf8 100644
--- a/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
+++ b/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
@@ -178,6 +178,9 @@
Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
ALOGI("setCurrentUsbFunctions Adb");
+ if (!WriteStringToFile("1", DESC_USE_PATH))
+ return Status::ERROR;
+
if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
diff --git a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
index 8986556..fa50821 100644
--- a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
+++ b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
@@ -190,6 +190,9 @@
Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
ALOGI("setCurrentUsbFunctions Adb");
+ if (!WriteStringToFile("1", DESC_USE_PATH))
+ return Status::ERROR;
+
if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS
index ae10db6..3982c7b 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/aidl/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 345036
include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
chasewu@google.com
-leungv@google.com
+taikuo@google.com
diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp
index bd834d2..feba2c7 100644
--- a/vibrator/aidl/default/main.cpp
+++ b/vibrator/aidl/default/main.cpp
@@ -31,14 +31,14 @@
auto vib = ndk::SharedRefBase::make<Vibrator>();
const std::string vibName = std::string() + Vibrator::descriptor + "/default";
binder_status_t status = AServiceManager_addService(vib->asBinder().get(), vibName.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
// make the vibrator manager service with a different vibrator
auto managedVib = ndk::SharedRefBase::make<Vibrator>();
auto vibManager = ndk::SharedRefBase::make<VibratorManager>(std::move(managedVib));
const std::string vibManagerName = std::string() + VibratorManager::descriptor + "/default";
status = AServiceManager_addService(vibManager->asBinder().get(), vibManagerName.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index 3f328fa..1261870 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
+ tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
srcs: ["VtsHalVibratorTargetTest.cpp"],
shared_libs: [
"libbinder",
diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp
index 56d9c4d..6b77924 100644
--- a/weaver/aidl/default/Weaver.cpp
+++ b/weaver/aidl/default/Weaver.cpp
@@ -15,30 +15,52 @@
*/
#include "Weaver.h"
+#include <array>
namespace aidl {
namespace android {
namespace hardware {
namespace weaver {
+struct Slotinfo {
+ int slot_id;
+ std::vector<uint8_t> key;
+ std::vector<uint8_t> value;
+};
+
+std::array<struct Slotinfo, 16> slot_array;
// Methods from ::android::hardware::weaver::IWeaver follow.
::ndk::ScopedAStatus Weaver::getConfig(WeaverConfig* out_config) {
- (void)out_config;
+ *out_config = {16, 16, 16};
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector<uint8_t>& in_key, WeaverReadResponse* out_response) {
- (void)in_slotId;
- (void)in_key;
- (void)out_response;
+
+ if (in_slotId > 15 || in_key.size() > 16) {
+ *out_response = {0, {}};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_FAILED));
+ }
+
+ if (slot_array[in_slotId].key != in_key) {
+ *out_response = {0, {}};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_INCORRECT_KEY));
+ }
+
+ *out_response = {0, slot_array[in_slotId].value};
+
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus Weaver::write(int32_t in_slotId, const std::vector<uint8_t>& in_key, const std::vector<uint8_t>& in_value) {
- (void)in_slotId;
- (void)in_key;
- (void)in_value;
+
+ if (in_slotId > 15 || in_key.size() > 16 || in_value.size() > 16)
+ return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+
+ slot_array[in_slotId].key = in_key;
+ slot_array[in_slotId].value = in_value;
+
return ::ndk::ScopedAStatus::ok();
}
diff --git a/weaver/aidl/default/service.cpp b/weaver/aidl/default/service.cpp
index 1495bc9..2099ffd 100644
--- a/weaver/aidl/default/service.cpp
+++ b/weaver/aidl/default/service.cpp
@@ -28,7 +28,7 @@
const std::string instance = std::string() + Weaver::descriptor + "/default";
binder_status_t status = AServiceManager_addService(weaver->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
+ CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return -1; // Should never be reached
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 6c0ebf7..ebfa164 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -48,6 +48,9 @@
cc_test {
name: "VtsHalWifiV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "wifi_chip_hidl_test.cpp",
+ ],
srcs: [
"wifi_chip_hidl_test.cpp",
"wifi_p2p_iface_hidl_test.cpp",
diff --git a/wifi/1.5/default/Android.bp b/wifi/1.5/default/Android.bp
new file mode 100644
index 0000000..6333b6e
--- /dev/null
+++ b/wifi/1.5/default/Android.bp
@@ -0,0 +1,105 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+filegroup {
+ name: "android.hardware.wifi@1.0-service_srcs",
+ srcs: ["service.cpp"],
+}
+
+cc_defaults {
+ name: "android.hardware.wifi@1.0-service_default",
+ srcs: [":android.hardware.wifi@1.0-service_srcs"],
+ relative_install_path: "hw",
+ soc_specific: true,
+ shared_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-system-iface",
+ "libxml2",
+ ],
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+filegroup {
+ name: "android.hardware.wifi@1.0-service-lib_srcs",
+ srcs: [
+ "hidl_struct_util.cpp",
+ "hidl_sync_util.cpp",
+ "ringbuffer.cpp",
+ "wifi.cpp",
+ "wifi_ap_iface.cpp",
+ "wifi_chip.cpp",
+ "wifi_feature_flags.cpp",
+ "wifi_iface_util.cpp",
+ "wifi_legacy_hal.cpp",
+ "wifi_legacy_hal_factory.cpp",
+ "wifi_legacy_hal_stubs.cpp",
+ "wifi_mode_controller.cpp",
+ "wifi_nan_iface.cpp",
+ "wifi_p2p_iface.cpp",
+ "wifi_rtt_controller.cpp",
+ "wifi_sta_iface.cpp",
+ "wifi_status_util.cpp",
+ ],
+}
+
+cc_defaults {
+ name: "android.hardware.wifi@1.0-service-lib_defaults",
+ srcs: [":android.hardware.wifi@1.0-service-lib_srcs"],
+ relative_install_path: "hw",
+ soc_specific: true,
+ shared_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-system-iface",
+ "libxml2",
+ ],
+ // Generated by building android.hardware.wifi@1.0-service-lib and printing LOCAL_CPPFLAGS.
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-DWIFI_HIDL_FEATURE_DUAL_INTERFACE",
+ ],
+ export_include_dirs: ["."],
+ include_dirs: ["external/libxml2/include"],
+}
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
index b9f20a4..a85b242 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -131,8 +131,14 @@
WifiStatus wifi_status =
createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ LOG(INFO) << "Attempting to invoke onSubsystemRestart "
+ "callback";
if (!callback->onSubsystemRestart(wifi_status).isOk()) {
- LOG(ERROR) << "Failed to invoke onFailure callback";
+ LOG(ERROR)
+ << "Failed to invoke onSubsystemRestart callback";
+ } else {
+ LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
+ "callback";
}
}
};
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 82d794c..6bdff42 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -28,6 +28,8 @@
#include "wifi_chip.h"
#include "wifi_status_util.h"
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
namespace {
using android::sp;
using android::base::unique_fd;
@@ -126,8 +128,37 @@
}
std::string getPredefinedP2pIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName;
+ char p2pParentIfname[100];
+ std::string p2pDevIfName = "";
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.direct.interface", buffer.data(), "p2p0");
+ if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX,
+ strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+ /* Get the p2p parent interface name from p2p device interface name set
+ * in property */
+ strncpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
+ strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
+ if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(),
+ nullptr) == 0) {
+ return buffer.data();
+ }
+ /* Check if the parent interface derived from p2p device interface name
+ * is active */
+ if (strncmp(p2pParentIfname, primaryIfaceName.data(),
+ strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) !=
+ 0) {
+ /*
+ * Update the predefined p2p device interface parent interface name
+ * with current active wlan interface
+ */
+ p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
+ p2pDevIfName += primaryIfaceName.data();
+ LOG(INFO) << "update the p2p device interface name to "
+ << p2pDevIfName.c_str();
+ return p2pDevIfName;
+ }
+ }
return buffer.data();
}
diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp
index 6eceadf..78cd4af 100644
--- a/wifi/hostapd/1.3/vts/functional/Android.bp
+++ b/wifi/hostapd/1.3/vts/functional/Android.bp
@@ -26,6 +26,9 @@
cc_test {
name: "VtsHalWifiHostapdV1_3TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "hostapd_hidl_test.cpp",
+ ],
srcs: [
"hostapd_hidl_test.cpp",
],
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index 41c54b3..8f88196 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -431,6 +431,7 @@
EXPECT_TRUE(status.isOk());
}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdAidl);
INSTANTIATE_TEST_SUITE_P(
Hostapd, HostapdAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(IHostapd::descriptor)),
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index 121117c..2d86822 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -44,6 +44,9 @@
cc_test {
name: "VtsHalWifiSupplicantV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "supplicant_sta_network_hidl_test.cpp",
+ ],
srcs: [
"supplicant_hidl_test.cpp",
"supplicant_sta_iface_hidl_test.cpp",
@@ -71,6 +74,9 @@
cc_test {
name: "VtsHalWifiSupplicantP2pV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ tidy_timeout_srcs: [
+ "supplicant_p2p_iface_hidl_test.cpp",
+ ],
srcs: [
"VtsHalWifiSupplicantP2pV1_0TargetTest.cpp",
"supplicant_p2p_iface_hidl_test.cpp",
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 ac39a24..eabbf1b 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
@@ -38,12 +38,15 @@
: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
public:
virtual void SetUp() override {
+ // Stop Wi-Fi
+ ASSERT_TRUE(stopWifiFramework()); // stop & wait for wifi to shutdown.
+
wifi_instance_name_ = std::get<0>(GetParam());
supplicant_instance_name_ = std::get<1>(GetParam());
+ std::system("/system/bin/start");
+ ASSERT_TRUE(waitForFrameworkReady());
isP2pOn_ =
testing::deviceSupportsFeature("android.hardware.wifi.direct");
- // Stop Framework
- std::system("/system/bin/stop");
stopSupplicant(wifi_instance_name_);
startSupplicantAndWaitForHidlService(wifi_instance_name_,
supplicant_instance_name_);
@@ -53,8 +56,8 @@
virtual void TearDown() override {
stopSupplicant(wifi_instance_name_);
- // Start Framework
- std::system("/system/bin/start");
+ // Start Wi-Fi
+ startWifiFramework();
}
protected:
@@ -220,4 +223,4 @@
android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
ISupplicant::descriptor))),
- android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file
+ android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index be6aad9..086166a 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -48,37 +48,26 @@
using ::android::wifi_system::SupplicantManager;
namespace {
-
-// Helper function to initialize the driver and firmware to STA mode
-// using the vendor HAL HIDL interface.
-void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
- // Skip if wifi instance is not set.
- if (wifi_instance_name == "") {
- return;
+bool waitForSupplicantState(bool is_running) {
+ SupplicantManager supplicant_manager;
+ int count = 50; /* wait at most 5 seconds for completion */
+ while (count-- > 0) {
+ if (supplicant_manager.IsSupplicantRunning() == is_running) {
+ return true;
+ }
+ usleep(100000);
}
- if (getWifi(wifi_instance_name) != nullptr) {
- sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
- ChipModeId mode_id;
- EXPECT_TRUE(configureChipToSupportIfaceType(
- wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
- } else {
- LOG(WARNING) << __func__ << ": Vendor HAL not supported";
- }
+ LOG(ERROR) << "Supplicant not " << is_running ? "running" : "stopped";
+ return false;
}
-// Helper function to deinitialize the driver and firmware
-// using the vendor HAL HIDL interface.
-void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
- // Skip if wifi instance is not set.
- if (wifi_instance_name == "") {
- return;
- }
- if (getWifi(wifi_instance_name) != nullptr) {
- stopWifi(wifi_instance_name);
- } else {
- LOG(WARNING) << __func__ << ": Vendor HAL not supported";
- }
-}
+// Helper function to wait for supplicant to be started by framework on wifi
+// enable.
+bool waitForSupplicantStart() { return waitForSupplicantState(true); }
+
+// Helper function to wait for supplicant to be stopped by framework on wifi
+// disable.
+bool waitForSupplicantStop() { return waitForSupplicantState(false); }
// Helper function to find any iface of the desired type exposed.
bool findIfaceOfType(sp<ISupplicant> supplicant, IfaceType desired_type,
@@ -118,20 +107,64 @@
}
} // namespace
+bool startWifiFramework() {
+ std::system("svc wifi enable");
+ std::system("cmd wifi set-scan-always-available enabled");
+ return waitForSupplicantStart(); // wait for wifi to start.
+}
+
+bool stopWifiFramework() {
+ std::system("svc wifi disable");
+ std::system("cmd wifi set-scan-always-available disabled");
+ return waitForSupplicantStop(); // wait for wifi to shutdown.
+}
+
void stopSupplicant() { stopSupplicant(""); }
void stopSupplicant(const std::string& wifi_instance_name) {
SupplicantManager supplicant_manager;
ASSERT_TRUE(supplicant_manager.StopSupplicant());
- deInitilializeDriverAndFirmware(wifi_instance_name);
+ deInitializeDriverAndFirmware(wifi_instance_name);
ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
}
+// Helper function to initialize the driver and firmware to STA mode
+// using the vendor HAL HIDL interface.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name) {
+ // Skip if wifi instance is not set.
+ if (wifi_instance_name == "") {
+ return;
+ }
+ if (getWifi(wifi_instance_name) != nullptr) {
+ sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+ ChipModeId mode_id;
+ EXPECT_TRUE(configureChipToSupportIfaceType(
+ wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA,
+ &mode_id));
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
+}
+
+// Helper function to deinitialize the driver and firmware
+// using the vendor HAL HIDL interface.
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name) {
+ // Skip if wifi instance is not set.
+ if (wifi_instance_name == "") {
+ return;
+ }
+ if (getWifi(wifi_instance_name) != nullptr) {
+ stopWifi(wifi_instance_name);
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
+}
+
void startSupplicantAndWaitForHidlService(
const std::string& wifi_instance_name,
const std::string& supplicant_instance_name) {
- initilializeDriverAndFirmware(wifi_instance_name);
+ initializeDriverAndFirmware(wifi_instance_name);
SupplicantManager supplicant_manager;
ASSERT_TRUE(supplicant_manager.StartSupplicant());
@@ -285,7 +318,7 @@
}
bool waitForFrameworkReady() {
- int waitCount = 10;
+ int waitCount = 15;
do {
// Check whether package service is ready or not.
if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
index 33945cc..7228623 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
@@ -29,9 +29,11 @@
#include "wifi_hidl_test_utils.h"
+// Used to start the android wifi framework after every test.
+bool startWifiFramework();
+
// Used to stop the android wifi framework before every test.
-void stopWifiFramework(const std::string& wifi_instance_name);
-void startWifiFramework(const std::string& wifi_instance_name);
+bool stopWifiFramework();
void stopSupplicant(const std::string& wifi_instance_name);
// Used to configure the chip, driver and start wpa_supplicant before every
@@ -40,6 +42,11 @@
const std::string& wifi_instance_name,
const std::string& supplicant_instance_name);
+// Used to initialize/deinitialize the driver and firmware at the
+// beginning and end of each test.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name);
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name);
+
// Helper functions to obtain references to the various HIDL interface objects.
// Note: We only have a single instance of each of these objects currently.
// These helper functions should be modified to return vectors if we support
@@ -70,16 +77,16 @@
: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
public:
virtual void SetUp() override {
+ // Stop Wi-Fi
+ ASSERT_TRUE(stopWifiFramework()); // stop & wait for wifi to shutdown.
+
// should always be v1.0 wifi
wifi_v1_0_instance_name_ = std::get<0>(GetParam());
supplicant_instance_name_ = std::get<1>(GetParam());
std::system("/system/bin/start");
ASSERT_TRUE(waitForFrameworkReady());
-
isP2pOn_ =
testing::deviceSupportsFeature("android.hardware.wifi.direct");
- // Stop Framework
- std::system("/system/bin/stop");
stopSupplicant(wifi_v1_0_instance_name_);
startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_,
supplicant_instance_name_);
@@ -88,8 +95,8 @@
virtual void TearDown() override {
stopSupplicant(wifi_v1_0_instance_name_);
- // Start Framework
- std::system("/system/bin/start");
+ // Start Wi-Fi
+ startWifiFramework();
}
protected:
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
deleted file mode 100644
index 287152d..0000000
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 33618
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/supplicant/1.3/vts/functional/Android.bp b/wifi/supplicant/1.3/vts/functional/Android.bp
index ec25de2..4b56336 100644
--- a/wifi/supplicant/1.3/vts/functional/Android.bp
+++ b/wifi/supplicant/1.3/vts/functional/Android.bp
@@ -74,5 +74,4 @@
"general-tests",
"vts",
],
- disable_framework: true,
}
diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp
index 8cbe04f..57ee830 100644
--- a/wifi/supplicant/1.4/vts/functional/Android.bp
+++ b/wifi/supplicant/1.4/vts/functional/Android.bp
@@ -77,7 +77,6 @@
"general-tests",
"vts",
],
- disable_framework: true,
}
cc_test {
@@ -108,5 +107,4 @@
"general-tests",
"vts",
],
- disable_framework: true,
}
diff --git a/wifi/supplicant/OWNERS b/wifi/supplicant/OWNERS
new file mode 100644
index 0000000..7febd60
--- /dev/null
+++ b/wifi/supplicant/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 33618
+arabawy@google.com
+etancohen@google.com
+gbiren@google.com
+lzye@google.com
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
new file mode 100644
index 0000000..d00dd21
--- /dev/null
+++ b/wifi/supplicant/aidl/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.wifi.supplicant",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/wifi/supplicant/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.wifi",
+ ],
+ min_sdk_version: "30",
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl
new file mode 100644
index 0000000..d8e49d7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable AnqpData {
+ byte[] venueName;
+ byte[] roamingConsortium;
+ byte[] ipAddrTypeAvailability;
+ byte[] naiRealm;
+ byte[] anqp3gppCellularNetwork;
+ byte[] domainName;
+ byte[] venueUrl;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl
new file mode 100644
index 0000000..cc32360
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum AnqpInfoId {
+ VENUE_NAME = 258,
+ ROAMING_CONSORTIUM = 261,
+ IP_ADDR_TYPE_AVAILABILITY = 262,
+ NAI_REALM = 263,
+ ANQP_3GPP_CELLULAR_NETWORK = 264,
+ DOMAIN_NAME = 268,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
new file mode 100644
index 0000000..f6830dc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable AssociationRejectionData {
+ byte[] ssid;
+ byte[] bssid;
+ android.hardware.wifi.supplicant.StaIfaceStatusCode statusCode;
+ boolean timedOut;
+ boolean isMboAssocDisallowedReasonCodePresent;
+ android.hardware.wifi.supplicant.MboAssocDisallowedReasonCode mboAssocDisallowedReason;
+ boolean isOceRssiBasedAssocRejectAttrPresent;
+ android.hardware.wifi.supplicant.OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl
new file mode 100644
index 0000000..9cd178d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum AuthAlgMask {
+ OPEN = 1,
+ SHARED = 2,
+ LEAP = 4,
+ SAE = 16,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl
new file mode 100644
index 0000000..34d894d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable BssTmData {
+ android.hardware.wifi.supplicant.BssTmStatusCode status;
+ android.hardware.wifi.supplicant.BssTmDataFlagsMask flags;
+ int assocRetryDelayMs;
+ android.hardware.wifi.supplicant.MboTransitionReasonCode mboTransitionReason;
+ android.hardware.wifi.supplicant.MboCellularDataConnectionPrefValue mboCellPreference;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
new file mode 100644
index 0000000..f215f05
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum BssTmDataFlagsMask {
+ WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED = 1,
+ WNM_MODE_ABRIDGED = 2,
+ WNM_MODE_DISASSOCIATION_IMMINENT = 4,
+ WNM_MODE_BSS_TERMINATION_INCLUDED = 8,
+ WNM_MODE_ESS_DISASSOCIATION_IMMINENT = 16,
+ MBO_TRANSITION_REASON_CODE_INCLUDED = 32,
+ MBO_ASSOC_RETRY_DELAY_INCLUDED = 64,
+ MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED = 128,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
new file mode 100644
index 0000000..c95825f
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BssTmStatusCode {
+ ACCEPT = 0,
+ REJECT_UNSPECIFIED = 1,
+ REJECT_INSUFFICIENT_BEACON = 2,
+ REJECT_INSUFFICIENT_CAPABITY = 3,
+ REJECT_BSS_TERMINATION_UNDESIRED = 4,
+ REJECT_BSS_TERMINATION_DELAY_REQUEST = 5,
+ REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
+ REJECT_NO_SUITABLE_CANDIDATES = 7,
+ REJECT_LEAVING_ESS = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl
new file mode 100644
index 0000000..1d24579
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BssidChangeReason {
+ ASSOC_START = 0,
+ ASSOC_COMPLETE = 1,
+ DISASSOC = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
new file mode 100644
index 0000000..bdc1b4a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BtCoexistenceMode {
+ ENABLED = 0,
+ DISABLED = 1,
+ SENSE = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
new file mode 100644
index 0000000..433b3d80
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable ConnectionCapabilities {
+ android.hardware.wifi.supplicant.WifiTechnology technology;
+ int channelBandwidth;
+ int maxNumberTxSpatialStreams;
+ int maxNumberRxSpatialStreams;
+ android.hardware.wifi.supplicant.LegacyMode legacyMode;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl
new file mode 100644
index 0000000..fbfb5b3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DebugLevel {
+ EXCESSIVE = 0,
+ MSGDUMP = 1,
+ DEBUG = 2,
+ INFO = 3,
+ WARNING = 4,
+ ERROR = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl
new file mode 100644
index 0000000..df2aef8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppAkm {
+ PSK = 0,
+ PSK_SAE = 1,
+ SAE = 2,
+ DPP = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl
new file mode 100644
index 0000000..e69da44
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppCurve {
+ PRIME256V1 = 0,
+ SECP384R1 = 1,
+ SECP521R1 = 2,
+ BRAINPOOLP256R1 = 3,
+ BRAINPOOLP384R1 = 4,
+ BRAINPOOLP512R1 = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl
new file mode 100644
index 0000000..9e394fc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppEventType {
+ CONFIGURATION_SENT = 0,
+ CONFIGURATION_APPLIED = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl
new file mode 100644
index 0000000..7e7c806
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppFailureCode {
+ INVALID_URI = 0,
+ AUTHENTICATION = 1,
+ NOT_COMPATIBLE = 2,
+ CONFIGURATION = 3,
+ BUSY = 4,
+ TIMEOUT = 5,
+ FAILURE = 6,
+ NOT_SUPPORTED = 7,
+ CONFIGURATION_REJECTED = 8,
+ CANNOT_FIND_NETWORK = 9,
+ ENROLLEE_AUTHENTICATION = 10,
+ URI_GENERATION = 11,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl
new file mode 100644
index 0000000..c6d3522
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppNetRole {
+ STA = 0,
+ AP = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl
new file mode 100644
index 0000000..f0618a5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppProgressCode {
+ AUTHENTICATION_SUCCESS = 0,
+ RESPONSE_PENDING = 1,
+ CONFIGURATION_SENT_WAITING_RESPONSE = 2,
+ CONFIGURATION_ACCEPTED = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
new file mode 100644
index 0000000..8b6492b
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable DppResponderBootstrapInfo {
+ int bootstrapId;
+ int listenChannel;
+ String uri;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl
new file mode 100644
index 0000000..2cf81d9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapErrorCode {
+ SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+ SIM_TEMPORARILY_DENIED = 1026,
+ SIM_NOT_SUBSCRIBED = 1031,
+ SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+ SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl
new file mode 100644
index 0000000..4ab23af
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapMethod {
+ PEAP = 0,
+ TLS = 1,
+ TTLS = 2,
+ PWD = 3,
+ SIM = 4,
+ AKA = 5,
+ AKA_PRIME = 6,
+ WFA_UNAUTH_TLS = 7,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl
new file mode 100644
index 0000000..4bd93a0
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapPhase2Method {
+ NONE = 0,
+ PAP = 1,
+ MSPAP = 2,
+ MSPAPV2 = 3,
+ GTC = 4,
+ SIM = 5,
+ AKA = 6,
+ AKA_PRIME = 7,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
new file mode 100644
index 0000000..cbf1a3e
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum ExtRadioWorkDefaults {
+ TIMEOUT_IN_SECS = 10,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl
new file mode 100644
index 0000000..0971d51
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable FreqRange {
+ int min;
+ int max;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl
new file mode 100644
index 0000000..f2da925
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum GroupCipherMask {
+ WEP40 = 2,
+ WEP104 = 4,
+ TKIP = 8,
+ CCMP = 16,
+ GTK_NOT_USED = 16384,
+ GCMP_256 = 256,
+ SMS4 = 128,
+ GCMP_128 = 64,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
new file mode 100644
index 0000000..c24d6cc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum GroupMgmtCipherMask {
+ BIP_GMAC_128 = 2048,
+ BIP_GMAC_256 = 4096,
+ BIP_CMAC_256 = 8192,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl
new file mode 100644
index 0000000..599a683
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable GsmRand {
+ byte[] data;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
new file mode 100644
index 0000000..43b182a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable Hs20AnqpData {
+ byte[] operatorFriendlyName;
+ byte[] wanMetrics;
+ byte[] connectionCapability;
+ byte[] osuProvidersList;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
new file mode 100644
index 0000000..270d43b
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum Hs20AnqpSubtypes {
+ OPERATOR_FRIENDLY_NAME = 3,
+ WAN_METRICS = 4,
+ CONNECTION_CAPABILITY = 5,
+ OSU_PROVIDERS_LIST = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
new file mode 100644
index 0000000..4b26ac3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicant {
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface addP2pInterface(in String ifName);
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface addStaInterface(in String ifName);
+ android.hardware.wifi.supplicant.DebugLevel getDebugLevel();
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface getP2pInterface(in String ifName);
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface getStaInterface(in String ifName);
+ boolean isDebugShowKeysEnabled();
+ boolean isDebugShowTimestampEnabled();
+ android.hardware.wifi.supplicant.IfaceInfo[] listInterfaces();
+ void registerCallback(in android.hardware.wifi.supplicant.ISupplicantCallback callback);
+ void removeInterface(in android.hardware.wifi.supplicant.IfaceInfo ifaceInfo);
+ void setConcurrencyPriority(in android.hardware.wifi.supplicant.IfaceType type);
+ void setDebugParams(in android.hardware.wifi.supplicant.DebugLevel level, in boolean showTimestamp, in boolean showKeys);
+ oneway void terminate();
+ const int EXT_RADIO_WORK_TIMEOUT_IN_SECS = 10;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
new file mode 100644
index 0000000..72ab3b9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantCallback {
+ oneway void onInterfaceCreated(in String ifaceName);
+ oneway void onInterfaceRemoved(in String ifaceName);
+ oneway void onTerminating();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
new file mode 100644
index 0000000..7876d86
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pIface {
+ void addBonjourService(in byte[] query, in byte[] response);
+ void addGroup(in boolean persistent, in int persistentNetworkId);
+ void addGroupWithConfig(in byte[] ssid, in String pskPassphrase, in boolean persistent, in int freq, in byte[] peerAddress, in boolean joinExistingGroup);
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork addNetwork();
+ void addUpnpService(in int version, in String serviceName);
+ void cancelConnect();
+ void cancelServiceDiscovery(in long identifier);
+ void cancelWps(in String groupIfName);
+ void configureExtListen(in int periodInMillis, in int intervalInMillis);
+ String connect(in byte[] peerAddress, in android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod, in String preSelectedPin, in boolean joinExistingGroup, in boolean persistent, in int goIntent);
+ byte[] createNfcHandoverRequestMessage();
+ byte[] createNfcHandoverSelectMessage();
+ void enableWfd(in boolean enable);
+ void find(in int timeoutInSec);
+ void flush();
+ void flushServices();
+ byte[] getDeviceAddress();
+ boolean getEdmg();
+ android.hardware.wifi.supplicant.P2pGroupCapabilityMask getGroupCapability(in byte[] peerAddress);
+ String getName();
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork getNetwork(in int id);
+ byte[] getSsid(in byte[] peerAddress);
+ android.hardware.wifi.supplicant.IfaceType getType();
+ void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress);
+ int[] listNetworks();
+ void provisionDiscovery(in byte[] peerAddress, in android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod);
+ void registerCallback(in android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback callback);
+ void reinvoke(in int persistentNetworkId, in byte[] peerAddress);
+ void reject(in byte[] peerAddress);
+ void removeBonjourService(in byte[] query);
+ void removeGroup(in String groupIfName);
+ void removeNetwork(in int id);
+ void removeUpnpService(in int version, in String serviceName);
+ void reportNfcHandoverInitiation(in byte[] select);
+ void reportNfcHandoverResponse(in byte[] request);
+ long requestServiceDiscovery(in byte[] peerAddress, in byte[] query);
+ void saveConfig();
+ void setDisallowedFrequencies(in android.hardware.wifi.supplicant.FreqRange[] ranges);
+ void setEdmg(in boolean enable);
+ void setGroupIdle(in String groupIfName, in int timeoutInSec);
+ void setListenChannel(in int channel, in int operatingClass);
+ void setMacRandomization(in boolean enable);
+ void setMiracastMode(in android.hardware.wifi.supplicant.MiracastMode mode);
+ void setPowerSave(in String groupIfName, in boolean enable);
+ void setSsidPostfix(in byte[] postfix);
+ void setWfdDeviceInfo(in byte[] info);
+ void setWfdR2DeviceInfo(in byte[] info);
+ void setWpsConfigMethods(in android.hardware.wifi.supplicant.WpsConfigMethods configMethods);
+ void setWpsDeviceName(in String name);
+ void setWpsDeviceType(in byte[] type);
+ void setWpsManufacturer(in String manufacturer);
+ void setWpsModelName(in String modelName);
+ void setWpsModelNumber(in String modelNumber);
+ void setWpsSerialNumber(in String serialNumber);
+ void startWpsPbc(in String groupIfName, in byte[] bssid);
+ String startWpsPinDisplay(in String groupIfName, in byte[] bssid);
+ void startWpsPinKeypad(in String groupIfName, in String pin);
+ void stopFind();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
new file mode 100644
index 0000000..ed435e2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pIfaceCallback {
+ oneway void onDeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress, in byte[] primaryDeviceType, in String deviceName, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in byte deviceCapabilities, in android.hardware.wifi.supplicant.P2pGroupCapabilityMask groupCapabilities, in byte[] wfdDeviceInfo);
+ oneway void onDeviceLost(in byte[] p2pDeviceAddress);
+ oneway void onFindStopped();
+ oneway void onGoNegotiationCompleted(in android.hardware.wifi.supplicant.P2pStatusCode status);
+ oneway void onGoNegotiationRequest(in byte[] srcAddress, in android.hardware.wifi.supplicant.WpsDevPasswordId passwordId);
+ oneway void onGroupFormationFailure(in String failureReason);
+ oneway void onGroupFormationSuccess();
+ oneway void onGroupRemoved(in String groupIfname, in boolean isGroupOwner);
+ oneway void onGroupStarted(in String groupIfname, in boolean isGroupOwner, in byte[] ssid, in int frequency, in byte[] psk, in String passphrase, in byte[] goDeviceAddress, in boolean isPersistent);
+ oneway void onInvitationReceived(in byte[] srcAddress, in byte[] goDeviceAddress, in byte[] bssid, in int persistentNetworkId, in int operatingFrequency);
+ oneway void onInvitationResult(in byte[] bssid, in android.hardware.wifi.supplicant.P2pStatusCode status);
+ oneway void onProvisionDiscoveryCompleted(in byte[] p2pDeviceAddress, in boolean isRequest, in android.hardware.wifi.supplicant.P2pProvDiscStatusCode status, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in String generatedPin);
+ oneway void onR2DeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress, in byte[] primaryDeviceType, in String deviceName, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in byte deviceCapabilities, in android.hardware.wifi.supplicant.P2pGroupCapabilityMask groupCapabilities, in byte[] wfdDeviceInfo, in byte[] wfdR2DeviceInfo);
+ oneway void onServiceDiscoveryResponse(in byte[] srcAddress, in char updateIndicator, in byte[] tlvs);
+ oneway void onStaAuthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+ oneway void onStaDeauthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
new file mode 100644
index 0000000..ef72724
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pNetwork {
+ byte[] getBssid();
+ android.hardware.wifi.supplicant.MacAddress[] getClientList();
+ int getId();
+ String getInterfaceName();
+ byte[] getSsid();
+ android.hardware.wifi.supplicant.IfaceType getType();
+ boolean isCurrent();
+ boolean isGroupOwner();
+ boolean isPersistent();
+ void setClientList(in android.hardware.wifi.supplicant.MacAddress[] clients);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
new file mode 100644
index 0000000..20c52ac
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaIface {
+ int addDppPeerUri(in String uri);
+ int addExtRadioWork(in String name, in int freqInMhz, in int timeoutInSec);
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork addNetwork();
+ void addRxFilter(in android.hardware.wifi.supplicant.RxFilterType type);
+ void cancelWps();
+ void disconnect();
+ void enableAutoReconnect(in boolean enable);
+ void filsHlpAddRequest(in byte[] dst_mac, in byte[] pkt);
+ void filsHlpFlushRequest();
+ android.hardware.wifi.supplicant.DppResponderBootstrapInfo generateDppBootstrapInfoForResponder(in byte[] macAddress, in String deviceInfo, in android.hardware.wifi.supplicant.DppCurve curve);
+ android.hardware.wifi.supplicant.ConnectionCapabilities getConnectionCapabilities();
+ android.hardware.wifi.supplicant.KeyMgmtMask getKeyMgmtCapabilities();
+ byte[] getMacAddress();
+ String getName();
+ @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork getNetwork(in int id);
+ android.hardware.wifi.supplicant.IfaceType getType();
+ android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask getWpaDriverCapabilities();
+ void initiateAnqpQuery(in byte[] macAddress, in android.hardware.wifi.supplicant.AnqpInfoId[] infoElements, in android.hardware.wifi.supplicant.Hs20AnqpSubtypes[] subTypes);
+ void initiateHs20IconQuery(in byte[] macAddress, in String fileName);
+ void initiateTdlsDiscover(in byte[] macAddress);
+ void initiateTdlsSetup(in byte[] macAddress);
+ void initiateTdlsTeardown(in byte[] macAddress);
+ void initiateVenueUrlAnqpQuery(in byte[] macAddress);
+ int[] listNetworks();
+ void reassociate();
+ void reconnect();
+ void registerCallback(in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback callback);
+ void removeDppUri(in int id);
+ void removeExtRadioWork(in int id);
+ void removeNetwork(in int id);
+ void removeRxFilter(in android.hardware.wifi.supplicant.RxFilterType type);
+ void setBtCoexistenceMode(in android.hardware.wifi.supplicant.BtCoexistenceMode mode);
+ void setBtCoexistenceScanModeEnabled(in boolean enable);
+ void setCountryCode(in byte[] code);
+ void setExternalSim(in boolean useExternalSim);
+ void setMboCellularDataStatus(in boolean available);
+ void setPowerSave(in boolean enable);
+ void setSuspendModeEnabled(in boolean enable);
+ void setWpsConfigMethods(in android.hardware.wifi.supplicant.WpsConfigMethods configMethods);
+ void setWpsDeviceName(in String name);
+ void setWpsDeviceType(in byte[] type);
+ void setWpsManufacturer(in String manufacturer);
+ void setWpsModelName(in String modelName);
+ void setWpsModelNumber(in String modelNumber);
+ void setWpsSerialNumber(in String serialNumber);
+ void startDppConfiguratorInitiator(in int peerBootstrapId, in int ownBootstrapId, in String ssid, in String password, in String psk, in android.hardware.wifi.supplicant.DppNetRole netRole, in android.hardware.wifi.supplicant.DppAkm securityAkm);
+ void startDppEnrolleeInitiator(in int peerBootstrapId, in int ownBootstrapId);
+ void startDppEnrolleeResponder(in int listenChannel);
+ void startRxFilter();
+ void startWpsPbc(in byte[] bssid);
+ String startWpsPinDisplay(in byte[] bssid);
+ void startWpsPinKeypad(in String pin);
+ void startWpsRegistrar(in byte[] bssid, in String pin);
+ void stopDppInitiator();
+ void stopDppResponder(in int ownBootstrapId);
+ void stopRxFilter();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
new file mode 100644
index 0000000..37b34cf
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaIfaceCallback {
+ oneway void onAnqpQueryDone(in byte[] bssid, in android.hardware.wifi.supplicant.AnqpData data, in android.hardware.wifi.supplicant.Hs20AnqpData hs20Data);
+ oneway void onAssociationRejected(in android.hardware.wifi.supplicant.AssociationRejectionData assocRejectData);
+ oneway void onAuthenticationTimeout(in byte[] bssid);
+ oneway void onBssTmHandlingDone(in android.hardware.wifi.supplicant.BssTmData tmData);
+ oneway void onBssidChanged(in android.hardware.wifi.supplicant.BssidChangeReason reason, in byte[] bssid);
+ oneway void onDisconnected(in byte[] bssid, in boolean locallyGenerated, in android.hardware.wifi.supplicant.StaIfaceReasonCode reasonCode);
+ oneway void onDppFailure(in android.hardware.wifi.supplicant.DppFailureCode code, in String ssid, in String channelList, in char[] bandList);
+ oneway void onDppProgress(in android.hardware.wifi.supplicant.DppProgressCode code);
+ oneway void onDppSuccess(in android.hardware.wifi.supplicant.DppEventType event);
+ oneway void onDppSuccessConfigReceived(in byte[] ssid, in String password, in byte[] psk, in android.hardware.wifi.supplicant.DppAkm securityAkm);
+ oneway void onDppSuccessConfigSent();
+ oneway void onEapFailure(in int errorCode);
+ oneway void onExtRadioWorkStart(in int id);
+ oneway void onExtRadioWorkTimeout(in int id);
+ oneway void onHs20DeauthImminentNotice(in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
+ oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
+ oneway void onHs20SubscriptionRemediation(in byte[] bssid, in android.hardware.wifi.supplicant.OsuMethod osuMethod, in String url);
+ oneway void onHs20TermsAndConditionsAcceptanceRequestedNotification(in byte[] bssid, in String url);
+ oneway void onNetworkAdded(in int id);
+ oneway void onNetworkNotFound(in byte[] ssid);
+ oneway void onNetworkRemoved(in int id);
+ oneway void onPmkCacheAdded(in long expirationTimeInSec, in byte[] serializedEntry);
+ oneway void onStateChanged(in android.hardware.wifi.supplicant.StaIfaceCallbackState newState, in byte[] bssid, in int id, in byte[] ssid, in boolean filsHlpSent);
+ oneway void onWpsEventFail(in byte[] bssid, in android.hardware.wifi.supplicant.WpsConfigError configError, in android.hardware.wifi.supplicant.WpsErrorIndication errorInd);
+ oneway void onWpsEventPbcOverlap();
+ oneway void onWpsEventSuccess();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
new file mode 100644
index 0000000..18baea6
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaNetwork {
+ void disable();
+ void enable(in boolean noConnect);
+ void enableSaePkOnlyMode(in boolean enable);
+ void enableSuiteBEapOpenSslCiphers();
+ void enableTlsSuiteBEapPhase1Param(in boolean enable);
+ android.hardware.wifi.supplicant.AuthAlgMask getAuthAlg();
+ byte[] getBssid();
+ String getEapAltSubjectMatch();
+ byte[] getEapAnonymousIdentity();
+ String getEapCACert();
+ String getEapCAPath();
+ String getEapClientCert();
+ String getEapDomainSuffixMatch();
+ boolean getEapEngine();
+ String getEapEngineId();
+ byte[] getEapIdentity();
+ android.hardware.wifi.supplicant.EapMethod getEapMethod();
+ byte[] getEapPassword();
+ android.hardware.wifi.supplicant.EapPhase2Method getEapPhase2Method();
+ String getEapPrivateKeyId();
+ String getEapSubjectMatch();
+ boolean getEdmg();
+ android.hardware.wifi.supplicant.GroupCipherMask getGroupCipher();
+ android.hardware.wifi.supplicant.GroupMgmtCipherMask getGroupMgmtCipher();
+ int getId();
+ String getIdStr();
+ String getInterfaceName();
+ android.hardware.wifi.supplicant.KeyMgmtMask getKeyMgmt();
+ android.hardware.wifi.supplicant.OcspType getOcsp();
+ android.hardware.wifi.supplicant.PairwiseCipherMask getPairwiseCipher();
+ android.hardware.wifi.supplicant.ProtoMask getProto();
+ byte[] getPsk();
+ String getPskPassphrase();
+ boolean getRequirePmf();
+ String getSaePassword();
+ String getSaePasswordId();
+ boolean getScanSsid();
+ byte[] getSsid();
+ android.hardware.wifi.supplicant.IfaceType getType();
+ String getWapiCertSuite();
+ byte[] getWepKey(in int keyIdx);
+ int getWepTxKeyIdx();
+ byte[] getWpsNfcConfigurationToken();
+ void registerCallback(in android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback callback);
+ void select();
+ void sendNetworkEapIdentityResponse(in byte[] identity, in byte[] encryptedIdentity);
+ void sendNetworkEapSimGsmAuthFailure();
+ void sendNetworkEapSimGsmAuthResponse(in android.hardware.wifi.supplicant.NetworkResponseEapSimGsmAuthParams[] params);
+ void sendNetworkEapSimUmtsAuthFailure();
+ void sendNetworkEapSimUmtsAuthResponse(in android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams params);
+ void sendNetworkEapSimUmtsAutsResponse(in byte[] auts);
+ void setAuthAlg(in android.hardware.wifi.supplicant.AuthAlgMask authAlgMask);
+ void setBssid(in byte[] bssid);
+ void setEapAltSubjectMatch(in String match);
+ void setEapAnonymousIdentity(in byte[] identity);
+ void setEapCACert(in String path);
+ void setEapCAPath(in String path);
+ void setEapClientCert(in String path);
+ void setEapDomainSuffixMatch(in String match);
+ void setEapEncryptedImsiIdentity(in byte[] identity);
+ void setEapEngine(in boolean enable);
+ void setEapEngineID(in String id);
+ void setEapErp(in boolean enable);
+ void setEapIdentity(in byte[] identity);
+ void setEapMethod(in android.hardware.wifi.supplicant.EapMethod method);
+ void setEapPassword(in byte[] password);
+ void setEapPhase2Method(in android.hardware.wifi.supplicant.EapPhase2Method method);
+ void setEapPrivateKeyId(in String id);
+ void setEapSubjectMatch(in String match);
+ void setEdmg(in boolean enable);
+ void setGroupCipher(in android.hardware.wifi.supplicant.GroupCipherMask groupCipherMask);
+ void setGroupMgmtCipher(in android.hardware.wifi.supplicant.GroupMgmtCipherMask groupMgmtCipherMask);
+ void setIdStr(in String idStr);
+ void setKeyMgmt(in android.hardware.wifi.supplicant.KeyMgmtMask keyMgmtMask);
+ void setOcsp(in android.hardware.wifi.supplicant.OcspType ocspType);
+ void setPairwiseCipher(in android.hardware.wifi.supplicant.PairwiseCipherMask pairwiseCipherMask);
+ void setPmkCache(in byte[] serializedEntry);
+ void setProactiveKeyCaching(in boolean enable);
+ void setProto(in android.hardware.wifi.supplicant.ProtoMask protoMask);
+ void setPsk(in byte[] psk);
+ void setPskPassphrase(in String psk);
+ void setRequirePmf(in boolean enable);
+ void setSaeH2eMode(in android.hardware.wifi.supplicant.SaeH2eMode mode);
+ void setSaePassword(in String saePassword);
+ void setSaePasswordId(in String saePasswordId);
+ void setScanSsid(in boolean enable);
+ void setSsid(in byte[] ssid);
+ void setUpdateIdentifier(in int id);
+ void setWapiCertSuite(in String suite);
+ void setWepKey(in int keyIdx, in byte[] wepKey);
+ void setWepTxKeyIdx(in int keyIdx);
+ const int SSID_MAX_LEN_IN_BYTES = 32;
+ const int PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8;
+ const int PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63;
+ const int WEP_KEYS_MAX_NUM = 4;
+ const int WEP40_KEY_LEN_IN_BYTES = 5;
+ const int WEP104_KEY_LEN_IN_BYTES = 13;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
new file mode 100644
index 0000000..4f7584d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaNetworkCallback {
+ oneway void onNetworkEapIdentityRequest();
+ oneway void onNetworkEapSimGsmAuthRequest(in android.hardware.wifi.supplicant.NetworkRequestEapSimGsmAuthParams params);
+ oneway void onNetworkEapSimUmtsAuthRequest(in android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams params);
+ oneway void onTransitionDisable(in android.hardware.wifi.supplicant.TransitionDisableIndication ind);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl
new file mode 100644
index 0000000..6706c8c
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable IfaceInfo {
+ android.hardware.wifi.supplicant.IfaceType type;
+ String name;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl
new file mode 100644
index 0000000..557dbd7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum IfaceType {
+ STA = 0,
+ P2P = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
new file mode 100644
index 0000000..7228480
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum KeyMgmtMask {
+ WPA_EAP = 1,
+ WPA_PSK = 2,
+ NONE = 4,
+ IEEE8021X = 8,
+ FT_EAP = 32,
+ FT_PSK = 64,
+ OSEN = 32768,
+ WPA_EAP_SHA256 = 128,
+ WPA_PSK_SHA256 = 256,
+ SAE = 1024,
+ SUITE_B_192 = 131072,
+ OWE = 4194304,
+ DPP = 8388608,
+ WAPI_PSK = 4096,
+ WAPI_CERT = 8192,
+ FILS_SHA256 = 262144,
+ FILS_SHA384 = 524288,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl
new file mode 100644
index 0000000..6896d75
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum LegacyMode {
+ UNKNOWN = 0,
+ A_MODE = 1,
+ B_MODE = 2,
+ G_MODE = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl
new file mode 100644
index 0000000..d17930a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable MacAddress {
+ byte[] data;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
new file mode 100644
index 0000000..661165d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MboAssocDisallowedReasonCode {
+ RESERVED = 0,
+ UNSPECIFIED = 1,
+ MAX_NUM_STA_ASSOCIATED = 2,
+ AIR_INTERFACE_OVERLOADED = 3,
+ AUTH_SERVER_OVERLOADED = 4,
+ INSUFFICIENT_RSSI = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
new file mode 100644
index 0000000..c4024d0
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum MboCellularDataConnectionPrefValue {
+ EXCLUDED = 0,
+ NOT_PREFERRED = 1,
+ PREFERRED = 255,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
new file mode 100644
index 0000000..caed095
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MboTransitionReasonCode {
+ UNSPECIFIED = 0,
+ EXCESSIVE_FRAME_LOSS = 1,
+ EXCESSIVE_TRAFFIC_DELAY = 2,
+ INSUFFICIENT_BANDWIDTH = 3,
+ LOAD_BALANCING = 4,
+ LOW_RSSI = 5,
+ RX_EXCESSIVE_RETRIES = 6,
+ HIGH_INTERFERENCE = 7,
+ GRAY_ZONE = 8,
+ TRANSITION_TO_PREMIUM_AP = 9,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl
new file mode 100644
index 0000000..6bc9e4d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MiracastMode {
+ DISABLED = 0,
+ SOURCE = 1,
+ SINK = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..1f03bb8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkRequestEapSimGsmAuthParams {
+ android.hardware.wifi.supplicant.GsmRand[] rands;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..956a799
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkRequestEapSimUmtsAuthParams {
+ byte[] rand;
+ byte[] autn;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..29415b7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkResponseEapSimGsmAuthParams {
+ byte[] kc;
+ byte[] sres;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..4e58dd8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkResponseEapSimUmtsAuthParams {
+ byte[] res;
+ byte[] ik;
+ byte[] ck;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
new file mode 100644
index 0000000..95a95bc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable OceRssiBasedAssocRejectAttr {
+ int deltaRssi;
+ int retryDelayS;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl
new file mode 100644
index 0000000..89de811
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum OcspType {
+ NONE = 0,
+ REQUEST_CERT_STATUS = 1,
+ REQUIRE_CERT_STATUS = 2,
+ REQUIRE_ALL_CERTS_STATUS = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl
new file mode 100644
index 0000000..1b99e2f
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum OsuMethod {
+ OMA_DM = 0,
+ SOAP_XML_SPP = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
new file mode 100644
index 0000000..ffee12c
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum P2pGroupCapabilityMask {
+ GROUP_OWNER = 1,
+ PERSISTENT_GROUP = 2,
+ GROUP_LIMIT = 4,
+ INTRA_BSS_DIST = 8,
+ CROSS_CONN = 16,
+ PERSISTENT_RECONN = 32,
+ GROUP_FORMATION = 64,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
new file mode 100644
index 0000000..c8e53b9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum P2pProvDiscStatusCode {
+ SUCCESS = 0,
+ TIMEOUT = 1,
+ REJECTED = 2,
+ TIMEOUT_JOIN = 3,
+ INFO_UNAVAILABLE = 4,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl
new file mode 100644
index 0000000..c7ad383
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum P2pStatusCode {
+ SUCCESS = 0,
+ FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
+ FAIL_INCOMPATIBLE_PARAMS = 2,
+ FAIL_LIMIT_REACHED = 3,
+ FAIL_INVALID_PARAMS = 4,
+ FAIL_UNABLE_TO_ACCOMMODATE = 5,
+ FAIL_PREV_PROTOCOL_ERROR = 6,
+ FAIL_NO_COMMON_CHANNELS = 7,
+ FAIL_UNKNOWN_GROUP = 8,
+ FAIL_BOTH_GO_INTENT_15 = 9,
+ FAIL_INCOMPATIBLE_PROV_METHOD = 10,
+ FAIL_REJECTED_BY_USER = 11,
+ SUCCESS_DEFERRED = 12,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
new file mode 100644
index 0000000..d9b00e1
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum PairwiseCipherMask {
+ NONE = 1,
+ TKIP = 8,
+ CCMP = 16,
+ GCMP_128 = 64,
+ SMS4 = 128,
+ GCMP_256 = 256,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl
new file mode 100644
index 0000000..de92428
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum ProtoMask {
+ WPA = 1,
+ RSN = 2,
+ WAPI = 4,
+ OSEN = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl
new file mode 100644
index 0000000..63f5bf2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum RxFilterType {
+ V4_MULTICAST = 0,
+ V6_MULTICAST = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl
new file mode 100644
index 0000000..978c337
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum SaeH2eMode {
+ DISABLED = 0,
+ H2E_OPTIONAL = 1,
+ H2E_MANDATORY = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
new file mode 100644
index 0000000..d78cfa2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceCallbackState {
+ DISCONNECTED = 0,
+ IFACE_DISABLED = 1,
+ INACTIVE = 2,
+ SCANNING = 3,
+ AUTHENTICATING = 4,
+ ASSOCIATING = 5,
+ ASSOCIATED = 6,
+ FOURWAY_HANDSHAKE = 7,
+ GROUP_HANDSHAKE = 8,
+ COMPLETED = 9,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
new file mode 100644
index 0000000..f26e7c5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceReasonCode {
+ UNSPECIFIED = 1,
+ PREV_AUTH_NOT_VALID = 2,
+ DEAUTH_LEAVING = 3,
+ DISASSOC_DUE_TO_INACTIVITY = 4,
+ DISASSOC_AP_BUSY = 5,
+ CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+ CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+ DISASSOC_STA_HAS_LEFT = 8,
+ STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+ PWR_CAPABILITY_NOT_VALID = 10,
+ SUPPORTED_CHANNEL_NOT_VALID = 11,
+ BSS_TRANSITION_DISASSOC = 12,
+ INVALID_IE = 13,
+ MICHAEL_MIC_FAILURE = 14,
+ FOURWAY_HANDSHAKE_TIMEOUT = 15,
+ GROUP_KEY_UPDATE_TIMEOUT = 16,
+ IE_IN_4WAY_DIFFERS = 17,
+ GROUP_CIPHER_NOT_VALID = 18,
+ PAIRWISE_CIPHER_NOT_VALID = 19,
+ AKMP_NOT_VALID = 20,
+ UNSUPPORTED_RSN_IE_VERSION = 21,
+ INVALID_RSN_IE_CAPAB = 22,
+ IEEE_802_1X_AUTH_FAILED = 23,
+ CIPHER_SUITE_REJECTED = 24,
+ TDLS_TEARDOWN_UNREACHABLE = 25,
+ TDLS_TEARDOWN_UNSPECIFIED = 26,
+ SSP_REQUESTED_DISASSOC = 27,
+ NO_SSP_ROAMING_AGREEMENT = 28,
+ BAD_CIPHER_OR_AKM = 29,
+ NOT_AUTHORIZED_THIS_LOCATION = 30,
+ SERVICE_CHANGE_PRECLUDES_TS = 31,
+ UNSPECIFIED_QOS_REASON = 32,
+ NOT_ENOUGH_BANDWIDTH = 33,
+ DISASSOC_LOW_ACK = 34,
+ EXCEEDED_TXOP = 35,
+ STA_LEAVING = 36,
+ END_TS_BA_DLS = 37,
+ UNKNOWN_TS_BA = 38,
+ TIMEOUT = 39,
+ PEERKEY_MISMATCH = 45,
+ AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+ EXTERNAL_SERVICE_REQUIREMENTS = 47,
+ INVALID_FT_ACTION_FRAME_COUNT = 48,
+ INVALID_PMKID = 49,
+ INVALID_MDE = 50,
+ INVALID_FTE = 51,
+ MESH_PEERING_CANCELLED = 52,
+ MESH_MAX_PEERS = 53,
+ MESH_CONFIG_POLICY_VIOLATION = 54,
+ MESH_CLOSE_RCVD = 55,
+ MESH_MAX_RETRIES = 56,
+ MESH_CONFIRM_TIMEOUT = 57,
+ MESH_INVALID_GTK = 58,
+ MESH_INCONSISTENT_PARAMS = 59,
+ MESH_INVALID_SECURITY_CAP = 60,
+ MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+ MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+ MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+ MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+ MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+ MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
new file mode 100644
index 0000000..13529a5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceStatusCode {
+ SUCCESS = 0,
+ UNSPECIFIED_FAILURE = 1,
+ TDLS_WAKEUP_ALTERNATE = 2,
+ TDLS_WAKEUP_REJECT = 3,
+ SECURITY_DISABLED = 5,
+ UNACCEPTABLE_LIFETIME = 6,
+ NOT_IN_SAME_BSS = 7,
+ CAPS_UNSUPPORTED = 10,
+ REASSOC_NO_ASSOC = 11,
+ ASSOC_DENIED_UNSPEC = 12,
+ NOT_SUPPORTED_AUTH_ALG = 13,
+ UNKNOWN_AUTH_TRANSACTION = 14,
+ CHALLENGE_FAIL = 15,
+ AUTH_TIMEOUT = 16,
+ AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+ ASSOC_DENIED_RATES = 18,
+ ASSOC_DENIED_NOSHORT = 19,
+ SPEC_MGMT_REQUIRED = 22,
+ PWR_CAPABILITY_NOT_VALID = 23,
+ SUPPORTED_CHANNEL_NOT_VALID = 24,
+ ASSOC_DENIED_NO_SHORT_SLOT_TIME = 25,
+ ASSOC_DENIED_NO_HT = 27,
+ R0KH_UNREACHABLE = 28,
+ ASSOC_DENIED_NO_PCO = 29,
+ ASSOC_REJECTED_TEMPORARILY = 30,
+ ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
+ UNSPECIFIED_QOS_FAILURE = 32,
+ DENIED_INSUFFICIENT_BANDWIDTH = 33,
+ DENIED_POOR_CHANNEL_CONDITIONS = 34,
+ DENIED_QOS_NOT_SUPPORTED = 35,
+ REQUEST_DECLINED = 37,
+ INVALID_PARAMETERS = 38,
+ REJECTED_WITH_SUGGESTED_CHANGES = 39,
+ INVALID_IE = 40,
+ GROUP_CIPHER_NOT_VALID = 41,
+ PAIRWISE_CIPHER_NOT_VALID = 42,
+ AKMP_NOT_VALID = 43,
+ UNSUPPORTED_RSN_IE_VERSION = 44,
+ INVALID_RSN_IE_CAPAB = 45,
+ CIPHER_REJECTED_PER_POLICY = 46,
+ TS_NOT_CREATED = 47,
+ DIRECT_LINK_NOT_ALLOWED = 48,
+ DEST_STA_NOT_PRESENT = 49,
+ DEST_STA_NOT_QOS_STA = 50,
+ ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51,
+ INVALID_FT_ACTION_FRAME_COUNT = 52,
+ INVALID_PMKID = 53,
+ INVALID_MDIE = 54,
+ INVALID_FTIE = 55,
+ REQUESTED_TCLAS_NOT_SUPPORTED = 56,
+ INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57,
+ TRY_ANOTHER_BSS = 58,
+ GAS_ADV_PROTO_NOT_SUPPORTED = 59,
+ NO_OUTSTANDING_GAS_REQ = 60,
+ GAS_RESP_NOT_RECEIVED = 61,
+ STA_TIMED_OUT_WAITING_FOR_GAS_RESP = 62,
+ GAS_RESP_LARGER_THAN_LIMIT = 63,
+ REQ_REFUSED_HOME = 64,
+ ADV_SRV_UNREACHABLE = 65,
+ REQ_REFUSED_SSPN = 67,
+ REQ_REFUSED_UNAUTH_ACCESS = 68,
+ INVALID_RSNIE = 72,
+ U_APSD_COEX_NOT_SUPPORTED = 73,
+ U_APSD_COEX_MODE_NOT_SUPPORTED = 74,
+ BAD_INTERVAL_WITH_U_APSD_COEX = 75,
+ ANTI_CLOGGING_TOKEN_REQ = 76,
+ FINITE_CYCLIC_GROUP_NOT_SUPPORTED = 77,
+ CANNOT_FIND_ALT_TBTT = 78,
+ TRANSMISSION_FAILURE = 79,
+ REQ_TCLAS_NOT_SUPPORTED = 80,
+ TCLAS_RESOURCES_EXCHAUSTED = 81,
+ REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82,
+ REJECT_WITH_SCHEDULE = 83,
+ REJECT_NO_WAKEUP_SPECIFIED = 84,
+ SUCCESS_POWER_SAVE_MODE = 85,
+ PENDING_ADMITTING_FST_SESSION = 86,
+ PERFORMING_FST_NOW = 87,
+ PENDING_GAP_IN_BA_WINDOW = 88,
+ REJECT_U_PID_SETTING = 89,
+ REFUSED_EXTERNAL_REASON = 92,
+ REFUSED_AP_OUT_OF_MEMORY = 93,
+ REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED = 94,
+ QUERY_RESP_OUTSTANDING = 95,
+ REJECT_DSE_BAND = 96,
+ TCLAS_PROCESSING_TERMINATED = 97,
+ TS_SCHEDULE_CONFLICT = 98,
+ DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
+ MCCAOP_RESERVATION_CONFLICT = 100,
+ MAF_LIMIT_EXCEEDED = 101,
+ MCCA_TRACK_LIMIT_EXCEEDED = 102,
+ DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+ ASSOC_DENIED_NO_VHT = 104,
+ ENABLEMENT_DENIED = 105,
+ RESTRICTION_FROM_AUTHORIZED_GDB = 106,
+ AUTHORIZATION_DEENABLED = 107,
+ FILS_AUTHENTICATION_FAILURE = 112,
+ UNKNOWN_AUTHENTICATION_SERVER = 113,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
new file mode 100644
index 0000000..32d71a3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum SupplicantStatusCode {
+ SUCCESS = 0,
+ FAILURE_UNKNOWN = 1,
+ FAILURE_ARGS_INVALID = 2,
+ FAILURE_IFACE_INVALID = 3,
+ FAILURE_IFACE_UNKNOWN = 4,
+ FAILURE_IFACE_EXISTS = 5,
+ FAILURE_IFACE_DISABLED = 6,
+ FAILURE_IFACE_NOT_DISCONNECTED = 7,
+ FAILURE_NETWORK_INVALID = 8,
+ FAILURE_NETWORK_UNKNOWN = 9,
+ FAILURE_UNSUPPORTED = 10,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
new file mode 100644
index 0000000..7c63217
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum TransitionDisableIndication {
+ USE_WPA3_PERSONAL = 1,
+ USE_SAE_PK = 2,
+ USE_WPA3_ENTERPRISE = 4,
+ USE_ENHANCED_OPEN = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl
new file mode 100644
index 0000000..ad36e68
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WifiTechnology {
+ UNKNOWN = 0,
+ LEGACY = 1,
+ HT = 2,
+ VHT = 3,
+ HE = 4,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
new file mode 100644
index 0000000..43772af
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpaDriverCapabilitiesMask {
+ MBO = 1,
+ OCE = 2,
+ SAE_PK = 4,
+ WFD_R2 = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl
new file mode 100644
index 0000000..c48b282
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsConfigError {
+ NO_ERROR = 0,
+ OOB_IFACE_READ_ERROR = 1,
+ DECRYPTION_CRC_FAILURE = 2,
+ CHAN_24_NOT_SUPPORTED = 3,
+ CHAN_50_NOT_SUPPORTED = 4,
+ SIGNAL_TOO_WEAK = 5,
+ NETWORK_AUTH_FAILURE = 6,
+ NETWORK_ASSOC_FAILURE = 7,
+ NO_DHCP_RESPONSE = 8,
+ FAILED_DHCP_CONFIG = 9,
+ IP_ADDR_CONFLICT = 10,
+ NO_CONN_TO_REGISTRAR = 11,
+ MULTIPLE_PBC_DETECTED = 12,
+ ROGUE_SUSPECTED = 13,
+ DEVICE_BUSY = 14,
+ SETUP_LOCKED = 15,
+ MSG_TIMEOUT = 16,
+ REG_SESS_TIMEOUT = 17,
+ DEV_PASSWORD_AUTH_FAILURE = 18,
+ CHAN_60G_NOT_SUPPORTED = 19,
+ PUBLIC_KEY_HASH_MISMATCH = 20,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
new file mode 100644
index 0000000..c98c479
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsConfigMethods {
+ USBA = 1,
+ ETHERNET = 2,
+ LABEL = 4,
+ DISPLAY = 8,
+ EXT_NFC_TOKEN = 16,
+ INT_NFC_TOKEN = 32,
+ NFC_INTERFACE = 64,
+ PUSHBUTTON = 128,
+ KEYPAD = 256,
+ VIRT_PUSHBUTTON = 640,
+ PHY_PUSHBUTTON = 1152,
+ P2PS = 4096,
+ VIRT_DISPLAY = 8200,
+ PHY_DISPLAY = 16392,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
new file mode 100644
index 0000000..975f1ab
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsDevPasswordId {
+ DEFAULT = 0,
+ USER_SPECIFIED = 1,
+ MACHINE_SPECIFIED = 2,
+ REKEY = 3,
+ PUSHBUTTON = 4,
+ REGISTRAR_SPECIFIED = 5,
+ NFC_CONNECTION_HANDOVER = 7,
+ P2PS_DEFAULT = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
new file mode 100644
index 0000000..50e69ff
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsErrorIndication {
+ NO_ERROR = 0,
+ SECURITY_TKIP_ONLY_PROHIBITED = 1,
+ SECURITY_WEP_PROHIBITED = 2,
+ AUTH_FAILURE = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
new file mode 100644
index 0000000..f6dba23
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsProvisionMethod {
+ PBC = 0,
+ DISPLAY = 1,
+ KEYPAD = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl
new file mode 100644
index 0000000..5bc1015
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * ANQP data for IEEE Std 802.11-2016.
+ * The format of the data within these elements follows the IEEE
+ * Std 802.11-2016 standard, section 9.4.5.
+ */
+@VintfStability
+parcelable AnqpData {
+ byte[] venueName;
+ byte[] roamingConsortium;
+ byte[] ipAddrTypeAvailability;
+ byte[] naiRealm;
+ byte[] anqp3gppCellularNetwork;
+ byte[] domainName;
+ byte[] venueUrl;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl
new file mode 100644
index 0000000..7b2eb23
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Access Network Query Protocol info ID elements
+ * for IEEE Std 802.11u-2011.
+ */
+@VintfStability
+@Backing(type="int")
+enum AnqpInfoId {
+ VENUE_NAME = 258,
+ ROAMING_CONSORTIUM = 261,
+ IP_ADDR_TYPE_AVAILABILITY = 262,
+ NAI_REALM = 263,
+ ANQP_3GPP_CELLULAR_NETWORK = 264,
+ DOMAIN_NAME = 268,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
new file mode 100644
index 0000000..5673021
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.MboAssocDisallowedReasonCode;
+import android.hardware.wifi.supplicant.OceRssiBasedAssocRejectAttr;
+import android.hardware.wifi.supplicant.StaIfaceStatusCode;
+
+/**
+ * Association Rejection related information.
+ */
+@VintfStability
+parcelable AssociationRejectionData {
+ /**
+ * SSID of the AP that rejected the association.
+ */
+ byte[] ssid;
+ /**
+ * BSSID of the AP that rejected the association.
+ */
+ byte[/* 6 */] bssid;
+ /*
+ * 802.11 code to indicate the reject reason.
+ * Refer to section 8.4.1.9 of IEEE 802.11 spec.
+ */
+ StaIfaceStatusCode statusCode;
+ /*
+ * Flag to indicate that failure is due to timeout rather than
+ * explicit rejection response from the AP.
+ */
+ boolean timedOut;
+ /**
+ * Flag to indicate that MboAssocDisallowedReasonCode is present
+ * in the (Re-)Association response frame.
+ */
+ boolean isMboAssocDisallowedReasonCodePresent;
+ /**
+ * mboAssocDisallowedReason is extracted from MBO association disallowed attribute
+ * in (Re-)Association response frame to indicate that the AP is not accepting new
+ * associations.
+ * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code.
+ * The value is undefined if isMboAssocDisallowedReasonCodePresent is false.
+ */
+ MboAssocDisallowedReasonCode mboAssocDisallowedReason;
+ /**
+ * Flag to indicate that OceRssiBasedAssocRejectAttr is present
+ * in the (Re-)Association response frame.
+ */
+ boolean isOceRssiBasedAssocRejectAttrPresent;
+ /*
+ * OCE RSSI-based (Re-)Association rejection attribute.
+ * The contents are undefined if isOceRssiBasedAssocRejectAttrPresent is false.
+ */
+ OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
new file mode 100644
index 0000000..039d41d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possible mask of values for AuthAlg param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_AUTH_ALG_OPEN).
+ */
+@VintfStability
+@Backing(type="int")
+enum AuthAlgMask {
+ OPEN = 1 << 0,
+ SHARED = 1 << 1,
+ LEAP = 1 << 2,
+ SAE = 1 << 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl
new file mode 100644
index 0000000..233e54a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.BssTmDataFlagsMask;
+import android.hardware.wifi.supplicant.BssTmStatusCode;
+import android.hardware.wifi.supplicant.MboCellularDataConnectionPrefValue;
+import android.hardware.wifi.supplicant.MboTransitionReasonCode;
+
+/**
+ * Data retrieved from received BSS transition management request frame.
+ */
+@VintfStability
+parcelable BssTmData {
+ /*
+ * Status code filled in BSS transition management response frame
+ */
+ BssTmStatusCode status;
+ /*
+ * Bitmask of BssTmDataFlagsMask
+ */
+ BssTmDataFlagsMask flags;
+ /*
+ * Duration for which STA shouldn't try to re-associate.
+ */
+ int assocRetryDelayMs;
+ /*
+ * Reason for BSS transition request.
+ */
+ MboTransitionReasonCode mboTransitionReason;
+ /*
+ * Cellular Data Connection preference value.
+ */
+ MboCellularDataConnectionPrefValue mboCellPreference;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
new file mode 100644
index 0000000..1eb75f4
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Bitmask of various information retrieved from BSS transition management request frame.
+ */
+@VintfStability
+@Backing(type="int")
+enum BssTmDataFlagsMask {
+ /**
+ * Preferred candidate list included.
+ */
+ WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED = 1 << 0,
+ /**
+ * Abridged.
+ */
+ WNM_MODE_ABRIDGED = 1 << 1,
+ /**
+ * Disassociation Imminent.
+ */
+ WNM_MODE_DISASSOCIATION_IMMINENT = 1 << 2,
+ /**
+ * BSS termination included.
+ */
+ WNM_MODE_BSS_TERMINATION_INCLUDED = 1 << 3,
+ /**
+ * ESS Disassociation Imminent.
+ */
+ WNM_MODE_ESS_DISASSOCIATION_IMMINENT = 1 << 4,
+ /**
+ * MBO transition reason code included.
+ */
+ MBO_TRANSITION_REASON_CODE_INCLUDED = 1 << 5,
+ /**
+ * MBO retry delay time included.
+ */
+ MBO_ASSOC_RETRY_DELAY_INCLUDED = 1 << 6,
+ /**
+ * MBO cellular data connection preference value included.
+ */
+ MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED = 1 << 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
new file mode 100644
index 0000000..51fbfed
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * IEEE Std 802.11-2016 - Table 9-357.
+ * BTM status code filled in BSS transition management response frame.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BssTmStatusCode {
+ ACCEPT = 0,
+ REJECT_UNSPECIFIED = 1,
+ REJECT_INSUFFICIENT_BEACON = 2,
+ REJECT_INSUFFICIENT_CAPABITY = 3,
+ REJECT_BSS_TERMINATION_UNDESIRED = 4,
+ REJECT_BSS_TERMINATION_DELAY_REQUEST = 5,
+ REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
+ REJECT_NO_SUITABLE_CANDIDATES = 7,
+ REJECT_LEAVING_ESS = 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl
new file mode 100644
index 0000000..8532bd7
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * BSSID change Reasons.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BssidChangeReason {
+ /**
+ * Started association with new bssid.
+ */
+ ASSOC_START = 0,
+ /**
+ * Completed association with new bssid.
+ */
+ ASSOC_COMPLETE = 1,
+ /**
+ * Dis-association with current bssid.
+ */
+ DISASSOC = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
new file mode 100644
index 0000000..4972744
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Enum describing the modes of BT coexistence supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BtCoexistenceMode {
+ ENABLED = 0,
+ DISABLED = 1,
+ SENSE = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
new file mode 100644
index 0000000..1718413
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.LegacyMode;
+import android.hardware.wifi.supplicant.WifiTechnology;
+
+/**
+ * Connection Capabilities supported by current network and device
+ */
+@VintfStability
+parcelable ConnectionCapabilities {
+ /**
+ * Wifi Technology
+ */
+ WifiTechnology technology;
+ /**
+ * channel bandwidth
+ */
+ int channelBandwidth;
+ /**
+ * max number of Tx spatial streams
+ */
+ int maxNumberTxSpatialStreams;
+ /**
+ * max number of Rx spatial streams
+ */
+ int maxNumberRxSpatialStreams;
+ /**
+ * detailed network mode for legacy network
+ */
+ LegacyMode legacyMode;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl
new file mode 100644
index 0000000..7caa406
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Debug levels for the supplicant.
+ * Only log messages with a level greater than the set level
+ * (via |setDebugParams|) will be logged.
+ */
+@VintfStability
+@Backing(type="int")
+enum DebugLevel {
+ EXCESSIVE = 0,
+ MSGDUMP = 1,
+ DEBUG = 2,
+ INFO = 3,
+ WARNING = 4,
+ ERROR = 5,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl
new file mode 100644
index 0000000..63fff54
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppAkm: The various AKMs that can be provisioned using DPP.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppAkm {
+ PSK,
+ PSK_SAE,
+ SAE,
+ DPP,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl
new file mode 100644
index 0000000..ea57505
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppCurve: Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppCurve {
+ PRIME256V1,
+ SECP384R1,
+ SECP521R1,
+ BRAINPOOLP256R1,
+ BRAINPOOLP384R1,
+ BRAINPOOLP512R1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl
new file mode 100644
index 0000000..4b9b38b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppEventType: Major events for DPP (Easy Connect) Configurator
+ */
+@VintfStability
+@Backing(type="int")
+enum DppEventType {
+ CONFIGURATION_SENT,
+ CONFIGURATION_APPLIED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl
new file mode 100644
index 0000000..5c0c6e8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppFailureCode: Error codes for DPP (Easy Connect)
+ */
+@VintfStability
+@Backing(type="int")
+enum DppFailureCode {
+ INVALID_URI,
+ AUTHENTICATION,
+ NOT_COMPATIBLE,
+ CONFIGURATION,
+ BUSY,
+ TIMEOUT,
+ FAILURE,
+ NOT_SUPPORTED,
+ CONFIGURATION_REJECTED,
+ CANNOT_FIND_NETWORK,
+ ENROLLEE_AUTHENTICATION,
+ /**
+ * Failure to generate a DPP URI.
+ */
+ URI_GENERATION,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl
new file mode 100644
index 0000000..d92cfa3
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppNetRole: The network role that the configurator offers the enrollee.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppNetRole {
+ STA,
+ AP,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl
new file mode 100644
index 0000000..f8b35c0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DppProgressCode: Progress codes for DPP (Easy Connect)
+ */
+@VintfStability
+@Backing(type="int")
+enum DppProgressCode {
+ AUTHENTICATION_SUCCESS,
+ RESPONSE_PENDING,
+ CONFIGURATION_SENT_WAITING_RESPONSE,
+ CONFIGURATION_ACCEPTED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
new file mode 100644
index 0000000..4f4778d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * DPP bootstrap info generated for responder mode operation
+ */
+@VintfStability
+parcelable DppResponderBootstrapInfo {
+ /**
+ * Generated bootstrap identifier
+ */
+ int bootstrapId;
+ /**
+ * The Wi-Fi channel that the DPP responder is listening on.
+ */
+ int listenChannel;
+ /**
+ * Bootstrapping URI per DPP specification, "section 5.2 Bootstrapping
+ * information", may contain listen channel, MAC address, public key, or other information.
+ */
+ String uri;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl
new file mode 100644
index 0000000..49f9e34
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/*
+ * EapErrorCode: Error code for EAP or EAP Method as per RFC-4186
+ */
+@VintfStability
+@Backing(type="int")
+enum EapErrorCode {
+ SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+ SIM_TEMPORARILY_DENIED = 1026,
+ SIM_NOT_SUBSCRIBED = 1031,
+ SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+ SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl
new file mode 100644
index 0000000..351fb6c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possble values for EapMethod param.
+ */
+@VintfStability
+@Backing(type="int")
+enum EapMethod {
+ PEAP = 0,
+ TLS = 1,
+ TTLS = 2,
+ PWD = 3,
+ SIM = 4,
+ AKA = 5,
+ AKA_PRIME = 6,
+ WFA_UNAUTH_TLS = 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl
new file mode 100644
index 0000000..a7eeca8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possble values for Phase2Method param.
+ */
+@VintfStability
+@Backing(type="int")
+enum EapPhase2Method {
+ NONE = 0,
+ PAP = 1,
+ MSPAP = 2,
+ MSPAPV2 = 3,
+ GTC = 4,
+ SIM = 5,
+ AKA = 6,
+ AKA_PRIME = 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
new file mode 100644
index 0000000..7325ba2
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+@VintfStability
+@Backing(type="int")
+enum ExtRadioWorkDefaults {
+ TIMEOUT_IN_SECS = 10,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl
new file mode 100644
index 0000000..a88c011
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Use to specify a range of frequencies.
+ * For example: 2412-2432,2462,5000-6000, etc.
+ */
+@VintfStability
+parcelable FreqRange {
+ int min;
+ int max;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
new file mode 100644
index 0000000..99e9da0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possible mask of values for GroupCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_CIPHER_WEP40).
+ */
+@VintfStability
+@Backing(type="int")
+enum GroupCipherMask {
+ WEP40 = 1 << 1,
+ WEP104 = 1 << 2,
+ TKIP = 1 << 3,
+ CCMP = 1 << 4,
+ GTK_NOT_USED = 1 << 14,
+ /**
+ * GCMP-256 Group Cipher
+ */
+ GCMP_256 = 1 << 8,
+ /**
+ * SMS4 Group Cipher
+ */
+ SMS4 = 1 << 7,
+ /**
+ * GCMP-128 Group Cipher
+ */
+ GCMP_128 = 1 << 6,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
new file mode 100644
index 0000000..07544f0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possble mask of values for GroupMgmtCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * all possible values (starting at WPA_CIPHER_BIP_GMAC_128).
+ */
+@VintfStability
+@Backing(type="int")
+enum GroupMgmtCipherMask {
+ /**
+ * BIP_GMAC-128 Group Management Cipher
+ */
+ BIP_GMAC_128 = 1 << 11,
+ /**
+ * BIP_GMAC-256 Group Management Cipher
+ */
+ BIP_GMAC_256 = 1 << 12,
+ /**
+ * BIP_CMAC-256 Group Management Cipher
+ */
+ BIP_CMAC_256 = 1 << 13,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl
new file mode 100644
index 0000000..4e31323
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Byte array with expected length 16. Used by NetworkRequestEapSimGsmAuthParams
+ * to pass an array of byte arrays, as 2D arrays are not supported in AIDL.
+ *
+ * TODO (b/210705533): Replace this type with a 2D byte array.
+ */
+@VintfStability
+parcelable GsmRand {
+ byte[/* 16 */] data;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
new file mode 100644
index 0000000..bdb9ec6
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * ANQP data for Hotspot 2.0.
+ * The format of the data within these elements follows the Hotspot 2.0
+ * standard.
+ */
+@VintfStability
+parcelable Hs20AnqpData {
+ byte[] operatorFriendlyName;
+ byte[] wanMetrics;
+ byte[] connectionCapability;
+ byte[] osuProvidersList;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
new file mode 100644
index 0000000..e08411d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Access Network Query Protocol subtype elements
+ * for Hotspot 2.0.
+ */
+@VintfStability
+@Backing(type="int")
+enum Hs20AnqpSubtypes {
+ OPERATOR_FRIENDLY_NAME = 3,
+ WAN_METRICS = 4,
+ CONNECTION_CAPABILITY = 5,
+ OSU_PROVIDERS_LIST = 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
new file mode 100644
index 0000000..c17289d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.DebugLevel;
+import android.hardware.wifi.supplicant.ISupplicantCallback;
+import android.hardware.wifi.supplicant.ISupplicantP2pIface;
+import android.hardware.wifi.supplicant.ISupplicantStaIface;
+import android.hardware.wifi.supplicant.IfaceInfo;
+import android.hardware.wifi.supplicant.IfaceType;
+
+/**
+ * Interface exposed by the supplicant AIDL service registered
+ * with the service manager. This is the root level object for
+ * any of the supplicant interactions.
+ */
+@VintfStability
+interface ISupplicant {
+ /**
+ * Default timeout (in seconds) for external radio work.
+ */
+ const int EXT_RADIO_WORK_TIMEOUT_IN_SECS = 10;
+
+ /**
+ * Registers a wireless interface in supplicant.
+ *
+ * @param ifName Name of the interface (e.g wlan0).
+ * @return AIDL interface object representing the interface if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_EXISTS|
+ */
+ @PropagateAllowBlocking ISupplicantP2pIface addP2pInterface(in String ifName);
+ @PropagateAllowBlocking ISupplicantStaIface addStaInterface(in String ifName);
+
+ /**
+ * Get the debug level set.
+ *
+ * @return one of |DebugLevel| values.
+ */
+ DebugLevel getDebugLevel();
+
+ /**
+ * Gets an AIDL interface object for the interface corresponding
+ * to an iface name which the supplicant already controls.
+ *
+ * @param ifName Name of the interface retrieved
+ * using |listInterfaces|.
+ * @return AIDL interface object representing the interface if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
+ */
+ @PropagateAllowBlocking ISupplicantP2pIface getP2pInterface(in String ifName);
+ @PropagateAllowBlocking ISupplicantStaIface getStaInterface(in String ifName);
+
+ /**
+ * Get whether the keys are shown in the debug logs or not.
+ *
+ * @return true if set, false otherwise.
+ */
+ boolean isDebugShowKeysEnabled();
+
+ /**
+ * Get whether the timestamps are shown in the debug logs or not.
+ *
+ * @return true if set, false otherwise.
+ */
+ boolean isDebugShowTimestampEnabled();
+
+ /**
+ * Retrieve a list of all interfaces controlled by the supplicant.
+ *
+ * The corresponding |ISupplicantIface| object for any interface can be
+ * retrieved using the proper |getInterface| method.
+ *
+ * @return List of all interfaces controlled by the supplicant.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ IfaceInfo[] listInterfaces();
+
+ /**
+ * Register for callbacks from the supplicant service.
+ *
+ * These callbacks are invoked for global events that are not specific
+ * to any interface or network. Registration of multiple callback
+ * objects is supported. These objects must be deleted when the corresponding
+ * client process is dead.
+ *
+ * @param callback An instance of the |ISupplicantCallback| AIDL interface
+ * object.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void registerCallback(in ISupplicantCallback callback);
+
+ /**
+ * Deregisters a wireless interface from supplicant.
+ *
+ * @param ifaceInfo Combination of the interface type and name (e.g wlan0).
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
+ */
+ void removeInterface(in IfaceInfo ifaceInfo);
+
+ /**
+ * Set concurrency priority.
+ *
+ * When both P2P and STA mode ifaces are active, this must be used
+ * to prioritize either STA or P2P connection to resolve conflicts
+ * arising during single channel concurrency.
+ *
+ * @param type The type of iface to prioritize.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setConcurrencyPriority(in IfaceType type);
+
+ /**
+ * Set debug parameters for the supplicant.
+ *
+ * @param level Debug logging level for the supplicant.
+ * (one of |DebugLevel| values).
+ * @param timestamp Determines whether to show timestamps in logs or
+ * not.
+ * @param showKeys Determines whether to show keys in debug logs or
+ * not.
+ * CAUTION: Do not set this param in production code!
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setDebugParams(in DebugLevel level, in boolean showTimestamp, in boolean showKeys);
+
+ /**
+ * Terminate the service.
+ * This must de-register the service and clear all state. If this HAL
+ * supports the lazy HAL protocol, then this may trigger daemon to exit and
+ * wait to be restarted.
+ */
+ oneway void terminate();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
new file mode 100644
index 0000000..6f15900
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Callback Interface exposed by the supplicant service (ISupplicant).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * |ISupplicant.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantCallback {
+ /**
+ * Used to indicate that a new interface has been created.
+ *
+ * @param ifaceName Name of the network interface, e.g., wlan0
+ */
+ oneway void onInterfaceCreated(in String ifaceName);
+
+ /**
+ * Used to indicate that an interface has been removed.
+ *
+ * @param ifaceName Name of the network interface, e.g., wlan0
+ */
+ oneway void onInterfaceRemoved(in String ifaceName);
+
+ /**
+ * Used to indicate that the supplicant daemon is terminating.
+ */
+ oneway void onTerminating();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
new file mode 100644
index 0000000..5394f49
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.FreqRange;
+import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback;
+import android.hardware.wifi.supplicant.ISupplicantP2pNetwork;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.MiracastMode;
+import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+import android.hardware.wifi.supplicant.WpsProvisionMethod;
+
+/**
+ * Interface exposed by the supplicant for each P2P mode network
+ * interface (e.g p2p0) it controls.
+ */
+@VintfStability
+interface ISupplicantP2pIface {
+ /**
+ * This command can be used to add a bonjour service.
+ *
+ * @param query Hex dump of the query data.
+ * @param return Hex dump of the response data.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void addBonjourService(in byte[] query, in byte[] response);
+
+ /**
+ * Set up a P2P group owner manually (i.e., without group owner
+ * negotiation with a specific peer). This is also known as autonomous
+ * group owner. Optional |persistentNetworkId| may be used to specify
+ * restart of a persistent group.
+ *
+ * @param persistent Used to request a persistent group to be formed.
+ * @param persistentNetworkId Used to specify the restart of a persistent
+ * group. Set to UINT32_MAX for a non-persistent group.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void addGroup(in boolean persistent, in int persistentNetworkId);
+
+ /**
+ * Set up a P2P group owner or join a group as a group client
+ * with the specified configuration.
+ *
+ * If joinExistingGroup is false, this device sets up a P2P group owner manually (i.e.,
+ * without group owner negotiation with a specific peer) with the specified SSID,
+ * passphrase, persistent mode, and frequency/band.
+ *
+ * If joinExistingGroup is true, this device acts as a group client and joins the group
+ * whose network name and group owner's MAC address matches the specified SSID
+ * and peer address without WPS process. If peerAddress is 00:00:00:00:00:00, the first found
+ * group whose network name matches the specified SSID is joined.
+ *
+ * @param ssid The SSID of this group.
+ * @param pskPassphrase The passphrase of this group.
+ * @param persistent Used to request a persistent group to be formed,
+ * only applied for the group owner.
+ * @param freq The required frequency or band for this group.
+ * only applied for the group owner.
+ * The following values are supported:
+ * 0: automatic channel selection,
+ * 2: for 2.4GHz channels
+ * 5: for 5GHz channels
+ * specific frequency, i.e., 2412, 5500, etc.
+ * If an invalid band or unsupported frequency are specified, it fails.
+ * @param peerAddress the group owner's MAC address, only applied for the group client.
+ * If the MAC is "00:00:00:00:00:00", the device must try to find a peer
+ * whose network name matches the specified SSID.
+ * @param joinExistingGroup if true, join a group as a group client; otherwise,
+ * create a group as a group owner.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void addGroupWithConfig(in byte[] ssid, in String pskPassphrase, in boolean persistent,
+ in int freq, in byte[] peerAddress, in boolean joinExistingGroup);
+
+ /**
+ * Add a new network to the interface.
+ *
+ * @return AIDL interface object representing the new network if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ @PropagateAllowBlocking ISupplicantP2pNetwork addNetwork();
+
+ /**
+ * This command can be used to add a UPNP service.
+ *
+ * @param version Version to be used.
+ * @package serviceName Service name to be used.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void addUpnpService(in int version, in String serviceName);
+
+ /**
+ * Cancel an ongoing P2P group formation and joining-a-group related
+ * operation. This operation unauthorizes the specific peer device (if any
+ * had been authorized to start group formation), stops P2P find (if in
+ * progress), stops pending operations for join-a-group, and removes the
+ * P2P group interface (if one was used) that is in the WPS provisioning
+ * step. If the WPS provisioning step has been completed, the group is not
+ * terminated.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void cancelConnect();
+
+ /**
+ * Cancel a previous service discovery request.
+ *
+ * @param identifier Identifier for the request to cancel.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void cancelServiceDiscovery(in long identifier);
+
+ /**
+ * Cancel any ongoing WPS operations.
+ *
+ * @param groupIfName Group interface name to use.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void cancelWps(in String groupIfName);
+
+ /**
+ * Configure Extended Listen Timing.
+ *
+ * If enabled, listen state must be entered every |intervalInMillis| for at
+ * least |periodInMillis|. Both values have acceptable range of 1-65535
+ * (with interval obviously having to be larger than or equal to duration).
+ * If the P2P module is not idle at the time the Extended Listen Timing
+ * timeout occurs, the Listen State operation must be skipped.
+ *
+ * @param periodInMillis Period in milliseconds.
+ * @param intervalInMillis Interval in milliseconds.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void configureExtListen(in int periodInMillis, in int intervalInMillis);
+
+ /**
+ * Start P2P group formation with a discovered P2P peer. This includes
+ * optional group owner negotiation, group interface setup, provisioning,
+ * and establishing data connection.
+ *
+ * @param peerAddress MAC address of the device to connect to.
+ * @param provisionMethod Provisioning method to use.
+ * @param preSelectedPin Pin to be used, if |provisionMethod| uses one of the
+ * preselected |PIN*| methods.
+ * @param joinExistingGroup Indicates that this is a command to join an
+ * existing group as a client. It skips the group owner negotiation
+ * part. This must send a Provision Discovery Request message to the
+ * target group owner before associating for WPS provisioning.
+ * @param persistent Used to request a persistent group to be formed.
+ * @param goIntent Used to override the default Intent for this group owner
+ * negotiation (Values from 1-15). Refer to section 4.1.6 in
+ * Wi-Fi Peer-to-Peer (P2P) Technical Specification Version 1.7.
+ * @return Pin generated, if |provisionMethod| uses one of the
+ * generated |PIN*| methods.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ String connect(in byte[] peerAddress, in WpsProvisionMethod provisionMethod,
+ in String preSelectedPin, in boolean joinExistingGroup, in boolean persistent,
+ in int goIntent);
+
+ /**
+ * Creates a NFC handover request message.
+ *
+ * @return Bytes representing the handover request as specified in
+ * section 3.1.1 of NFC Connection Handover 1.2 Technical
+ * Specification.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ byte[] createNfcHandoverRequestMessage();
+
+ /**
+ * Creates a NFC handover select message.
+ *
+ * @return Bytes representing the handover select as specified in
+ * section 3.1.2 of NFC Connection Handover 1.2 Technical
+ * Specification.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ byte[] createNfcHandoverSelectMessage();
+
+ /**
+ * Enable/Disable Wifi Display.
+ *
+ * @param enable true to enable, false to disable.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void enableWfd(in boolean enable);
+
+ /**
+ * Initiate a P2P service discovery with an optional timeout.
+ *
+ * @param timeoutInSec Max time to be spent is performing discovery.
+ * Set to 0 to indefinely continue discovery until an explicit
+ * |stopFind| is sent.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void find(in int timeoutInSec);
+
+ /**
+ * Flush P2P peer table and state.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void flush();
+
+ /**
+ * This command can be used to flush all services from the
+ * device.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void flushServices();
+
+ /**
+ * Gets the MAC address of the device.
+ *
+ * @return MAC address of the device.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ byte[] getDeviceAddress();
+
+ /**
+ * Get whether EDMG(802.11ay) is enabled for this network.
+ *
+ * @return true if set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean getEdmg();
+
+ /**
+ * Gets the capability of the group which the device is a
+ * member of.
+ *
+ * @param peerAddress MAC address of the peer.
+ * @return Combination of |P2pGroupCapabilityMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ P2pGroupCapabilityMask getGroupCapability(in byte[] peerAddress);
+
+ /**
+ * Retrieves the name of the network interface.
+ *
+ * @return Name of the network interface, e.g., wlan0
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ String getName();
+
+ /**
+ * Gets an AIDL interface object for the network corresponding to the
+ * network id.
+ *
+ * Use |ISupplicantP2pNetwork.getId()| on the corresponding network AIDL
+ * interface object to retrieve the ID.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ * @return AIDL interface object representing the new network if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+ */
+ @PropagateAllowBlocking ISupplicantP2pNetwork getNetwork(in int id);
+
+ /**
+ * Gets the operational SSID of the device.
+ *
+ * @param peerAddress MAC address of the peer.
+ * @return SSID of the device
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ byte[] getSsid(in byte[] peerAddress);
+
+ /**
+ * Retrieves the type of the network interface.
+ *
+ * @return Type of the network interface, e.g., STA.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ IfaceType getType();
+
+ /**
+ * Invite a device to a persistent group.
+ * If the peer device is the group owner of the persistent group, the peer
+ * parameter is not needed. Otherwise it is used to specify which
+ * device to invite. |goDeviceAddress| parameter may be used to override
+ * the group owner device address for Invitation Request should it not be
+ * known for some reason (this should not be needed in most cases).
+ *
+ * @param groupIfName Group interface name to use.
+ * @param goDeviceAddress MAC address of the group owner device.
+ * @param peerAddress MAC address of the device to invite.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress);
+
+ /**
+ * Retrieve a list of all the network Id's controlled by the supplicant.
+ *
+ * The corresponding |ISupplicantP2pNetwork| object for any network can be
+ * retrieved using the |getNetwork| method.
+ *
+ * @return List of all network Id's controlled by the supplicant.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ int[] listNetworks();
+
+ /**
+ * Send P2P provision discovery request to the specified peer. The
+ * parameters for this command are the P2P device address of the peer and the
+ * desired configuration method.
+ *
+ * @param peerAddress MAC address of the device to send discovery.
+ * @method provisionMethod Provisioning method to use.
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void provisionDiscovery(in byte[] peerAddress, in WpsProvisionMethod provisionMethod);
+
+ /**
+ * Register for callbacks from this interface.
+ *
+ * These callbacks are invoked for events that are specific to this interface.
+ * Registration of multiple callback objects is supported. These objects must
+ * be automatically deleted when the corresponding client process is dead or
+ * if this interface is removed.
+ *
+ * @param callback An instance of the |ISupplicantP2pIfaceCallback| AIDL
+ * interface object.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void registerCallback(in ISupplicantP2pIfaceCallback callback);
+
+ /**
+ * Reinvoke a device from a persistent group.
+ *
+ * @param persistentNetworkId Used to specify the persistent group.
+ * @param peerAddress MAC address of the device to reinvoke.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void reinvoke(in int persistentNetworkId, in byte[] peerAddress);
+
+ /**
+ * Reject connection attempt from a peer (specified with a device
+ * address). This is a mechanism to reject a pending group owner negotiation
+ * with a peer and request to automatically block any further connection or
+ * discovery of the peer.
+ *
+ * @param peerAddress MAC address of the device to reject.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void reject(in byte[] peerAddress);
+
+ /**
+ * This command can be used to remove a bonjour service.
+ *
+ * @param query Hex dump of the query data.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void removeBonjourService(in byte[] query);
+
+ /**
+ * Terminate a P2P group. If a new virtual network interface was used for
+ * the group, it must also be removed. The network interface name of the
+ * group interface is used as a parameter for this command.
+ *
+ * @param groupIfName Group interface name to use.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void removeGroup(in String groupIfName);
+
+ /**
+ * Remove a network from the interface.
+ *
+ * Use |ISupplicantP2pNetwork.getId()| on the corresponding network AIDL
+ * interface object to retrieve the ID.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+ */
+ void removeNetwork(in int id);
+
+ /**
+ * This command can be used to remove a UPNP service.
+ *
+ * @param version Version to be used.
+ * @package serviceName Service name to be used.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void removeUpnpService(in int version, in String serviceName);
+
+ /**
+ * Report the initiation of the NFC handover select.
+ *
+ * @param select Bytes representing the handover select as specified in
+ * section 3.1.2 of NFC Connection Handover 1.2 Technical
+ * Specification.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void reportNfcHandoverInitiation(in byte[] select);
+
+ /**
+ * Report the response of the NFC handover request.
+ *
+ * @param request Bytes representing the handover request as specified in
+ * section 3.1.1 of NFC Connection Handover 1.2 Technical
+ * Specification.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void reportNfcHandoverResponse(in byte[] request);
+
+ /**
+ * Schedule a P2P service discovery request. The parameters for this command
+ * are the device address of the peer device (or 00:00:00:00:00:00 for
+ * wildcard query that is sent to every discovered P2P peer that supports
+ * service discovery) and P2P Service Query TLV(s) as hexdump.
+ *
+ * @param peerAddress MAC address of the device to discover.
+ * @param query Hex dump of the query data.
+ * @return Identifier for the request. Can be used to cancel the
+ * request.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ long requestServiceDiscovery(in byte[] peerAddress, in byte[] query);
+
+ /**
+ * Persist the current configuration to disk.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void saveConfig();
+
+ /**
+ * Set P2P disallowed frequency ranges.
+ *
+ * Specify ranges of frequencies that are disallowed for any P2P operations.
+ *
+ * @param ranges List of ranges which needs to be disallowed.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setDisallowedFrequencies(in FreqRange[] ranges);
+
+ /**
+ * Set whether to enable EDMG(802.11ay). Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD|
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEdmg(in boolean enable);
+
+ /**
+ * Set the Maximum idle time in seconds for P2P groups.
+ * This value controls how long a P2P group is maintained after there
+ * is no other members in the group. As a group owner, this means no
+ * associated stations in the group. As a P2P client, this means no
+ * group owner seen in scan results.
+ *
+ * @param groupIfName Group interface name to use.
+ * @param timeoutInSec Timeout value in seconds.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setGroupIdle(in String groupIfName, in int timeoutInSec);
+
+ /**
+ * Set P2P Listen channel.
+ *
+ * When specifying a social channel on the 2.4 GHz band (1/6/11) there is no
+ * need to specify the operating class since it defaults to 81. When
+ * specifying a social channel on the 60 GHz band (2), specify the 60 GHz
+ * operating class (180).
+ *
+ * @param channel Wifi channel. eg, 1, 6, 11.
+ * @param operatingClass Operating Class indicates the channel set of the AP
+ * indicated by this BSSID
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setListenChannel(in int channel, in int operatingClass);
+
+ /**
+ * Set MAC randomization enabled/disabled.
+ *
+ * @param enable true to enable, false to disable.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setMacRandomization(in boolean enable);
+
+ /**
+ * Send driver command to set Miracast mode.
+ *
+ * @param mode Mode of Miracast.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setMiracastMode(in MiracastMode mode);
+
+ /**
+ * Turn on/off power save mode for the interface.
+ *
+ * @param groupIfName Group interface name to use.
+ * @param enable Indicate if power save is to be turned on/off.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void setPowerSave(in String groupIfName, in boolean enable);
+
+ /**
+ * Set the postfix to be used for P2P SSID's.
+ *
+ * @param postfix String to be appended to SSID.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setSsidPostfix(in byte[] postfix);
+
+ /**
+ * Set Wifi Display device info.
+ *
+ * @param info WFD device info as described in section 5.1.2 of WFD technical
+ * specification v1.0.0.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setWfdDeviceInfo(in byte[] info);
+
+ /**
+ * Set Wifi Display R2 device info.
+ *
+ * @param info WFD R2 device info as described in section 5.1.12 of WFD technical
+ * specification v2.1.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setWfdR2DeviceInfo(in byte[] info);
+
+ /**
+ * Set the list of supported config methods for WPS operations.
+ *
+ * @param configMethods Mask of WPS configuration methods supported by the
+ * device.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsConfigMethods(in WpsConfigMethods configMethods);
+
+ /**
+ * Set the device name for WPS operations.
+ * User-friendly description of device (up to |WPS_DEVICE_NAME_MAX_LEN|
+ * octets encoded in UTF-8).
+ *
+ * @param name Name to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsDeviceName(in String name);
+
+ /**
+ * Set the device type for WPS operations.
+ *
+ * @param type Type of device. Refer to section B.1 of Wifi P2P
+ * Technical specification v1.2.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsDeviceType(in byte[] type);
+
+ /**
+ * Set the manufacturer for WPS operations.
+ * The manufacturer of the device (up to |WPS_MANUFACTURER_MAX_LEN| ASCII
+ * characters).
+ *
+ * @param manufacturer Manufacture to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsManufacturer(in String manufacturer);
+
+ /**
+ * Set the model name for WPS operations.
+ * Model of the device (up to |WPS_MODEL_NAME_MAX_LEN| ASCII characters).
+ *
+ * @param modelName Model name to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsModelName(in String modelName);
+
+ /**
+ * Set the model number for WPS operations.
+ * Additional device description (up to |WPS_MODEL_NUMBER_MAX_LEN| ASCII
+ * characters).
+ *
+ * @param modelNumber Model number to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsModelNumber(in String modelNumber);
+
+ /**
+ * Set the serial number for WPS operations.
+ * Serial number of the device (up to |WPS_SERIAL_NUMBER_MAX_LEN| characters)
+ *
+ * @param serialNumber Serial number to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsSerialNumber(in String serialNumber);
+
+ /**
+ * Initiate WPS Push Button setup.
+ * The PBC operation requires that a button is also pressed at the
+ * AP/Registrar at about the same time (2 minute window).
+ *
+ * @param groupIfName Group interface name to use.
+ * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startWpsPbc(in String groupIfName, in byte[] bssid);
+
+ /**
+ * Initiate WPS Pin Display setup.
+ *
+ * @param groupIfName Group interface name to use.
+ * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+ * @return 8 digit pin generated.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ String startWpsPinDisplay(in String groupIfName, in byte[] bssid);
+
+ /**
+ * Initiate WPS Pin Keypad setup.
+ *
+ * @param groupIfName Group interface name to use.
+ * @param pin 8 digit pin to be used.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startWpsPinKeypad(in String groupIfName, in String pin);
+
+ /**
+ * Stop an ongoing P2P service discovery.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void stopFind();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
new file mode 100644
index 0000000..f0cabd6
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
+import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
+import android.hardware.wifi.supplicant.P2pStatusCode;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+import android.hardware.wifi.supplicant.WpsDevPasswordId;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each P2P mode interface (ISupplicantP2pIface).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantP2pIface.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantP2pIfaceCallback {
+ /**
+ * Used to indicate that a P2P device has been found.
+ *
+ * @param srcAddress MAC address of the device found. This must either
+ * be the P2P device address or the P2P interface address.
+ * @param p2pDeviceAddress P2P device address.
+ * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+ * Technical specification v1.2.
+ * @param deviceName Name of the device.
+ * @param configMethods Mask of WPS configuration methods supported by the
+ * device.
+ * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+ * technical specification v1.0.0.
+ */
+ oneway void onDeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress,
+ in byte[] primaryDeviceType, in String deviceName, in WpsConfigMethods configMethods,
+ in byte deviceCapabilities, in P2pGroupCapabilityMask groupCapabilities,
+ in byte[] wfdDeviceInfo);
+
+ /**
+ * Used to indicate that a P2P device has been lost.
+ *
+ * @param p2pDeviceAddress P2P device address.
+ */
+ oneway void onDeviceLost(in byte[] p2pDeviceAddress);
+
+ /**
+ * Used to indicate the termination of P2P find operation.
+ */
+ oneway void onFindStopped();
+
+ /**
+ * Used to indicate the completion of a P2P Group Owner negotiation request.
+ *
+ * @param status Status of the GO negotiation.
+ */
+ oneway void onGoNegotiationCompleted(in P2pStatusCode status);
+
+ /**
+ * Used to indicate the reception of a P2P Group Owner negotiation request.
+ *
+ * @param srcAddress MAC address of the device that initiated the GO
+ * negotiation request.
+ * @param passwordId Type of password.
+ */
+ oneway void onGoNegotiationRequest(in byte[] srcAddress, in WpsDevPasswordId passwordId);
+
+ /**
+ * Used to indicate a failure to form a P2P group.
+ *
+ * @param failureReason Failure reason string for debug purposes.
+ */
+ oneway void onGroupFormationFailure(in String failureReason);
+
+ /**
+ * Used to indicate a successful formation of a P2P group.
+ */
+ oneway void onGroupFormationSuccess();
+
+ /**
+ * Used to indicate the removal of a P2P group.
+ *
+ * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+ * @param isGroupOwner Whether this device is owner of the group.
+ */
+ oneway void onGroupRemoved(in String groupIfname, in boolean isGroupOwner);
+
+ /**
+ * Used to indicate the start of a P2P group.
+ *
+ * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+ * @param isGroupOwner Whether this device is owner of the group.
+ * @param ssid SSID of the group.
+ * @param frequency Frequency on which this group is created.
+ * @param psk PSK used to secure the group.
+ * @param passphrase PSK passphrase used to secure the group.
+ * @param goDeviceAddress MAC Address of the owner of this group.
+ * @param isPersistent Whether this group is persisted or not.
+ */
+ oneway void onGroupStarted(in String groupIfname, in boolean isGroupOwner, in byte[] ssid,
+ in int frequency, in byte[] psk, in String passphrase, in byte[] goDeviceAddress,
+ in boolean isPersistent);
+
+ /**
+ * Used to indicate the reception of a P2P invitation.
+ *
+ * @param srcAddress MAC address of the device that sent the invitation.
+ * @param goDeviceAddress MAC Address of the owner of this group.
+ * @param bssid Bssid of the group.
+ * @param persistentNetworkId Persistent network Id of the group.
+ * @param operatingFrequency Frequency on which the invitation was received.
+ */
+ oneway void onInvitationReceived(in byte[] srcAddress, in byte[] goDeviceAddress,
+ in byte[] bssid, in int persistentNetworkId, in int operatingFrequency);
+
+ /**
+ * Used to indicate the result of the P2P invitation request.
+ *
+ * @param bssid Bssid of the group.
+ * @param status Status of the invitation.
+ */
+ oneway void onInvitationResult(in byte[] bssid, in P2pStatusCode status);
+
+ /**
+ * Used to indicate the completion of a P2P provision discovery request.
+ *
+ * @param p2pDeviceAddress P2P device address.
+ * @param isRequest Whether we received or sent the provision discovery.
+ * @param status Status of the provision discovery.
+ * @param configMethods Mask of WPS configuration methods supported.
+ * @param generatedPin 8 digit pin generated.
+ */
+ oneway void onProvisionDiscoveryCompleted(in byte[] p2pDeviceAddress, in boolean isRequest,
+ in P2pProvDiscStatusCode status, in WpsConfigMethods configMethods,
+ in String generatedPin);
+
+ /**
+ * Used to indicate that a P2P Wi-Fi Display R2 device has been found. Refer to
+ * Wi-Fi Display Technical Specification Version 2.0.
+ *
+ * @param srcAddress MAC address of the device found. This must either
+ * be the P2P device address for a peer which is not in a group,
+ * or the P2P interface address for a peer which is a Group Owner.
+ * @param p2pDeviceAddress P2P device address.
+ * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+ * Technical specification v1.2.
+ * @param deviceName Name of the device.
+ * @param configMethods Mask of WPS configuration methods supported by the
+ * device.
+ * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+ * technical specification v1.0.0.
+ * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD
+ * technical specification v2.1.
+ */
+ oneway void onR2DeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress,
+ in byte[] primaryDeviceType, in String deviceName, in WpsConfigMethods configMethods,
+ in byte deviceCapabilities, in P2pGroupCapabilityMask groupCapabilities,
+ in byte[] wfdDeviceInfo, in byte[] wfdR2DeviceInfo);
+
+ /**
+ * Used to indicate the reception of a P2P service discovery response.
+ *
+ * @param srcAddress MAC address of the device that sent the service discovery.
+ * @param updateIndicator Service update indicator. Refer to section 3.1.3 of
+ * Wifi P2P Technical specification v1.2.
+ * @parm tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2.
+ */
+ oneway void onServiceDiscoveryResponse(
+ in byte[] srcAddress, in char updateIndicator, in byte[] tlvs);
+
+ /**
+ * Used to indicate when a STA device is connected to this device.
+ *
+ * @param srcAddress MAC address of the device that was authorized.
+ * @param p2pDeviceAddress P2P device address.
+ */
+ oneway void onStaAuthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+
+ /**
+ * Used to indicate when a STA device is disconnected from this device.
+ *
+ * @param srcAddress MAC address of the device that was deauthorized.
+ * @param p2pDeviceAddress P2P device address.
+ */
+ oneway void onStaDeauthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
new file mode 100644
index 0000000..f037252
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.MacAddress;
+
+/**
+ * Interface exposed by the supplicant for each P2P mode network
+ * configuration it controls.
+ */
+@VintfStability
+interface ISupplicantP2pNetwork {
+ /**
+ * Get the BSSID set for this network.
+ *
+ * @return bssid Value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getBssid();
+
+ /**
+ * Get the list of P2P Clients in a persistent group (GO).
+ * This is a list of P2P Clients (P2P Device Address) that have joined
+ * the persistent group. This is maintained on the GO for persistent
+ * group entries (disabled == 2).
+ *
+ * @return MAC addresses of the clients.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ MacAddress[] getClientList();
+
+ /**
+ * Retrieves the ID allocated to this network by the supplicant.
+ *
+ * This is not the |SSID| of the network, but an internal identifier for
+ * this network used by the supplicant.
+ *
+ * @return Network ID.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ int getId();
+
+ /**
+ * Retrieves the name of the interface this network belongs to.
+ *
+ * @return Name of the network interface, e.g., wlan0
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getInterfaceName();
+
+ /**
+ * Getters for the various network params.
+ *
+ *
+ * Get SSID for this network.
+ *
+ * @return ssid value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getSsid();
+
+ /**
+ * Retrieves the type of the interface this network belongs to.
+ *
+ * @return Type of the network interface, e.g., STA.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ IfaceType getType();
+
+ /**
+ * Check if the network is currently active one.
+ *
+ * @return true if current, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean isCurrent();
+
+ /**
+ * Check if the device is the group owner of the network.
+ *
+ * @return true if group owner, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean isGroupOwner();
+
+ /**
+ * Check if the network is marked persistent.
+ *
+ * @return true if persistent, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean isPersistent();
+
+ /**
+ * Set the list of P2P Clients in a persistent group (GO).
+ * This is a list of P2P Clients (P2P Device Address) that have joined
+ * the persistent group. This is maintained on the GO for persistent
+ * group entries (disabled == 2).
+ *
+ * @param clients MAC address of the clients.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setClientList(in MacAddress[] clients);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
new file mode 100644
index 0000000..5cb236f
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AnqpInfoId;
+import android.hardware.wifi.supplicant.BtCoexistenceMode;
+import android.hardware.wifi.supplicant.ConnectionCapabilities;
+import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppCurve;
+import android.hardware.wifi.supplicant.DppNetRole;
+import android.hardware.wifi.supplicant.DppResponderBootstrapInfo;
+import android.hardware.wifi.supplicant.Hs20AnqpSubtypes;
+import android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback;
+import android.hardware.wifi.supplicant.ISupplicantStaNetwork;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
+import android.hardware.wifi.supplicant.RxFilterType;
+import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+@VintfStability
+interface ISupplicantStaIface {
+ /**
+ * Add a DPP peer URI. URI is acquired externally, e.g. by scanning a QR code
+ *
+ * @param uri Peer's DPP URI.
+ * @return ID for the URI
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ int addDppPeerUri(in String uri);
+
+ /**
+ * External programs can request supplicant to not start offchannel
+ * operations during other tasks that may need exclusive control of the
+ * radio.
+ *
+ * This method can be used to reserve a slot for radio access. If freq is
+ * specified, other radio work items on the same channel can be completed in
+ * parallel. Otherwise, all other radio work items are blocked during
+ * execution. Timeout must be set to |ExtRadioWorkDefaults.TIMEOUT_IN_SECS|
+ * seconds by default to avoid blocking supplicant operations on the iface
+ * for excessive time. If a longer (or shorter) safety timeout is needed,
+ * that may be specified with the optional timeout parameter. This command
+ * returns an identifier for the radio work item.
+ *
+ * Once the radio work item has been started,
+ * |ISupplicant.onExtRadioWorkStart| callback is indicated that the external
+ * processing can start.
+ *
+ * @param name Name for the radio work being added.
+ * @param freqInMhz Frequency to specify. Set to 0 for all channels.
+ * @param timeoutInSec Timeout to specify. Set to 0 for default timeout.
+ * @return Identifier for this radio work.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ int addExtRadioWork(in String name, in int freqInMhz, in int timeoutInSec);
+
+ /**
+ * Add a new network to the interface.
+ *
+ * @return AIDL interface object representing the new network if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ @PropagateAllowBlocking ISupplicantStaNetwork addNetwork();
+
+ /**
+ * Send driver command to add the specified RX filter.
+ *
+ * @param type Type of filter.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void addRxFilter(in RxFilterType type);
+
+ /**
+ * Cancel any ongoing WPS operations.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void cancelWps();
+
+ /**
+ * Disconnect from the current active network.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void disconnect();
+
+ /**
+ * Enable/Disable auto reconnect to networks.
+ * Use this to prevent wpa_supplicant from trying to connect to networks
+ * on its own.
+ *
+ * @param enable true to enable, false to disable.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void enableAutoReconnect(in boolean enable);
+
+ /**
+ * Add fast initial link setup (IEEE 802.11ai FILS) HLP packets.
+ * Use this to add higher layer protocol (HLP) packet in FILS (Re)Association Request frame
+ * (Eg: DHCP discover packet).
+ *
+ * @param dst_mac MAC address of the destination
+ * @param pkt The contents of the HLP packet starting from ethertype
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void filsHlpAddRequest(in byte[] dst_mac, in byte[] pkt);
+
+ /**
+ * Flush fast initial link setup (IEEE 802.11ai FILS) HLP packets.
+ * Use this to flush all the higher layer protocol (HLP) packets added in
+ * wpa_supplicant to send in FILS (Re)Association Request frame
+ * (Eg: DHCP discover packet).
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void filsHlpFlushRequest();
+
+ /**
+ * Generates DPP bootstrap information: Bootstrap ID, DPP URI and listen
+ * channel for responder mode.
+ *
+ * @param macAddress MAC address of the interface for the DPP operation.
+ * @param deviceInfo Device specific information.
+ * As per DPP Specification V1.0 section 5.2,
+ * allowed Range of ASCII characters in deviceInfo - %x20-7E
+ * semicolon is not allowed.
+ * @param curve Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ * @return Bootstrap info.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ DppResponderBootstrapInfo generateDppBootstrapInfoForResponder(
+ in byte[] macAddress, in String deviceInfo, in DppCurve curve);
+
+ /**
+ * Get Connection capabilities
+ *
+ * @return Connection capabilities.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ ConnectionCapabilities getConnectionCapabilities();
+
+ /**
+ * Get Key management capabilities of the device
+ *
+ * @return Bitmap of key management mask.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ KeyMgmtMask getKeyMgmtCapabilities();
+
+ /**
+ * Send driver command to get MAC address of the device.
+ *
+ * @return MAC address of the device.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ byte[] getMacAddress();
+
+ /**
+ * Retrieves the name of the network interface.
+ *
+ * @return Name of the network interface, e.g., wlan0
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ String getName();
+
+ /**
+ * Gets an AIDL interface object for the network corresponding to the
+ * network id.
+ *
+ * Use |ISupplicantStaNetwork.getId()| on the corresponding network AIDL
+ * interface object to retrieve the ID.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ * @return AIDL interface object representing the new network if
+ * successful, null otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+ */
+ @PropagateAllowBlocking ISupplicantStaNetwork getNetwork(in int id);
+
+ /**
+ * Retrieves the type of the network interface.
+ *
+ * @return Type of the network interface, e.g., STA.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ IfaceType getType();
+
+ /**
+ * Get wpa driver capabilities.
+ *
+ * @return Bitmap of wpa driver features.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ WpaDriverCapabilitiesMask getWpaDriverCapabilities();
+
+ /**
+ * Initiate ANQP (for IEEE 802.11u Interworking/Hotspot 2.0) queries with the
+ * specified access point.
+ * The ANQP data fetched must be returned in the
+ * |ISupplicantStaIfaceCallback.onAnqpQueryDone| callback.
+ *
+ * @param macAddress MAC address of the access point.
+ * @param infoElements List of information elements to query for.
+ * @param subtypes List of HS20 subtypes to query for.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateAnqpQuery(
+ in byte[] macAddress, in AnqpInfoId[] infoElements, in Hs20AnqpSubtypes[] subTypes);
+
+ /**
+ * Initiate the Hotspot 2.0 icon query with the specified accesss point.
+ * The icon data fetched must be returned in the
+ * |ISupplicantStaIfaceCallback.onHs20IconQueryDone| callback.
+ *
+ * @param macAddress MAC address of the access point.
+ * @param fileName Name of the file to request from the access point.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateHs20IconQuery(in byte[] macAddress, in String fileName);
+
+ /**
+ * Initiate TDLS discover with the provided peer MAC address.
+ *
+ * @param macAddress MAC address of the peer.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateTdlsDiscover(in byte[] macAddress);
+
+ /**
+ * Initiate TDLS setup with the provided peer MAC address.
+ *
+ * @param macAddress MAC address of the peer.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateTdlsSetup(in byte[] macAddress);
+
+ /**
+ * Initiate TDLS teardown with the provided peer MAC address.
+ *
+ * @param macAddress MAC address of the peer.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateTdlsTeardown(in byte[] macAddress);
+
+ /**
+ * Initiate Venue URL ANQP (for IEEE 802.11u Interworking/Hotspot 2.0) query with the
+ * specified access point. This specific query can be used only post connection, once security
+ * is established and PMF is enabled, to avoid spoofing preassociation ANQP responses.
+ * The ANQP data fetched must be returned in the
+ * |ISupplicantStaIfaceCallback.onAnqpQueryDone| callback.
+ *
+ * @param macAddress MAC address of the access point.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void initiateVenueUrlAnqpQuery(in byte[] macAddress);
+
+ /**
+ * Retrieve a list of all the network Id's controlled by the supplicant.
+ *
+ * The corresponding |ISupplicantStaNetwork| object for any network can be
+ * retrieved using |getNetwork| method.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return List of all network Id's controlled by the supplicant.
+ */
+ int[] listNetworks();
+
+ /**
+ * Reconnect to the currently active network, even if we are already
+ * connected.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void reassociate();
+
+ /**
+ * Reconnect to the currently active network, if we are currently
+ * disconnected.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|,
+ * |SupplicantStatusCode.FAILURE_IFACE_NOT_DISCONNECTED|
+ */
+ void reconnect();
+
+ /**
+ * Register for callbacks from this interface.
+ *
+ * These callbacks are invoked for events that are specific to this interface.
+ * Registration of multiple callback objects is supported. These objects must
+ * be automatically deleted when the corresponding client process is dead or
+ * if this interface is removed.
+ *
+ * @param callback An instance of the |ISupplicantStaIfaceCallback| AIDL
+ * interface object.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void registerCallback(in ISupplicantStaIfaceCallback callback);
+
+ /**
+ * Remove a DPP peer URI.
+ *
+ * @param id The ID of the URI, as returned by |addDppPeerUri|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void removeDppUri(in int id);
+
+ /**
+ * Indicates to supplicant that the external radio work has completed.
+ * This allows other radio works to be performed. If this method is not
+ * invoked (e.g., due to the external program terminating), supplicant
+ * must time out the radio work item on the iface and send
+ * |ISupplicantCallback.onExtRadioWorkTimeout| event to indicate
+ * that this has happened.
+ *
+ * This method may also be used to cancel items that have been scheduled
+ * via |addExtRadioWork|, but have not yet been started (notified via
+ * |ISupplicantCallback.onExtRadioWorkStart|).
+ *
+ * @param id Identifier generated for the radio work addition
+ * (using |addExtRadioWork|).
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void removeExtRadioWork(in int id);
+
+ /**
+ * Remove a network from the interface.
+ *
+ * Use |ISupplicantStaNetwork.getId()| on the corresponding network AIDL
+ * interface object to retrieve the ID.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+ */
+ void removeNetwork(in int id);
+
+ /**
+ * Send driver command to remove the specified RX filter.
+ *
+ * @param type Type of filter.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void removeRxFilter(in RxFilterType type);
+
+ /**
+ * Send driver command to set Bluetooth coexistence mode.
+ *
+ * @param mode Mode of Bluetooth coexistence.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setBtCoexistenceMode(in BtCoexistenceMode mode);
+
+ /**
+ * Send driver command to set Bluetooth coexistence scan mode.
+ * When this mode is on, some of the low-level scan parameters
+ * used by the driver are changed to reduce interference
+ * with A2DP streaming.
+ *
+ * @param enable true to enable, false to disable.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setBtCoexistenceScanModeEnabled(in boolean enable);
+
+ /**
+ * Send driver command to set country code.
+ *
+ * @param code 2 byte country code (as defined in ISO 3166) to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setCountryCode(in byte[] code);
+
+ /**
+ * Use external processing for SIM/USIM operations
+ *
+ * @param useExternalSim true to use external, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setExternalSim(in boolean useExternalSim);
+
+ /**
+ * Set Wi-Fi Alliance Agile Multiband (MBO) cellular data status.
+ *
+ * @param available true means cellular data available, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setMboCellularDataStatus(in boolean available);
+
+ /**
+ * Turn on/off power save mode for the interface.
+ *
+ * @param enable Indicate if power save is to be turned on/off.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+ */
+ void setPowerSave(in boolean enable);
+
+ /**
+ * Send driver command to set suspend optimizations for power save.
+ *
+ * @param enable true to enable, false to disable.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void setSuspendModeEnabled(in boolean enable);
+
+ /**
+ * Set the list of supported config methods for WPS operations.
+ *
+ * @param configMethods Mask of WPS configuration methods supported by the
+ * device.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsConfigMethods(in WpsConfigMethods configMethods);
+
+ /**
+ * Set the device name for WPS operations.
+ * User-friendly description of device (up to |WPS_DEVICE_NAME_MAX_LEN|
+ * octets encoded in UTF-8).
+ *
+ * @parm name Name to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsDeviceName(in String name);
+
+ /**
+ * Set the device type for WPS operations.
+ *
+ * @parm type Type of device. Refer to section B.1 of Wifi P2P
+ * Technical specification v1.2.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsDeviceType(in byte[] type);
+
+ /**
+ * Set the manufacturer for WPS operations.
+ * The manufacturer of the device (up to |WPS_MANUFACTURER_MAX_LEN| ASCII
+ * characters).
+ *
+ * @parm manufacturer Manufacture to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsManufacturer(in String manufacturer);
+
+ /**
+ * Set the model name for WPS operations.
+ * Model of the device (up to |WPS_MODEL_NAME_MAX_LEN| ASCII characters).
+ *
+ * @parm modelName Model name to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsModelName(in String modelName);
+
+ /**
+ * Set the model number for WPS operations.
+ * Additional device description (up to |WPS_MODEL_NUMBER_MAX_LEN| ASCII
+ * characters).
+ *
+ * @parm modelNumber Model number to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsModelNumber(in String modelNumber);
+
+ /**
+ * Set the serial number for WPS operations.
+ * Serial number of the device (up to |WPS_SERIAL_NUMBER_MAX_LEN| characters)
+ *
+ * @parm serialNumber Serial number to be set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWpsSerialNumber(in String serialNumber);
+
+ /**
+ * Start DPP in Configurator-Initiator mode.
+ *
+ * @param peerBootstrapId Peer device's URI ID.
+ * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+ * @param ssid Network SSID to send to peer (SAE/PSK mode).
+ * @param password Network password to send to peer (SAE/PSK mode).
+ * @param psk Network PSK to send to peer (PSK mode only). Either password or psk should be set.
+ * @param netRole Role to configure the peer, |DppNetRole.DPP_NET_ROLE_STA| or
+ * |DppNetRole.DPP_NET_ROLE_AP|.
+ * @param securityAkm Security AKM to use (See DppAkm).
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void startDppConfiguratorInitiator(in int peerBootstrapId, in int ownBootstrapId,
+ in String ssid, in String password, in String psk, in DppNetRole netRole,
+ in DppAkm securityAkm);
+
+ /**
+ * Start DPP in Enrollee-Initiator mode.
+ *
+ * @param peerBootstrapId Peer device's URI ID.
+ * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void startDppEnrolleeInitiator(in int peerBootstrapId, in int ownBootstrapId);
+
+ /**
+ * Start DPP in Enrollee-Responder mode.
+ * Framework must first call |generateDppBootstrapInfoForResponder| to generate
+ * the bootstrapping information: Bootstrap ID, DPP URI and the listen channel.
+ * Then call this API with derived listen channel to start listening for
+ * authentication request from Peer initiator.
+ *
+ * @param listenChannel DPP listen channel.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ void startDppEnrolleeResponder(in int listenChannel);
+
+ /**
+ * Send driver command to start RX filter.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startRxFilter();
+
+ /**
+ * Initiate WPS Push Button setup.
+ * The PBC operation requires that a button is also pressed at the
+ * AP/Registrar at about the same time (2 minute window).
+ *
+ * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startWpsPbc(in byte[] bssid);
+
+ /**
+ * Initiate WPS Pin Display setup.
+ *
+ * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * @return 8 digit pin generated.
+ */
+ String startWpsPinDisplay(in byte[] bssid);
+
+ /**
+ * Initiate WPS Pin Keypad setup.
+ *
+ * @param pin 8 digit pin to be used.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startWpsPinKeypad(in String pin);
+
+ /**
+ * Initiate WPS setup in registrar role to learn the current AP configuration.
+ *
+ * @param bssid BSSID of the AP.
+ * @param pin Pin of the AP.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void startWpsRegistrar(in byte[] bssid, in String pin);
+
+ /**
+ * Stop DPP Initiator operation.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void stopDppInitiator();
+
+ /**
+ * Stop DPP Responder operation - Remove the bootstrap code and stop listening.
+ *
+ * @param ownBootstrapId Local device's URI ID obtained through
+ * |generateDppBootstrapInfoForResponder| call.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ void stopDppResponder(in int ownBootstrapId);
+
+ /**
+ * Send driver command to stop RX filter.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ void stopRxFilter();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
new file mode 100644
index 0000000..594fef9
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AnqpData;
+import android.hardware.wifi.supplicant.AssociationRejectionData;
+import android.hardware.wifi.supplicant.BssTmData;
+import android.hardware.wifi.supplicant.BssidChangeReason;
+import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppEventType;
+import android.hardware.wifi.supplicant.DppFailureCode;
+import android.hardware.wifi.supplicant.DppProgressCode;
+import android.hardware.wifi.supplicant.Hs20AnqpData;
+import android.hardware.wifi.supplicant.OsuMethod;
+import android.hardware.wifi.supplicant.StaIfaceCallbackState;
+import android.hardware.wifi.supplicant.StaIfaceReasonCode;
+import android.hardware.wifi.supplicant.WpsConfigError;
+import android.hardware.wifi.supplicant.WpsErrorIndication;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantStaIfaceCallback {
+ /**
+ * Used to indicate the result of ANQP (either for IEEE 802.11u Interworking
+ * or Hotspot 2.0) query.
+ *
+ * @param bssid BSSID of the access point.
+ * @param data ANQP data fetched from the access point.
+ * All the fields in this struct must be empty if the query failed.
+ * @param hs20Data ANQP data fetched from the Hotspot 2.0 access point.
+ * All the fields in this struct must be empty if the query failed.
+ */
+ oneway void onAnqpQueryDone(in byte[] bssid, in AnqpData data, in Hs20AnqpData hs20Data);
+
+ /**
+ * Used to indicate an association rejection received from the AP
+ * to which the connection is being attempted.
+ *
+ * @param assocRejectData Association Rejection related information.
+ */
+ oneway void onAssociationRejected(in AssociationRejectionData assocRejectData);
+
+ /**
+ * Used to indicate the timeout of authentication to an AP.
+ *
+ * @param bssid BSSID of the corresponding AP.
+ */
+ oneway void onAuthenticationTimeout(in byte[] bssid);
+
+ /**
+ * Indicates BTM request frame handling status.
+ *
+ * @param tmData Data retrieved from received BSS transition management
+ * request frame.
+ */
+ oneway void onBssTmHandlingDone(in BssTmData tmData);
+
+ /**
+ * Used to indicate the change of active bssid.
+ * This is useful to figure out when the driver/firmware roams to a bssid
+ * on its own.
+ *
+ * @param reason Reason why the bssid changed.
+ * @param bssid BSSID of the corresponding AP.
+ */
+ oneway void onBssidChanged(in BssidChangeReason reason, in byte[] bssid);
+
+ /**
+ * Used to indicate the disconnection from the currently connected
+ * network on this iface.
+ *
+ * @param bssid BSSID of the AP from which we disconnected.
+ * @param locallyGenerated If the disconnect was triggered by
+ * wpa_supplicant.
+ * @param reasonCode 802.11 code to indicate the disconnect reason
+ * from access point. Refer to section 8.4.1.7 of IEEE802.11 spec.
+ */
+ oneway void onDisconnected(
+ in byte[] bssid, in boolean locallyGenerated, in StaIfaceReasonCode reasonCode);
+
+ /**
+ * Indicates a DPP failure event.
+ *
+ * ssid: A string indicating the SSID for the AP that the Enrollee attempted to connect.
+ * channelList: A string containing a list of operating channels and operating classes
+ * indicating the channels that the Enrollee scanned in attempting to discover the AP.
+ * The list conforms to the following ABNF syntax:
+ * channel-list2 = class-and-channels *(“,” class-and-channels)
+ * class-and-channels = class “/” channel *(“,” channel)
+ * class = 1*3DIGIT
+ * channel = 1*3DIGIT
+ * bandList: A list of band parameters that are supported by the Enrollee expressed as the
+ * Operating Class.
+ */
+ oneway void onDppFailure(
+ in DppFailureCode code, in String ssid, in String channelList, in char[] bandList);
+
+ /**
+ * Indicates a DPP progress event.
+ */
+ oneway void onDppProgress(in DppProgressCode code);
+
+ /**
+ * Indicates a DPP success event.
+ */
+ oneway void onDppSuccess(in DppEventType event);
+
+ /**
+ * Indicates DPP configuration received success event (Enrolee mode).
+ */
+ oneway void onDppSuccessConfigReceived(
+ in byte[] ssid, in String password, in byte[] psk, in DppAkm securityAkm);
+
+ /**
+ * Indicates DPP configuration sent success event (Configurator mode).
+ */
+ oneway void onDppSuccessConfigSent();
+
+ /**
+ * Indicates an EAP authentication failure.
+ * @param errorCode Error code for EAP authentication failure.
+ * Either standard error code (enum EapErrorCode) or
+ * private error code defined by network provider.
+ */
+ oneway void onEapFailure(in int errorCode);
+
+ /**
+ * Used to indicate that the external radio work can start now.
+ *
+ * @param id Identifier generated for the radio work request.
+ */
+ oneway void onExtRadioWorkStart(in int id);
+
+ /**
+ * Used to indicate that the external radio work request has timed out.
+ *
+ * @param id Identifier generated for the radio work request.
+ */
+ oneway void onExtRadioWorkTimeout(in int id);
+
+ /**
+ * Used to indicate a Hotspot 2.0 imminent deauth notice.
+ *
+ * @param bssid BSSID of the access point.
+ * @param reasonCode Code to indicate the deauth reason.
+ * Refer to section 3.2.1.2 of the Hotspot 2.0 spec.
+ * @param reAuthDelayInSec Delay before reauthenticating.
+ * @param url URL of the server.
+ */
+ oneway void onHs20DeauthImminentNotice(
+ in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
+
+ /**
+ * Used to indicate the result of Hotspot 2.0 Icon query.
+ *
+ * @param bssid BSSID of the access point.
+ * @param fileName Name of the file that was requested.
+ * @param data Icon data fetched from the access point.
+ * Must be empty if the query failed.
+ */
+ oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
+
+ /**
+ * Used to indicate a Hotspot 2.0 subscription remediation event.
+ *
+ * @param bssid BSSID of the access point.
+ * @param osuMethod OSU method.
+ * @param url URL of the server.
+ */
+ oneway void onHs20SubscriptionRemediation(
+ in byte[] bssid, in OsuMethod osuMethod, in String url);
+
+ /**
+ * Used to indicate a Hotspot 2.0 terms and conditions acceptance is requested from the user
+ * before allowing the device to get internet access.
+ *
+ * @param bssid BSSID of the access point.
+ * @param url URL of the T&C server.
+ */
+ oneway void onHs20TermsAndConditionsAcceptanceRequestedNotification(
+ in byte[] bssid, in String url);
+
+ /**
+ * Used to indicate that a new network has been added.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ */
+ oneway void onNetworkAdded(in int id);
+
+ /**
+ * Used to indicate that the supplicant failed to find a network in scan result
+ * which matches with the network capabilities requested by upper layer
+ * for connection.
+ *
+ * @param ssid network name supplicant tried to connect.
+ */
+ oneway void onNetworkNotFound(in byte[] ssid);
+
+ /**
+ * Used to indicate that a network has been removed.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ */
+ oneway void onNetworkRemoved(in int id);
+
+ /**
+ * Indicates pairwise master key (PMK) cache added event.
+ *
+ * @param expirationTimeInSec expiration time in seconds
+ * @param serializedEntry is serialized PMK cache entry, the content is
+ * opaque for the framework and depends on the native implementation.
+ */
+ oneway void onPmkCacheAdded(in long expirationTimeInSec, in byte[] serializedEntry);
+
+ /**
+ * Used to indicate a state change event on this particular iface. If this
+ * event is triggered by a particular network, the |SupplicantNetworkId|,
+ * |ssid|, |bssid| parameters must indicate the parameters of the network/AP
+ * which caused this state transition.
+ *
+ * @param newState New State of the interface. This must be one of the |State|
+ * values above.
+ * @param bssid BSSID of the corresponding AP which caused this state
+ * change event. This must be zero'ed if this event is not
+ * specific to a particular network.
+ * @param id ID of the corresponding network which caused this
+ * state change event. This must be invalid (UINT32_MAX) if this
+ * event is not specific to a particular network.
+ * @param ssid SSID of the corresponding network which caused this state
+ * change event. This must be empty if this event is not specific
+ * to a particular network.
+ * @param filsHlpSent If FILS HLP IEs were included in this association.
+ */
+ oneway void onStateChanged(in StaIfaceCallbackState newState, in byte[] bssid, in int id,
+ in byte[] ssid, in boolean filsHlpSent);
+
+ /**
+ * Used to indicate the failure of a WPS connection attempt.
+ *
+ * @param bssid BSSID of the AP to which we initiated WPS
+ * connection.
+ * @param configError Configuration error code.
+ * @param errorInd Error indication code.
+ */
+ oneway void onWpsEventFail(
+ in byte[] bssid, in WpsConfigError configError, in WpsErrorIndication errorInd);
+
+ /**
+ * Used to indicate the overlap of a WPS PBC connection attempt.
+ */
+ oneway void onWpsEventPbcOverlap();
+
+ /**
+ * Used to indicate the success of a WPS connection attempt.
+ */
+ oneway void onWpsEventSuccess();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
new file mode 100644
index 0000000..603e2ad
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AuthAlgMask;
+import android.hardware.wifi.supplicant.EapMethod;
+import android.hardware.wifi.supplicant.EapPhase2Method;
+import android.hardware.wifi.supplicant.GroupCipherMask;
+import android.hardware.wifi.supplicant.GroupMgmtCipherMask;
+import android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
+import android.hardware.wifi.supplicant.NetworkResponseEapSimGsmAuthParams;
+import android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams;
+import android.hardware.wifi.supplicant.OcspType;
+import android.hardware.wifi.supplicant.PairwiseCipherMask;
+import android.hardware.wifi.supplicant.ProtoMask;
+import android.hardware.wifi.supplicant.SaeH2eMode;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * configuration it controls.
+ */
+@VintfStability
+interface ISupplicantStaNetwork {
+ /**
+ * Max length of SSID param.
+ */
+ const int SSID_MAX_LEN_IN_BYTES = 32;
+
+ /**
+ * Min length of PSK passphrase param.
+ */
+ const int PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8;
+
+ /**
+ * Max length of PSK passphrase param.
+ */
+ const int PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63;
+
+ /**
+ * Max number of WEP keys param.
+ */
+ const int WEP_KEYS_MAX_NUM = 4;
+
+ /**
+ * Length of each WEP40 keys param.
+ */
+ const int WEP40_KEY_LEN_IN_BYTES = 5;
+
+ /**
+ * Length of each WEP104 keys param.
+ */
+ const int WEP104_KEY_LEN_IN_BYTES = 13;
+
+ /**
+ * Disable the network for connection purposes.
+ *
+ * This must trigger a disconnection from the network, if currently
+ * connected to this one.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void disable();
+
+ /**
+ * Enable the network for connection purposes.
+ *
+ * This must trigger a connection to the network if:
+ * a) |noConnect| is false, and
+ * b) This is the only network configured, and
+ * c) Is visible in the current scan results.
+ *
+ * @param noConnect Only enable the network, don't trigger a connect.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void enable(in boolean noConnect);
+
+ /**
+ * Set whether to enable SAE PK (Public Key) only mode to enable public AP validation.
+ * When enabled, only SAE PK network is allowed; otherwise PK is optional.
+ * If this API is not called before connecting to an SAE
+ * network, SAE PK mode depends on SAE PK config in wpa_supplicant configuration.
+ * If SAE PK config of wpa_supplicant configuration is not set,
+ * the default mode is optional (support for both PK and standard mode).
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ void enableSaePkOnlyMode(in boolean enable);
+
+ /**
+ * Set EAP OpenSSL Suite-B-192 ciphers for WPA3-Enterprise
+ * Supported option:
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void enableSuiteBEapOpenSslCiphers();
+
+ /**
+ * Enable TLS Suite-B in EAP Phase1
+ *
+ * @param enable Set to true to enable TLS Suite-B in EAP phase1
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void enableTlsSuiteBEapPhase1Param(in boolean enable);
+
+ /**
+ * Get the auth alg mask set for the network.
+ *
+ * @return Combination of |AuthAlgMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ AuthAlgMask getAuthAlg();
+
+ /**
+ * Get the BSSID set for this network.
+ *
+ * @return bssid Value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getBssid();
+
+ /**
+ * Get EAP Alt subject match set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapAltSubjectMatch();
+
+ /**
+ * Get EAP Anonymous Identity set for this network.
+ *
+ * @return identity value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getEapAnonymousIdentity();
+
+ /**
+ * Get EAP CA certificate file path set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapCACert();
+
+ /**
+ * Get EAP CA certificate directory path set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapCAPath();
+
+ /**
+ * Get EAP Client certificate file path set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapClientCert();
+
+ /**
+ * Get EAP Domain suffix match set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapDomainSuffixMatch();
+
+ /**
+ * Get whether EAP Open SSL Engine is enabled for this network.
+ *
+ * @return true if set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean getEapEngine();
+
+ /**
+ * Get EAP Open SSL Engine ID set for this network.
+ *
+ * @return value set.
+ * throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapEngineId();
+
+ /**
+ * Get EAP Identity set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getEapIdentity();
+
+ /**
+ * Get EAP Method set for this network.
+ *
+ * @return value set.
+ * Must be one of |EapMethod| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ EapMethod getEapMethod();
+
+ /**
+ * Get EAP Password set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getEapPassword();
+
+ /**
+ * Get EAP Phase2 Method set for this network.
+ *
+ * @return value set.
+ * Must be one of |EapPhase2Method| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ EapPhase2Method getEapPhase2Method();
+
+ /**
+ * Get EAP private key Id set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|)
+ */
+ String getEapPrivateKeyId();
+
+ /**
+ * Get EAP subject match set for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getEapSubjectMatch();
+
+ /**
+ * Get whether enhanced directional multi-gigabit (802.11ay EDMG) is enabled for this network.
+ *
+ * @return true if set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean getEdmg();
+
+ /**
+ * Get the group cipher mask set for the network.
+ *
+ * @return Combination of |GroupCipherMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ GroupCipherMask getGroupCipher();
+
+ /**
+ * Get the group management cipher mask set for the network.
+ *
+ * @return Combination of |GroupMgmtCipherMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ GroupMgmtCipherMask getGroupMgmtCipher();
+
+ /**
+ * Retrieves the ID allocated to this network by the supplicant.
+ *
+ * This is not the |SSID| of the network, but an internal identifier for
+ * this network used by the supplicant.
+ *
+ * @return Network ID.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ int getId();
+
+ /**
+ * Get ID string set for this network.
+ * Network identifier string for external scripts.
+ *
+ * @return ID string set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getIdStr();
+
+ /**
+ * Retrieves the name of the interface this network belongs to.
+ *
+ * @return Name of the network interface, e.g., wlan0
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getInterfaceName();
+
+ /**
+ * Get the key mgmt mask set for the network.
+ *
+ * @return Combination of |KeyMgmtMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ KeyMgmtMask getKeyMgmt();
+
+ /**
+ * Get OCSP (Online Certificate Status Protocol) type for this network.
+ *
+ * @return ocsp type.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ OcspType getOcsp();
+
+ /**
+ * Get the pairwise cipher mask set for the network.
+ *
+ * @return Combination of |PairwiseCipherMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ PairwiseCipherMask getPairwiseCipher();
+
+ /**
+ * Get the proto mask set for the network.
+ *
+ * @return Combination of |ProtoMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ ProtoMask getProto();
+
+ /**
+ * Get raw psk for WPA_PSK network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getPsk();
+
+ /**
+ * Get passphrase for WPA_PSK network.
+ * Must return a failure if network has no passphrase set (use |getPsk| if
+ * network was configured with raw psk instead).
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getPskPassphrase();
+
+ /**
+ * Get whether RequirePmf is enabled for this network.
+ *
+ * @return true if set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean getRequirePmf();
+
+ /**
+ * Get SAE password for WPA3-Personal
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getSaePassword();
+
+ /**
+ * Get SAE password ID for WPA3-Personal
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ String getSaePasswordId();
+
+ /**
+ * Get whether Probe Requests are being sent for this network (hidden).
+ *
+ * @return true if set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ boolean getScanSsid();
+
+ /**
+ *
+ * Getters for the various network params.
+ *
+ */
+
+ /**
+ * Get SSID for this network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getSsid();
+
+ /**
+ * Retrieves the type of the interface this network belongs to.
+ *
+ * @return Type of the network interface, e.g., STA.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ IfaceType getType();
+
+ /**
+ * Get WAPI certificate suite name set for this network.
+ *
+ * @return The name of a suite.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ String getWapiCertSuite();
+
+ /**
+ * Get WEP key for WEP network.
+ *
+ * @param keyIdx Index of wep key to be fetched.
+ * Max of |WEP_KEYS_MAX_NUM|.
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getWepKey(in int keyIdx);
+
+ /**
+ * Get default Tx key index for WEP network.
+ *
+ * @return value set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ int getWepTxKeyIdx();
+
+ /**
+ * Retrieves a WPS-NFC configuration token for this network.
+ *
+ * @return Bytes representing WPS-NFC configuration token.
+ * This is a dump of all the WPS atrributes of the AP configuration
+ * as specified in the Wi-Fi Protected Setup Specification.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ byte[] getWpsNfcConfigurationToken();
+
+ /**
+ * Register for callbacks from this network.
+ *
+ * These callbacks are invoked for events that are specific to this network.
+ * Registration of multiple callback objects is supported. These objects must
+ * be automatically deleted when the corresponding client process is dead or
+ * if this network is removed.
+ *
+ * @param callback An instance of the |ISupplicantStaNetworkCallback| AIDL
+ * interface object.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void registerCallback(in ISupplicantStaNetworkCallback callback);
+
+ /**
+ * Initiate connection to this network.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void select();
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapIdentityRequest| request.
+ *
+ * @param identity Identity string containing the IMSI.
+ * @param encryptedIdentity Identity string containing the encrypted IMSI.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapIdentityResponse(in byte[] identity, in byte[] encryptedIdentity);
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapSimGsmAuthRequest| request.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapSimGsmAuthFailure();
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapSimGsmAuthRequest| request.
+ *
+ * @param params Params to be used for EAP GSM authentication.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapSimGsmAuthResponse(in NetworkResponseEapSimGsmAuthParams[] params);
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapSimUmtsAuthFailure();
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+ *
+ * @param params Params to be used for EAP UMTS authentication.
+ * @throws ServiceSpecificException with one of the following values:
+
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapSimUmtsAuthResponse(in NetworkResponseEapSimUmtsAuthParams params);
+
+ /**
+ * Used to send a response to the
+ * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+ *
+ * @param auts Params to be used for EAP UMTS authentication.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void sendNetworkEapSimUmtsAutsResponse(in byte[] auts);
+
+ /**
+ * Set auth alg mask for the network.
+ *
+ * @param authAlgMask value to set.
+ * Combination of |ProtoMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setAuthAlg(in AuthAlgMask authAlgMask);
+
+ /**
+ * Set the network to only connect to an AP with provided BSSID.
+ *
+ * @param bssid value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setBssid(in byte[] bssid);
+
+ /**
+ * Set EAP Alt subject match for this network.
+ *
+ * @param match value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapAltSubjectMatch(in String match);
+
+ /**
+ * Set EAP Anonymous Identity for this network.
+ *
+ * @param identity value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapAnonymousIdentity(in byte[] identity);
+
+ /**
+ * Set EAP CA certificate file path for this network.
+ *
+ * @param path value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapCACert(in String path);
+
+ /**
+ * Set EAP CA certificate directory path for this network.
+ *
+ * @param path value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapCAPath(in String path);
+
+ /**
+ * Set EAP Client certificate file path for this network.
+ *
+ * @param path value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapClientCert(in String path);
+
+ /**
+ * Set EAP Domain suffix match for this network.
+ *
+ * @param match value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapDomainSuffixMatch(in String match);
+
+ /**
+ * Set EAP encrypted IMSI Identity for this network.
+ *
+ * @param identity Identity string built from the encrypted IMSI.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapEncryptedImsiIdentity(in byte[] identity);
+
+ /**
+ * Enable EAP Open SSL Engine for this network.
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapEngine(in boolean enable);
+
+ /**
+ * Set EAP Open SSL Engine ID for this network.
+ *
+ * @param id value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapEngineID(in String id);
+
+ /**
+ * Enable Extensible Authentication (EAP) - Re-authentication Protocol (ERP) for this network.
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapErp(in boolean enable);
+
+ /**
+ * Set EAP Identity for this network.
+ *
+ * @param identity value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapIdentity(in byte[] identity);
+
+ /**
+ * Set EAP Method for this network.
+ *
+ * @param method value to be set.
+ * Must be one of |EapMethod| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapMethod(in EapMethod method);
+
+ /**
+ * Set EAP Password for this network.
+ *
+ * @param password value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapPassword(in byte[] password);
+
+ /**
+ * Set EAP Phase2 Method for this network.
+ *
+ * EAP method needs to be set for this to work.
+ *
+ * @param method value to set.
+ * Must be one of |EapPhase2Method| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapPhase2Method(in EapPhase2Method method);
+
+ /**
+ * Set EAP private key Id for this network.
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
+ *
+ * @param id value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapPrivateKeyId(in String id);
+
+ /**
+ * Set EAP subject match for this network.
+ *
+ * @param match value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEapSubjectMatch(in String match);
+
+ /**
+ * Set whether to enable enhanced directional multi-gigabit (802.11ay EDMG).
+ * Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD|
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setEdmg(in boolean enable);
+
+ /**
+ * Set group cipher mask for the network.
+ *
+ * @param groupCipherMask value to set.
+ * Combination of |ProtoMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setGroupCipher(in GroupCipherMask groupCipherMask);
+
+ /**
+ * Set group management cipher mask for the network.
+ *
+ * @param groupMgmtCipherMask value to set.
+ * Combination of |GroupMgmtCipherMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setGroupMgmtCipher(in GroupMgmtCipherMask groupMgmtCipherMask);
+
+ /**
+ * Set ID string for this network.
+ * Network identifier string for external scripts.
+ *
+ * @param idStr ID string value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setIdStr(in String idStr);
+
+ /**
+ * Set key management mask for the network.
+ *
+ * @param keyMgmtMask value to set.
+ * Combination of |KeyMgmtMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setKeyMgmt(in KeyMgmtMask keyMgmtMask);
+
+ /**
+ * Set OCSP (Online Certificate Status Protocol) type for this network.
+ *
+ * @param ocspType value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setOcsp(in OcspType ocspType);
+
+ /**
+ * Set pairwise cipher mask for the network.
+ *
+ * @param pairwiseCipherMask value to set.
+ * Combination of |ProtoMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setPairwiseCipher(in PairwiseCipherMask pairwiseCipherMask);
+
+ /**
+ * Add a pairwise master key (PMK) into supplicant PMK cache.
+ *
+ * @param serializedEntry is serialized PMK cache entry, the content is
+ * opaque for the framework and depends on the native implementation.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setPmkCache(in byte[] serializedEntry);
+
+ /**
+ * This field can be used to enable proactive key caching which is also
+ * known as opportunistic PMKSA caching for WPA2. This is disabled (0)
+ * by default unless default value is changed with the global okc=1
+ * parameter.
+ *
+ * Proactive key caching is used to make supplicant assume that the APs
+ * are using the same PMK and generate PMKSA cache entries without
+ * doing RSN pre-authentication. This requires support from the AP side
+ * and is normally used with wireless switches that co-locate the
+ * authenticator.
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setProactiveKeyCaching(in boolean enable);
+
+ /**
+ * Set proto mask for the network.
+ *
+ * @param protoMask value to set.
+ * Combination of |ProtoMask| values.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setProto(in ProtoMask protoMask);
+
+ /**
+ * Set raw psk for WPA_PSK network.
+ *
+ * @param psk value to set as specified in IEEE 802.11i-2004 standard.
+ * This is the calculated using 'wpa_passphrase <ssid> [passphrase]'
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setPsk(in byte[] psk);
+
+ /**
+ * Set passphrase for WPA_PSK network.
+ *
+ * @param psk value to set.
+ * Length of value must be between
+ * |PSK_PASSPHRASE_MIN_LEN_IN_BYTES| and
+ * |PSK_PASSPHRASE_MAX_LEN_IN_BYTES|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setPskPassphrase(in String psk);
+
+ /**
+ * Set whether RequirePmf is enabled for this network.
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setRequirePmf(in boolean enable);
+
+ /**
+ * Set SAE H2E (Hash-to-Element) mode.
+ *
+ * @param mode SAE H2E supporting mode.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setSaeH2eMode(in SaeH2eMode mode);
+
+ /**
+ * Set SAE password for WPA3-Personal
+ *
+ * @param saePassword string with the above option
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setSaePassword(in String saePassword);
+
+ /**
+ * Set SAE password ID for WPA3-Personal
+ *
+ * @param sae_password_id string with the above option
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setSaePasswordId(in String saePasswordId);
+
+ /**
+ * Set whether to send probe requests for this network (hidden).
+ *
+ * @param enable true to set, false otherwise.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setScanSsid(in boolean enable);
+
+ /**
+ *
+ * Setters for the various network params.
+ * These correspond to elements of |wpa_sssid| struct used internally by
+ * the supplicant to represent each network.
+ *
+ */
+
+ /**
+ * Set SSID for this network.
+ *
+ * @param ssid value to set.
+ * Max length of |SSID_MAX_LEN_IN_BYTES|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setSsid(in byte[] ssid);
+
+ /**
+ * Set PPS MO ID for this network.
+ * (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
+ *
+ * @param id ID value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setUpdateIdentifier(in int id);
+
+ /**
+ * Set WAPI certificate suite name for this network.
+ *
+ * @param suite value to set.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ void setWapiCertSuite(in String suite);
+
+ /**
+ * Set WEP key for WEP network.
+ *
+ * @param keyIdx Index of wep key to set.
+ * Max of |WEP_KEYS_MAX_NUM|.
+ * @param wepKey value to set.
+ * Length of each key must be either
+ * |WEP40_KEY_LEN_IN_BYTES| or
+ * |WEP104_KEY_LEN_IN_BYTES|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setWepKey(in int keyIdx, in byte[] wepKey);
+
+ /**
+ * Set default Tx key index for WEP network.
+ *
+ * @param keyIdx Value to set.
+ * Max of |WEP_KEYS_MAX_NUM|.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setWepTxKeyIdx(in int keyIdx);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
new file mode 100644
index 0000000..c28b494
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.NetworkRequestEapSimGsmAuthParams;
+import android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams;
+import android.hardware.wifi.supplicant.TransitionDisableIndication;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each network (ISupplicantStaNetwork).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaNetwork.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantStaNetworkCallback {
+ /**
+ * Used to request EAP Identity for this particular network.
+ *
+ * The response for the request must be sent using the corresponding
+ * |ISupplicantNetwork.sendNetworkEapIdentityResponse| call.
+ */
+ oneway void onNetworkEapIdentityRequest();
+
+ /**
+ * Used to request EAP GSM SIM authentication for this particular network.
+ *
+ * The response for the request must be sent using the corresponding
+ * |ISupplicantNetwork.sendNetworkEapSimGsmAuthResponse| call.
+ *
+ * @param params Params associated with the request.
+ */
+ oneway void onNetworkEapSimGsmAuthRequest(in NetworkRequestEapSimGsmAuthParams params);
+
+ /**
+ * Used to request EAP UMTS SIM authentication for this particular network.
+ *
+ * The response for the request must be sent using the corresponding
+ * |ISupplicantNetwork.sendNetworkEapSimUmtsAuthResponse| call.
+ *
+ * @param params Params associated with the request.
+ */
+ oneway void onNetworkEapSimUmtsAuthRequest(in NetworkRequestEapSimUmtsAuthParams params);
+
+ /**
+ * Used to notify WPA3 transition disable.
+ */
+ oneway void onTransitionDisable(in TransitionDisableIndication ind);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl
new file mode 100644
index 0000000..7792142
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.IfaceType;
+
+/**
+ * Structure describing the type and name of an iface
+ * controlled by the supplicant.
+ */
+@VintfStability
+parcelable IfaceInfo {
+ /**
+ * Type of the network interface.
+ */
+ IfaceType type;
+ /**
+ * Name of the network interface, e.g., wlan0
+ */
+ String name;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl
new file mode 100644
index 0000000..e39dcd1
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * List of Iface types supported.
+ */
+@VintfStability
+@Backing(type="int")
+enum IfaceType {
+ STA,
+ P2P,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
new file mode 100644
index 0000000..f0c3345
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possible mask of values for KeyMgmt param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_KEY_MGMT_IEEE8021X).
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyMgmtMask {
+ WPA_EAP = 1 << 0,
+ WPA_PSK = 1 << 1,
+ NONE = 1 << 2,
+ IEEE8021X = 1 << 3,
+ FT_EAP = 1 << 5,
+ FT_PSK = 1 << 6,
+ OSEN = 1 << 15,
+ /**
+ * WPA using EAP authentication with stronger SHA256-based algorithms
+ */
+ WPA_EAP_SHA256 = 1 << 7,
+ /**
+ * WPA pre-shared key with stronger SHA256-based algorithms
+ */
+ WPA_PSK_SHA256 = 1 << 8,
+ /**
+ * WPA3-Personal SAE Key management
+ */
+ SAE = 1 << 10,
+ /**
+ * WPA3-Enterprise Suite-B Key management
+ */
+ SUITE_B_192 = 1 << 17,
+ /**
+ * Enhacned Open (OWE) Key management
+ */
+ OWE = 1 << 22,
+ /**
+ * Easy Connect (DPP) Key management
+ */
+ DPP = 1 << 23,
+ /*
+ * WAPI Psk
+ */
+ WAPI_PSK = 1 << 12,
+ /**
+ * WAPI Cert
+ */
+ WAPI_CERT = 1 << 13,
+ /**
+ * FILS shared key authentication with sha-256
+ */
+ FILS_SHA256 = 1 << 18,
+ /**
+ * FILS shared key authentication with sha-384
+ */
+ FILS_SHA384 = 1 << 19,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl
new file mode 100644
index 0000000..f933f6c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Detailed network mode for legacy network
+ */
+@VintfStability
+@Backing(type="int")
+enum LegacyMode {
+ UNKNOWN = 0,
+ /**
+ * For 802.11a
+ */
+ A_MODE = 1,
+ /**
+ * For 802.11b
+ */
+ B_MODE = 2,
+ /**
+ * For 802.11g
+ */
+ G_MODE = 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl
new file mode 100644
index 0000000..40ad22a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Byte array representing a Mac Address. Use when we need
+ * to pass an array of Mac Addresses to a method, as 2D
+ * arrays are not supported in AIDL.
+ *
+ * TODO (b/210705533): Replace this type with a 2D byte array.
+ */
+@VintfStability
+parcelable MacAddress {
+ byte[/* 6 */] data;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
new file mode 100644
index 0000000..41868aa
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * MBO spec v1.2, 4.2.4 Table 14: MBO Association disallowed reason code attribute
+ * values.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MboAssocDisallowedReasonCode {
+ RESERVED = 0,
+ UNSPECIFIED = 1,
+ MAX_NUM_STA_ASSOCIATED = 2,
+ AIR_INTERFACE_OVERLOADED = 3,
+ AUTH_SERVER_OVERLOADED = 4,
+ INSUFFICIENT_RSSI = 5,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
new file mode 100644
index 0000000..98f707e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * MBO spec v1.2, 4.2.5 Table 16: MBO Cellular Data connection preference
+ * attribute values. AP use this to indicate STA, its preference for the
+ * STA to move from BSS to cellular network.
+ */
+@VintfStability
+@Backing(type="int")
+enum MboCellularDataConnectionPrefValue {
+ EXCLUDED = 0,
+ NOT_PREFERRED = 1,
+ /*
+ * 2-254 Reserved.
+ */
+ PREFERRED = 255,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
new file mode 100644
index 0000000..66ad9ee
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * MBO spec v1.2, 4.2.6 Table 18: MBO transition reason code attribute
+ * values.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MboTransitionReasonCode {
+ UNSPECIFIED = 0,
+ EXCESSIVE_FRAME_LOSS = 1,
+ EXCESSIVE_TRAFFIC_DELAY = 2,
+ INSUFFICIENT_BANDWIDTH = 3,
+ LOAD_BALANCING = 4,
+ LOW_RSSI = 5,
+ RX_EXCESSIVE_RETRIES = 6,
+ HIGH_INTERFERENCE = 7,
+ GRAY_ZONE = 8,
+ TRANSITION_TO_PREMIUM_AP = 9,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl
new file mode 100644
index 0000000..4eaaf1d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Enum describing the modes of Miracast supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MiracastMode {
+ DISABLED = 0,
+ /**
+ * Operating as source.
+ */
+ SOURCE = 1,
+ /**
+ * Operating as sink.
+ */
+ SINK = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..c706c81
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.GsmRand;
+
+/**
+ * Params of |onNetworkEapSimGsmAuthRequest| request. (Refer RFC 4186)
+ */
+@VintfStability
+parcelable NetworkRequestEapSimGsmAuthParams {
+ GsmRand[] rands;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..2f5e7fa
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Params of |onNetworkEapSimUmtsAuthRequest| request. (Refer RFC 4187)
+ */
+@VintfStability
+parcelable NetworkRequestEapSimUmtsAuthParams {
+ byte[/* 16 */] rand;
+ byte[/* 16 */] autn;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..38929a2
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Params of |sendNetworkEapSimGsmAuthResponse| request. (Refer RFC 4186)
+ */
+@VintfStability
+parcelable NetworkResponseEapSimGsmAuthParams {
+ byte[/* 8 */] kc;
+ byte[/* 4 */] sres;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..5311016
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Params of |sendNetworkEapSimUmtsAuthResponse| request. (Refer RFC 4187)
+ */
+@VintfStability
+parcelable NetworkResponseEapSimUmtsAuthParams {
+ byte[] res;
+ byte[/* 16 */] ik;
+ byte[/* 16 */] ck;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
new file mode 100644
index 0000000..09ec09c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response
+ * frame from an OCE AP to indicate that the AP has rejected the
+ * (Re-)Association request on the basis of insufficient RSSI.
+ * Refer OCE spec v1.0 section 4.2.2 Table 7.
+ */
+@VintfStability
+parcelable OceRssiBasedAssocRejectAttr {
+ /*
+ * Delta RSSI - The difference in dB between the minimum RSSI at which
+ * the AP would accept a (Re-)Association request from the STA before
+ * Retry Delay expires and the AP's measurement of the RSSI at which the
+ * (Re-)Association request was received.
+ */
+ int deltaRssi;
+ /*
+ * Retry Delay - The time period in seconds for which the AP will not
+ * accept any subsequent (Re-)Association requests from the STA, unless
+ * the received RSSI has improved by Delta RSSI.
+ */
+ int retryDelayS;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl
new file mode 100644
index 0000000..876fb11
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * OcspType: The type of OCSP request.
+ */
+@VintfStability
+@Backing(type="int")
+enum OcspType {
+ NONE,
+ REQUEST_CERT_STATUS,
+ REQUIRE_CERT_STATUS,
+ REQUIRE_ALL_CERTS_STATUS,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl
new file mode 100644
index 0000000..a060365
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * OSU Method. Refer to section 4.8.1.3 of the Hotspot 2.0 spec.
+ */
+@VintfStability
+@Backing(type="byte")
+enum OsuMethod {
+ OMA_DM = 0,
+ SOAP_XML_SPP = 1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
new file mode 100644
index 0000000..bda3c34
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * P2P group capability.
+ * See /external/wpa_supplicant_8/src/common/ieee802_11_defs.h
+ * for all possible values (starting at P2P_GROUP_CAPAB_GROUP_OWNER).
+ */
+@VintfStability
+@Backing(type="int")
+enum P2pGroupCapabilityMask {
+ GROUP_OWNER = 1 << 0,
+ PERSISTENT_GROUP = 1 << 1,
+ GROUP_LIMIT = 1 << 2,
+ INTRA_BSS_DIST = 1 << 3,
+ CROSS_CONN = 1 << 4,
+ PERSISTENT_RECONN = 1 << 5,
+ GROUP_FORMATION = 1 << 6,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
new file mode 100644
index 0000000..9effd0a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Status codes for P2P discovery.
+ */
+@VintfStability
+@Backing(type="byte")
+enum P2pProvDiscStatusCode {
+ SUCCESS = 0,
+ TIMEOUT = 1,
+ REJECTED = 2,
+ TIMEOUT_JOIN = 3,
+ INFO_UNAVAILABLE = 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl
new file mode 100644
index 0000000..4020f9e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Status codes for P2P operations.
+ */
+@VintfStability
+@Backing(type="int")
+enum P2pStatusCode {
+ SUCCESS = 0,
+ FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
+ FAIL_INCOMPATIBLE_PARAMS = 2,
+ FAIL_LIMIT_REACHED = 3,
+ FAIL_INVALID_PARAMS = 4,
+ FAIL_UNABLE_TO_ACCOMMODATE = 5,
+ FAIL_PREV_PROTOCOL_ERROR = 6,
+ FAIL_NO_COMMON_CHANNELS = 7,
+ FAIL_UNKNOWN_GROUP = 8,
+ FAIL_BOTH_GO_INTENT_15 = 9,
+ FAIL_INCOMPATIBLE_PROV_METHOD = 10,
+ FAIL_REJECTED_BY_USER = 11,
+ SUCCESS_DEFERRED = 12,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
new file mode 100644
index 0000000..7179fea
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possible mask of values for PairwiseCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_CIPHER_NONE).
+ */
+@VintfStability
+@Backing(type="int")
+enum PairwiseCipherMask {
+ NONE = 1 << 0,
+ TKIP = 1 << 3,
+ CCMP = 1 << 4,
+ /**
+ * GCMP-128 Pairwise Cipher
+ */
+ GCMP_128 = 1 << 6,
+ /**
+ * SMS4 Pairwise Cipher
+ */
+ SMS4 = 1 << 7,
+ /**
+ * GCMP-256 Pairwise Cipher
+ */
+ GCMP_256 = 1 << 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
new file mode 100644
index 0000000..dc3d80b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Possible mask of values for Proto param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_PROTO_WPA).
+ */
+@VintfStability
+@Backing(type="int")
+enum ProtoMask {
+ WPA = 1 << 0,
+ RSN = 1 << 1,
+ WAPI = 1 << 2,
+ OSEN = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl
new file mode 100644
index 0000000..5dfb73e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Enum describing the types of RX filter supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum RxFilterType {
+ V4_MULTICAST = 0,
+ V6_MULTICAST = 1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl
new file mode 100644
index 0000000..48a879b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * SAE Hash-to-Element mode.
+ */
+@VintfStability
+@Backing(type="byte")
+enum SaeH2eMode {
+ /**
+ * Hash-to-Element is disabled, only Hunting & Pecking is allowed.
+ */
+ DISABLED,
+ /**
+ * Both Hash-to-Element and Hunting & Pecking are allowed.
+ */
+ H2E_OPTIONAL,
+ /**
+ * Only Hash-to-Element is allowed.
+ */
+ H2E_MANDATORY,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
new file mode 100644
index 0000000..19f6f88
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Various states of the interface reported by |onStateChanged|.
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceCallbackState {
+ /**
+ * This state indicates that client is not associated, but is likely to
+ * start looking for an access point. This state is entered when a
+ * connection is lost.
+ */
+ DISCONNECTED = 0,
+ /**
+ * This state is entered if the network interface is disabled, e.g.,
+ * due to rfkill. the supplicant refuses any new operations that would
+ * use the radio until the interface has been enabled.
+ */
+ IFACE_DISABLED = 1,
+ /**
+ * This state is entered if there are no enabled networks in the
+ * configuration. the supplicant is not trying to associate with a new
+ * network and external interaction (e.g., ctrl_iface call to add or
+ * enable a network) is needed to start association.
+ */
+ INACTIVE = 2,
+ /**
+ * This state is entered when the supplicant starts scanning for a
+ * network.
+ */
+ SCANNING = 3,
+ /**
+ * This state is entered when the supplicant has found a suitable BSS
+ * to authenticate with and the driver is configured to try to
+ * authenticate with this BSS. This state is used only with drivers
+ * that use the supplicant as the SME.
+ */
+ AUTHENTICATING = 4,
+ /**
+ * This state is entered when the supplicant has found a suitable BSS
+ * to associate with and the driver is configured to try to associate
+ * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
+ * state is entered when the driver is configured to try to associate
+ * with a network using the configured SSID and security policy.
+ */
+ ASSOCIATING = 5,
+ /**
+ * This state is entered when the driver reports that association has
+ * been successfully completed with an AP. If IEEE 802.1X is used
+ * (with or without WPA/WPA2), the supplicant remains in this state
+ * until the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ ASSOCIATED = 6,
+ /**
+ * This state is entered when WPA/WPA2 4-Way Handshake is started. In
+ * case of WPA-PSK, this happens when receiving the first EAPOL-Key
+ * frame after association. In case of WPA-EAP, this state is entered
+ * when the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ FOURWAY_HANDSHAKE = 7,
+ /**
+ * This state is entered when 4-Way Key Handshake has been completed
+ * (i.e., when the supplicant sends out message 4/4) and when Group
+ * Key rekeying is started by the AP (i.e., when supplicant receives
+ * message 1/2).
+ */
+ GROUP_HANDSHAKE = 8,
+ /**
+ * This state is entered when the full authentication process is
+ * completed. In case of WPA2, this happens when the 4-Way Handshake is
+ * successfully completed. With WPA, this state is entered after the
+ * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
+ * completed after dynamic keys are received (or if not used, after
+ * the EAP authentication has been completed). With static WEP keys and
+ * plaintext connections, this state is entered when an association
+ * has been completed.
+ *
+ * This state indicates that the supplicant has completed its
+ * processing for the association phase and that data connection is
+ * fully configured.
+ */
+ COMPLETED = 9,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
new file mode 100644
index 0000000..6b05c07
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceReasonCode {
+ UNSPECIFIED = 1,
+ PREV_AUTH_NOT_VALID = 2,
+ DEAUTH_LEAVING = 3,
+ DISASSOC_DUE_TO_INACTIVITY = 4,
+ DISASSOC_AP_BUSY = 5,
+ CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+ CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+ DISASSOC_STA_HAS_LEFT = 8,
+ STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+ PWR_CAPABILITY_NOT_VALID = 10,
+ SUPPORTED_CHANNEL_NOT_VALID = 11,
+ BSS_TRANSITION_DISASSOC = 12,
+ INVALID_IE = 13,
+ MICHAEL_MIC_FAILURE = 14,
+ FOURWAY_HANDSHAKE_TIMEOUT = 15,
+ GROUP_KEY_UPDATE_TIMEOUT = 16,
+ IE_IN_4WAY_DIFFERS = 17,
+ GROUP_CIPHER_NOT_VALID = 18,
+ PAIRWISE_CIPHER_NOT_VALID = 19,
+ AKMP_NOT_VALID = 20,
+ UNSUPPORTED_RSN_IE_VERSION = 21,
+ INVALID_RSN_IE_CAPAB = 22,
+ IEEE_802_1X_AUTH_FAILED = 23,
+ CIPHER_SUITE_REJECTED = 24,
+ TDLS_TEARDOWN_UNREACHABLE = 25,
+ TDLS_TEARDOWN_UNSPECIFIED = 26,
+ SSP_REQUESTED_DISASSOC = 27,
+ NO_SSP_ROAMING_AGREEMENT = 28,
+ BAD_CIPHER_OR_AKM = 29,
+ NOT_AUTHORIZED_THIS_LOCATION = 30,
+ SERVICE_CHANGE_PRECLUDES_TS = 31,
+ UNSPECIFIED_QOS_REASON = 32,
+ NOT_ENOUGH_BANDWIDTH = 33,
+ DISASSOC_LOW_ACK = 34,
+ EXCEEDED_TXOP = 35,
+ STA_LEAVING = 36,
+ END_TS_BA_DLS = 37,
+ UNKNOWN_TS_BA = 38,
+ TIMEOUT = 39,
+ PEERKEY_MISMATCH = 45,
+ AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+ EXTERNAL_SERVICE_REQUIREMENTS = 47,
+ INVALID_FT_ACTION_FRAME_COUNT = 48,
+ INVALID_PMKID = 49,
+ INVALID_MDE = 50,
+ INVALID_FTE = 51,
+ MESH_PEERING_CANCELLED = 52,
+ MESH_MAX_PEERS = 53,
+ MESH_CONFIG_POLICY_VIOLATION = 54,
+ MESH_CLOSE_RCVD = 55,
+ MESH_MAX_RETRIES = 56,
+ MESH_CONFIRM_TIMEOUT = 57,
+ MESH_INVALID_GTK = 58,
+ MESH_INCONSISTENT_PARAMS = 59,
+ MESH_INVALID_SECURITY_CAP = 60,
+ MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+ MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+ MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+ MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+ MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+ MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
new file mode 100644
index 0000000..75e7f68
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46).
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceStatusCode {
+ SUCCESS = 0,
+ UNSPECIFIED_FAILURE = 1,
+ TDLS_WAKEUP_ALTERNATE = 2,
+ TDLS_WAKEUP_REJECT = 3,
+ SECURITY_DISABLED = 5,
+ UNACCEPTABLE_LIFETIME = 6,
+ NOT_IN_SAME_BSS = 7,
+ CAPS_UNSUPPORTED = 10,
+ REASSOC_NO_ASSOC = 11,
+ ASSOC_DENIED_UNSPEC = 12,
+ NOT_SUPPORTED_AUTH_ALG = 13,
+ UNKNOWN_AUTH_TRANSACTION = 14,
+ CHALLENGE_FAIL = 15,
+ AUTH_TIMEOUT = 16,
+ AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+ ASSOC_DENIED_RATES = 18,
+ ASSOC_DENIED_NOSHORT = 19,
+ SPEC_MGMT_REQUIRED = 22,
+ PWR_CAPABILITY_NOT_VALID = 23,
+ SUPPORTED_CHANNEL_NOT_VALID = 24,
+ ASSOC_DENIED_NO_SHORT_SLOT_TIME = 25,
+ ASSOC_DENIED_NO_HT = 27,
+ R0KH_UNREACHABLE = 28,
+ ASSOC_DENIED_NO_PCO = 29,
+ ASSOC_REJECTED_TEMPORARILY = 30,
+ ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
+ UNSPECIFIED_QOS_FAILURE = 32,
+ DENIED_INSUFFICIENT_BANDWIDTH = 33,
+ DENIED_POOR_CHANNEL_CONDITIONS = 34,
+ DENIED_QOS_NOT_SUPPORTED = 35,
+ REQUEST_DECLINED = 37,
+ INVALID_PARAMETERS = 38,
+ REJECTED_WITH_SUGGESTED_CHANGES = 39,
+ INVALID_IE = 40,
+ GROUP_CIPHER_NOT_VALID = 41,
+ PAIRWISE_CIPHER_NOT_VALID = 42,
+ AKMP_NOT_VALID = 43,
+ UNSUPPORTED_RSN_IE_VERSION = 44,
+ INVALID_RSN_IE_CAPAB = 45,
+ CIPHER_REJECTED_PER_POLICY = 46,
+ TS_NOT_CREATED = 47,
+ DIRECT_LINK_NOT_ALLOWED = 48,
+ DEST_STA_NOT_PRESENT = 49,
+ DEST_STA_NOT_QOS_STA = 50,
+ ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51,
+ INVALID_FT_ACTION_FRAME_COUNT = 52,
+ INVALID_PMKID = 53,
+ INVALID_MDIE = 54,
+ INVALID_FTIE = 55,
+ REQUESTED_TCLAS_NOT_SUPPORTED = 56,
+ INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57,
+ TRY_ANOTHER_BSS = 58,
+ GAS_ADV_PROTO_NOT_SUPPORTED = 59,
+ NO_OUTSTANDING_GAS_REQ = 60,
+ GAS_RESP_NOT_RECEIVED = 61,
+ STA_TIMED_OUT_WAITING_FOR_GAS_RESP = 62,
+ GAS_RESP_LARGER_THAN_LIMIT = 63,
+ REQ_REFUSED_HOME = 64,
+ ADV_SRV_UNREACHABLE = 65,
+ REQ_REFUSED_SSPN = 67,
+ REQ_REFUSED_UNAUTH_ACCESS = 68,
+ INVALID_RSNIE = 72,
+ U_APSD_COEX_NOT_SUPPORTED = 73,
+ U_APSD_COEX_MODE_NOT_SUPPORTED = 74,
+ BAD_INTERVAL_WITH_U_APSD_COEX = 75,
+ ANTI_CLOGGING_TOKEN_REQ = 76,
+ FINITE_CYCLIC_GROUP_NOT_SUPPORTED = 77,
+ CANNOT_FIND_ALT_TBTT = 78,
+ TRANSMISSION_FAILURE = 79,
+ REQ_TCLAS_NOT_SUPPORTED = 80,
+ TCLAS_RESOURCES_EXCHAUSTED = 81,
+ REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82,
+ REJECT_WITH_SCHEDULE = 83,
+ REJECT_NO_WAKEUP_SPECIFIED = 84,
+ SUCCESS_POWER_SAVE_MODE = 85,
+ PENDING_ADMITTING_FST_SESSION = 86,
+ PERFORMING_FST_NOW = 87,
+ PENDING_GAP_IN_BA_WINDOW = 88,
+ REJECT_U_PID_SETTING = 89,
+ REFUSED_EXTERNAL_REASON = 92,
+ REFUSED_AP_OUT_OF_MEMORY = 93,
+ REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED = 94,
+ QUERY_RESP_OUTSTANDING = 95,
+ REJECT_DSE_BAND = 96,
+ TCLAS_PROCESSING_TERMINATED = 97,
+ TS_SCHEDULE_CONFLICT = 98,
+ DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
+ MCCAOP_RESERVATION_CONFLICT = 100,
+ MAF_LIMIT_EXCEEDED = 101,
+ MCCA_TRACK_LIMIT_EXCEEDED = 102,
+ DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+ ASSOC_DENIED_NO_VHT = 104,
+ ENABLEMENT_DENIED = 105,
+ RESTRICTION_FROM_AUTHORIZED_GDB = 106,
+ AUTHORIZATION_DEENABLED = 107,
+ FILS_AUTHENTICATION_FAILURE = 112,
+ UNKNOWN_AUTHENTICATION_SERVER = 113,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
new file mode 100644
index 0000000..c7b7ffd
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Enum values indicating the status of any supplicant operation.
+ */
+@VintfStability
+@Backing(type="int")
+enum SupplicantStatusCode {
+ /**
+ * No errors.
+ */
+ SUCCESS,
+ /**
+ * Unknown failure occurred.
+ */
+ FAILURE_UNKNOWN,
+ /**
+ * One of the incoming args is invalid.
+ */
+ FAILURE_ARGS_INVALID,
+ /**
+ * |ISupplicantIface| AIDL interface object is no longer valid.
+ */
+ FAILURE_IFACE_INVALID,
+ /**
+ * Iface with the provided name does not exist.
+ */
+ FAILURE_IFACE_UNKNOWN,
+ /**
+ * Iface with the provided name already exists.
+ */
+ FAILURE_IFACE_EXISTS,
+ /**
+ * Iface is disabled and cannot be used.
+ */
+ FAILURE_IFACE_DISABLED,
+ /**
+ * Iface is not currently disconnected, so cannot reconnect.
+ */
+ FAILURE_IFACE_NOT_DISCONNECTED,
+ /**
+ * |ISupplicantNetwork| AIDL interface object is no longer valid.
+ */
+ FAILURE_NETWORK_INVALID,
+ /**
+ * Network with the provided id does not exist.
+ */
+ FAILURE_NETWORK_UNKNOWN,
+ FAILURE_UNSUPPORTED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
new file mode 100644
index 0000000..baf20a8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * WPA3™ Specification Addendum for WPA3 R3 - Table 3.
+ * Transition Disable Indication filled in the third
+ * 4-way handshake message.
+ * See /external/wpa_supplicant_8/src/common/wpa_common.h for
+ * all possible values (starting at TRANSITION_DISABLE_WPA3_PERSONAL).
+ */
+@VintfStability
+@Backing(type="int")
+enum TransitionDisableIndication {
+ USE_WPA3_PERSONAL = 1 << 0,
+ USE_SAE_PK = 1 << 1,
+ USE_WPA3_ENTERPRISE = 1 << 2,
+ USE_ENHANCED_OPEN = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
new file mode 100644
index 0000000..00c16b4
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Wifi Technologies
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiTechnology {
+ UNKNOWN = 0,
+ /**
+ * For 802.11a/b/g
+ */
+ LEGACY = 1,
+ /**
+ * For 802.11n
+ */
+ HT = 2,
+ /**
+ * For 802.11ac
+ */
+ VHT = 3,
+ /**
+ * For 802.11ax
+ */
+ HE = 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
new file mode 100644
index 0000000..e174199
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * WPA Driver capability.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpaDriverCapabilitiesMask {
+ /**
+ * Multi Band Operation.
+ */
+ MBO = 1 << 0,
+ /**
+ * Optimized Connectivity Experience.
+ */
+ OCE = 1 << 1,
+ /**
+ * WPA3 SAE Public-Key.
+ */
+ SAE_PK = 1 << 2,
+ /**
+ * Wi-Fi Display R2
+ */
+ WFD_R2 = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl
new file mode 100644
index 0000000..926946c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * WPS Configuration Error.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsConfigError {
+ NO_ERROR = 0,
+ OOB_IFACE_READ_ERROR = 1,
+ DECRYPTION_CRC_FAILURE = 2,
+ CHAN_24_NOT_SUPPORTED = 3,
+ CHAN_50_NOT_SUPPORTED = 4,
+ SIGNAL_TOO_WEAK = 5,
+ NETWORK_AUTH_FAILURE = 6,
+ NETWORK_ASSOC_FAILURE = 7,
+ NO_DHCP_RESPONSE = 8,
+ FAILED_DHCP_CONFIG = 9,
+ IP_ADDR_CONFLICT = 10,
+ NO_CONN_TO_REGISTRAR = 11,
+ MULTIPLE_PBC_DETECTED = 12,
+ ROGUE_SUSPECTED = 13,
+ DEVICE_BUSY = 14,
+ SETUP_LOCKED = 15,
+ MSG_TIMEOUT = 16,
+ REG_SESS_TIMEOUT = 17,
+ DEV_PASSWORD_AUTH_FAILURE = 18,
+ CHAN_60G_NOT_SUPPORTED = 19,
+ PUBLIC_KEY_HASH_MISMATCH = 20,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
new file mode 100644
index 0000000..ec08a45
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * WPS config methods.
+ * Refer to section 3 of IBSS with Wi-Fi Protected Setup
+ * Technical Specification Version 1.0.0.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsConfigMethods {
+ USBA = 0x0001,
+ ETHERNET = 0x0002,
+ LABEL = 0x0004,
+ DISPLAY = 0x0008,
+ EXT_NFC_TOKEN = 0x0010,
+ INT_NFC_TOKEN = 0x0020,
+ NFC_INTERFACE = 0x0040,
+ PUSHBUTTON = 0x0080,
+ KEYPAD = 0x0100,
+ VIRT_PUSHBUTTON = 0x0280,
+ PHY_PUSHBUTTON = 0x0480,
+ P2PS = 0x1000,
+ VIRT_DISPLAY = 0x2008,
+ PHY_DISPLAY = 0x4008,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
new file mode 100644
index 0000000..ca5a533
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * WPS Device Password ID
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsDevPasswordId {
+ DEFAULT = 0x0000,
+ USER_SPECIFIED = 0x0001,
+ MACHINE_SPECIFIED = 0x0002,
+ REKEY = 0x0003,
+ PUSHBUTTON = 0x0004,
+ REGISTRAR_SPECIFIED = 0x0005,
+ NFC_CONNECTION_HANDOVER = 0x0007,
+ P2PS_DEFAULT = 0x0008,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
new file mode 100644
index 0000000..4866acc
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+/**
+ * Vendor specific Error Indication for WPS event messages.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsErrorIndication {
+ NO_ERROR = 0,
+ SECURITY_TKIP_ONLY_PROHIBITED = 1,
+ SECURITY_WEP_PROHIBITED = 2,
+ AUTH_FAILURE = 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
new file mode 100644
index 0000000..5b59392
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.wifi.supplicant;
+
+@VintfStability
+@Backing(type="int")
+enum WpsProvisionMethod {
+ /**
+ * Push button method.
+ */
+ PBC,
+ /**
+ * Display pin method configuration - pin is generated and displayed on
+ * device.
+ */
+ DISPLAY,
+ /**
+ * Keypad pin method configuration - pin is entered on device.
+ */
+ KEYPAD,
+}
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..8e142ec
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -0,0 +1,126 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalWifiSupplicantStaIfaceTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["supplicant_sta_iface_aidl_test.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hardware.wifi.supplicant@1.1",
+ "android.hardware.wifi.supplicant-V1-ndk",
+ "libwifi-system",
+ "libwifi-system-iface",
+ "VtsHalWifiV1_0TargetTestUtil",
+ "VtsHalWifiV1_5TargetTestUtil",
+ "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiSupplicantStaNetworkTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["supplicant_sta_network_aidl_test.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hardware.wifi.supplicant@1.1",
+ "android.hardware.wifi.supplicant-V1-ndk",
+ "libwifi-system",
+ "libwifi-system-iface",
+ "VtsHalWifiV1_0TargetTestUtil",
+ "VtsHalWifiV1_5TargetTestUtil",
+ "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiSupplicantP2pIfaceTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["supplicant_p2p_iface_aidl_test.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hardware.wifi.supplicant@1.1",
+ "android.hardware.wifi.supplicant-V1-ndk",
+ "libwifi-system",
+ "libwifi-system-iface",
+ "VtsHalWifiV1_0TargetTestUtil",
+ "VtsHalWifiV1_5TargetTestUtil",
+ "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
new file mode 100644
index 0000000..d5bdde2
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pIfaceCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::BnSupplicantP2pIfaceCallback;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::FreqRange;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::MiracastMode;
+using aidl::android::hardware::wifi::supplicant::P2pGroupCapabilityMask;
+using aidl::android::hardware::wifi::supplicant::P2pProvDiscStatusCode;
+using aidl::android::hardware::wifi::supplicant::P2pStatusCode;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+using aidl::android::hardware::wifi::supplicant::WpsDevPasswordId;
+using aidl::android::hardware::wifi::supplicant::WpsProvisionMethod;
+using android::ProcessState;
+
+namespace {
+const std::string kTestSsidStr = "TestSsid1234";
+const std::vector<uint8_t> kTestSsid =
+ std::vector<uint8_t>(kTestSsidStr.begin(), kTestSsidStr.end());
+const std::vector<uint8_t> kTestMacAddr = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::vector<uint8_t> kTestPeerMacAddr = {0x56, 0x67, 0x55,
+ 0xf4, 0x56, 0x92};
+const std::vector<uint8_t> kTestZeroMacAddr = std::vector<uint8_t>(6, 0);
+const std::string kTestPassphrase = "P2pWorld1234";
+const std::string kTestConnectPin = "34556665";
+const std::string kTestGroupIfName = "TestGroup";
+const uint32_t kTestFindTimeout = 5;
+const uint32_t kTestConnectGoIntent = 6;
+const uint32_t kTestNetworkId = 7;
+const uint32_t kTestGroupFreq = 0;
+const bool kTestGroupPersistent = false;
+const bool kTestGroupIsJoin = false;
+
+} // namespace
+
+class SupplicantP2pIfaceCallback : public BnSupplicantP2pIfaceCallback {
+ public:
+ SupplicantP2pIfaceCallback() = default;
+
+ ::ndk::ScopedAStatus onDeviceFound(
+ const std::vector<uint8_t>& /* srcAddress */,
+ const std::vector<uint8_t>& /* p2pDeviceAddress */,
+ const std::vector<uint8_t>& /* primaryDeviceType */,
+ const std::string& /* deviceName */,
+ WpsConfigMethods /* configMethods */, int8_t /* deviceCapabilities */,
+ P2pGroupCapabilityMask /* groupCapabilities */,
+ const std::vector<uint8_t>& /* wfdDeviceInfo */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDeviceLost(
+ const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onFindStopped() override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGoNegotiationCompleted(
+ P2pStatusCode /* status */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGoNegotiationRequest(
+ const std::vector<uint8_t>& /* srcAddress */,
+ WpsDevPasswordId /* passwordId */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGroupFormationFailure(
+ const std::string& /* failureReason */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGroupFormationSuccess() override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGroupRemoved(const std::string& /* groupIfname */,
+ bool /* isGroupOwner */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onGroupStarted(
+ const std::string& /* groupIfname */, bool /* isGroupOwner */,
+ const std::vector<uint8_t>& /* ssid */, int32_t /* frequency */,
+ const std::vector<uint8_t>& /* psk */,
+ const std::string& /* passphrase */,
+ const std::vector<uint8_t>& /* goDeviceAddress */,
+ bool /* isPersistent */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onInvitationReceived(
+ const std::vector<uint8_t>& /* srcAddress */,
+ const std::vector<uint8_t>& /* goDeviceAddress */,
+ const std::vector<uint8_t>& /* bssid */,
+ int32_t /* persistentNetworkId */,
+ int32_t /* operatingFrequency */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onInvitationResult(
+ const std::vector<uint8_t>& /* bssid */,
+ P2pStatusCode /* status */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onProvisionDiscoveryCompleted(
+ const std::vector<uint8_t>& /* p2pDeviceAddress */,
+ bool /* isRequest */, P2pProvDiscStatusCode /* status */,
+ WpsConfigMethods /* configMethods */,
+ const std::string& /* generatedPin */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onR2DeviceFound(
+ const std::vector<uint8_t>& /* srcAddress */,
+ const std::vector<uint8_t>& /* p2pDeviceAddress */,
+ const std::vector<uint8_t>& /* primaryDeviceType */,
+ const std::string& /* deviceName */,
+ WpsConfigMethods /* configMethods */, int8_t /* deviceCapabilities */,
+ P2pGroupCapabilityMask /* groupCapabilities */,
+ const std::vector<uint8_t>& /* wfdDeviceInfo */,
+ const std::vector<uint8_t>& /* wfdR2DeviceInfo */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onServiceDiscoveryResponse(
+ const std::vector<uint8_t>& /* srcAddress */,
+ char16_t /* updateIndicator */,
+ const std::vector<uint8_t>& /* tlvs */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onStaAuthorized(
+ const std::vector<uint8_t>& /* srcAddress */,
+ const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onStaDeauthorized(
+ const std::vector<uint8_t>& /* srcAddress */,
+ const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+class SupplicantP2pIfaceAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ initializeService();
+ supplicant_ = getSupplicant(GetParam().c_str());
+ ASSERT_NE(supplicant_, nullptr);
+ ASSERT_TRUE(supplicant_
+ ->setDebugParams(DebugLevel::EXCESSIVE,
+ true, // show timestamps
+ true)
+ .isOk());
+
+ bool p2pEnabled =
+ testing::deviceSupportsFeature("android.hardware.wifi.direct");
+ if (!p2pEnabled) {
+ GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
+ }
+
+ EXPECT_TRUE(supplicant_->getP2pInterface(getP2pIfaceName(), &p2p_iface_)
+ .isOk());
+ ASSERT_NE(p2p_iface_, nullptr);
+ }
+
+ void TearDown() override {
+ stopSupplicantService();
+ startWifiFramework();
+ }
+
+ protected:
+ std::shared_ptr<ISupplicant> supplicant_;
+ std::shared_ptr<ISupplicantP2pIface> p2p_iface_;
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RegisterCallback) {
+ std::shared_ptr<SupplicantP2pIfaceCallback> callback =
+ ndk::SharedRefBase::make<SupplicantP2pIfaceCallback>();
+ ASSERT_NE(callback, nullptr);
+ EXPECT_TRUE(p2p_iface_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetName) {
+ std::string name;
+ EXPECT_TRUE(p2p_iface_->getName(&name).isOk());
+ EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetType) {
+ IfaceType type;
+ EXPECT_TRUE(p2p_iface_->getType(&type).isOk());
+ EXPECT_EQ(type, IfaceType::P2P);
+}
+
+/*
+ * GetDeviceAddress
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetDeviceAddress) {
+ std::vector<uint8_t> macAddr;
+ EXPECT_TRUE(p2p_iface_->getDeviceAddress(&macAddr).isOk());
+ EXPECT_EQ(macAddr.size(), 6);
+}
+
+/*
+ * GetSsid
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetSsid) {
+ // This will fail with fake values.
+ std::vector<uint8_t> ssid;
+ EXPECT_FALSE(p2p_iface_->getSsid(kTestMacAddr, &ssid).isOk());
+}
+
+/*
+ * GetGroupCapability
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetGroupCapability) {
+ // This will fail with fake values.
+ P2pGroupCapabilityMask cap;
+ EXPECT_FALSE(p2p_iface_->getGroupCapability(kTestMacAddr, &cap).isOk());
+}
+
+/*
+ * Set/Get Edmg
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetGetEdmg) {
+ bool emdg = false;
+ EXPECT_TRUE(p2p_iface_->setEdmg(true).isOk());
+ EXPECT_TRUE(p2p_iface_->getEdmg(&emdg).isOk());
+ EXPECT_EQ(emdg, true);
+
+ EXPECT_TRUE(p2p_iface_->setEdmg(false).isOk());
+ EXPECT_TRUE(p2p_iface_->getEdmg(&emdg).isOk());
+ EXPECT_EQ(emdg, false);
+}
+
+/*
+ * SetWpsDeviceName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsDeviceName) {
+ const std::string deviceName = "TestWpsDeviceName";
+ EXPECT_TRUE(p2p_iface_->setWpsDeviceName(deviceName).isOk());
+}
+
+/*
+ * SetWpsDeviceType
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsDeviceType) {
+ const std::vector<uint8_t> deviceType = std::vector<uint8_t>(8, 0x01);
+ EXPECT_TRUE(p2p_iface_->setWpsDeviceType(deviceType).isOk());
+}
+
+/*
+ * SetWpsManufacturer
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsManufacturer) {
+ const std::string deviceManufacturer = "TestManufacturer";
+ EXPECT_TRUE(p2p_iface_->setWpsManufacturer(deviceManufacturer).isOk());
+}
+
+/*
+ * SetWpsModelName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsModelName) {
+ const std::string modelName = "TestModelName";
+ EXPECT_TRUE(p2p_iface_->setWpsModelName(modelName).isOk());
+}
+
+/*
+ * SetWpsModelNumber
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsModelNumber) {
+ const std::string modelNumber = "TestModelNumber";
+ EXPECT_TRUE(p2p_iface_->setWpsModelName(modelNumber).isOk());
+}
+
+/*
+ * SetWpsSerialNumber
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsSerialNumber) {
+ const std::string serialNumber = "TestSerialNumber";
+ EXPECT_TRUE(p2p_iface_->setWpsSerialNumber(serialNumber).isOk());
+}
+
+/*
+ * SetWpsConfigMethods
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsConfigMethods) {
+ const WpsConfigMethods config = WpsConfigMethods::DISPLAY;
+ EXPECT_TRUE(p2p_iface_->setWpsConfigMethods(config).isOk());
+}
+
+/*
+ * SetSsidPostfix
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetSsidPostfix) {
+ const std::vector<uint8_t> ssidPostfix = {'t', 'e', 's', 't'};
+ EXPECT_TRUE(p2p_iface_->setSsidPostfix(ssidPostfix).isOk());
+}
+
+/*
+ * SetWfdDeviceInfo
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWfdDeviceInfo) {
+ const std::vector<uint8_t> wfdDeviceInfo = std::vector<uint8_t>(6, 0x01);
+ EXPECT_TRUE(p2p_iface_->setWfdDeviceInfo(wfdDeviceInfo).isOk());
+}
+
+/*
+ * SetWfdR2DeviceInfo
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWfdR2DeviceInfo) {
+ const std::vector<uint8_t> wfdR2DeviceInfo = std::vector<uint8_t>(4, 0x01);
+ EXPECT_TRUE(p2p_iface_->setWfdR2DeviceInfo(wfdR2DeviceInfo).isOk());
+}
+
+/*
+ * SetGroupIdle
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetGroupIdle) {
+ // This will fail with fake values.
+ const uint32_t groupIdleTimeout = 8;
+ EXPECT_FALSE(
+ p2p_iface_->setGroupIdle(kTestGroupIfName, groupIdleTimeout).isOk());
+}
+
+/*
+ * SetPowerSave
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetPowerSave) {
+ // This will fail with fake values.
+ EXPECT_FALSE(p2p_iface_->setPowerSave(kTestGroupIfName, true).isOk());
+ EXPECT_FALSE(p2p_iface_->setPowerSave(kTestGroupIfName, false).isOk());
+}
+
+/*
+ * SetMiracastMode
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetMiracastMode) {
+ EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::DISABLED).isOk());
+ EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::SOURCE).isOk());
+ EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::SINK).isOk());
+}
+
+/*
+ * SetDisallowedFrequencies
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetDisallowedFrequencies) {
+ FreqRange range1;
+ range1.min = 2412;
+ range1.max = 2432;
+ const std::vector<FreqRange> ranges = {range1};
+ EXPECT_TRUE(p2p_iface_->setDisallowedFrequencies(ranges).isOk());
+}
+
+/*
+ * SetListenChannel
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetListenChannel) {
+ const uint32_t testChannel = 1;
+ const uint32_t testOperatingClass = 81;
+ EXPECT_TRUE(
+ p2p_iface_->setListenChannel(testChannel, testOperatingClass).isOk());
+}
+
+/*
+ * SetMacRandomization
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, EnableMacRandomization) {
+ // Enable twice
+ EXPECT_TRUE(p2p_iface_->setMacRandomization(true).isOk());
+ EXPECT_TRUE(p2p_iface_->setMacRandomization(true).isOk());
+
+ // Disable twice
+ EXPECT_TRUE(p2p_iface_->setMacRandomization(false).isOk());
+ EXPECT_TRUE(p2p_iface_->setMacRandomization(false).isOk());
+}
+
+/*
+ * AddGroup
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroup) {
+ EXPECT_TRUE(p2p_iface_->addGroup(false, kTestNetworkId).isOk());
+}
+
+/*
+ * RemoveGroup
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RemoveGroup) {
+ // This will fail with fake values.
+ EXPECT_FALSE(p2p_iface_->removeGroup(kTestGroupIfName).isOk());
+}
+
+/*
+ * AddGroupWithConfig - success.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_Success) {
+ EXPECT_TRUE(p2p_iface_
+ ->addGroupWithConfig(kTestSsid, kTestPassphrase,
+ kTestGroupPersistent, kTestGroupFreq,
+ kTestZeroMacAddr, kTestGroupIsJoin)
+ .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid SSID.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_FailureInvalidSsid) {
+ const std::vector<uint8_t> ssid;
+ EXPECT_FALSE(p2p_iface_
+ ->addGroupWithConfig(ssid, kTestPassphrase,
+ kTestGroupPersistent, kTestGroupFreq,
+ kTestZeroMacAddr, kTestGroupIsJoin)
+ .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid passphrase.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest,
+ AddGroupWithConfig_FailureInvalidPassphrase) {
+ const std::string passphrase = "1234";
+ EXPECT_FALSE(p2p_iface_
+ ->addGroupWithConfig(kTestSsid, passphrase,
+ kTestGroupPersistent, kTestGroupFreq,
+ kTestZeroMacAddr, kTestGroupIsJoin)
+ .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid frequency.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_FailureInvalidFrequency) {
+ const int freq = 9999;
+ EXPECT_FALSE(p2p_iface_
+ ->addGroupWithConfig(kTestSsid, kTestPassphrase,
+ kTestGroupPersistent, freq,
+ kTestZeroMacAddr, kTestGroupIsJoin)
+ .isOk());
+}
+
+/*
+ * Find
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Find) {
+ EXPECT_TRUE(p2p_iface_->find(kTestFindTimeout).isOk());
+}
+
+/*
+ * StopFind
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, StopFind) {
+ EXPECT_TRUE(p2p_iface_->find(kTestFindTimeout).isOk());
+ EXPECT_TRUE(p2p_iface_->stopFind().isOk());
+}
+
+/*
+ * Flush
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Flush) {
+ EXPECT_TRUE(p2p_iface_->flush().isOk());
+}
+
+/*
+ * Connect
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Connect) {
+ /*
+ * Auto-join is not enabled before R. After enabling auto-join,
+ * this should always succeed.
+ */
+ std::string pin;
+ EXPECT_TRUE(p2p_iface_
+ ->connect(kTestMacAddr, WpsProvisionMethod::PBC,
+ kTestConnectPin, false, false,
+ kTestConnectGoIntent, &pin)
+ .isOk());
+}
+
+/*
+ * CancelConnect
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, CancelConnect) {
+ std::string pin;
+ EXPECT_TRUE(p2p_iface_
+ ->connect(kTestMacAddr, WpsProvisionMethod::PBC,
+ kTestConnectPin, false, false,
+ kTestConnectGoIntent, &pin)
+ .isOk());
+ EXPECT_TRUE(p2p_iface_->cancelConnect().isOk());
+}
+
+/*
+ * ProvisionDiscovery
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ProvisionDiscovery) {
+ // This will fail with fake values.
+ EXPECT_FALSE(
+ p2p_iface_->provisionDiscovery(kTestMacAddr, WpsProvisionMethod::PBC)
+ .isOk());
+}
+
+/*
+ * Reject
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Reject) {
+ // This will fail with fake values.
+ ASSERT_FALSE(p2p_iface_->reject(kTestMacAddr).isOk());
+}
+
+/*
+ * Invite
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Invite) {
+ // This will fail with fake values.
+ EXPECT_FALSE(
+ p2p_iface_->invite(kTestGroupIfName, kTestMacAddr, kTestPeerMacAddr)
+ .isOk());
+}
+
+/*
+ * Reinvoke
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Reinvoke) {
+ // This will fail with fake values.
+ EXPECT_FALSE(p2p_iface_->reinvoke(kTestNetworkId, kTestMacAddr).isOk());
+}
+
+/*
+ * ConfigureExtListen
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ConfigureExtListen) {
+ const uint32_t extListenPeriod = 400;
+ const uint32_t extListenInterval = 400;
+ EXPECT_TRUE(
+ p2p_iface_->configureExtListen(extListenPeriod, extListenInterval)
+ .isOk());
+}
+
+/*
+ * FlushServices
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, FlushServices) {
+ EXPECT_TRUE(p2p_iface_->flushServices().isOk());
+}
+
+/*
+ * EnableWfd
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, EnableWfd) {
+ EXPECT_TRUE(p2p_iface_->enableWfd(true).isOk());
+ EXPECT_TRUE(p2p_iface_->enableWfd(false).isOk());
+}
+
+/*
+ * Add/Remove BonjourService
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddAndRemoveBonjourService) {
+ const std::string serviceQueryStr = "testquery";
+ const std::string serviceResponseStr = "testresponse";
+ const std::vector<uint8_t> bonjourServiceQuery =
+ std::vector<uint8_t>(serviceQueryStr.begin(), serviceQueryStr.end());
+ const std::vector<uint8_t> bonjourServiceResponse = std::vector<uint8_t>(
+ serviceResponseStr.begin(), serviceResponseStr.end());
+
+ EXPECT_TRUE(
+ p2p_iface_
+ ->addBonjourService(bonjourServiceQuery, bonjourServiceResponse)
+ .isOk());
+ EXPECT_TRUE(p2p_iface_->removeBonjourService(bonjourServiceQuery).isOk());
+
+ // This will fail because the boujour service with
+ // bonjourServiceQuery was already removed.
+ EXPECT_FALSE(p2p_iface_->removeBonjourService(bonjourServiceQuery).isOk());
+}
+
+/*
+ * Add/Remove UpnpService
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddAndRemoveUpnpService) {
+ const std::string upnpServiceName = "TestServiceName";
+ EXPECT_TRUE(
+ p2p_iface_->addUpnpService(0 /* version */, upnpServiceName).isOk());
+ EXPECT_TRUE(
+ p2p_iface_->removeUpnpService(0 /* version */, upnpServiceName).isOk());
+
+ // This will fail because Upnp service with
+ // upnpServiceName was already removed.
+ EXPECT_FALSE(
+ p2p_iface_->removeUpnpService(0 /* version */, upnpServiceName).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantP2pIfaceAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ ISupplicant::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
new file mode 100644
index 0000000..b24f502
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaIfaceCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::AnqpInfoId;
+using aidl::android::hardware::wifi::supplicant::BnSupplicantStaIfaceCallback;
+using aidl::android::hardware::wifi::supplicant::BtCoexistenceMode;
+using aidl::android::hardware::wifi::supplicant::ConnectionCapabilities;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::DppAkm;
+using aidl::android::hardware::wifi::supplicant::DppCurve;
+using aidl::android::hardware::wifi::supplicant::DppNetRole;
+using aidl::android::hardware::wifi::supplicant::DppResponderBootstrapInfo;
+using aidl::android::hardware::wifi::supplicant::Hs20AnqpSubtypes;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::RxFilterType;
+using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+using android::ProcessState;
+
+static constexpr int TIMEOUT_PERIOD = 60;
+class IfaceDppCallback;
+
+namespace {
+const std::vector<uint8_t> kTestMacAddr = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::string kTestUri =
+ "DPP:C:81/1,117/"
+ "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+ "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
+} // namespace
+
+class SupplicantStaIfaceCallback : public BnSupplicantStaIfaceCallback {
+ public:
+ SupplicantStaIfaceCallback() = default;
+
+ ::ndk::ScopedAStatus onAnqpQueryDone(
+ const std::vector<uint8_t>& /* bssid */,
+ const ::aidl::android::hardware::wifi::supplicant::AnqpData& /* data */,
+ const ::aidl::android::hardware::wifi::supplicant::
+ Hs20AnqpData& /* hs20Data */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onAssociationRejected(
+ const ::aidl::android::hardware::wifi::supplicant::
+ AssociationRejectionData& /* assocRejectData */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onAuthenticationTimeout(
+ const std::vector<uint8_t>& /* bssid */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onBssTmHandlingDone(
+ const ::aidl::android::hardware::wifi::supplicant::
+ BssTmData& /* tmData */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onBssidChanged(
+ ::aidl::android::hardware::wifi::supplicant::
+ BssidChangeReason /* reason */,
+ const std::vector<uint8_t>& /* bssid */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDisconnected(
+ const std::vector<uint8_t>& /* bssid */, bool /* locallyGenerated */,
+ ::aidl::android::hardware::wifi::supplicant::
+ StaIfaceReasonCode /* reasonCode */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppFailure(
+ ::aidl::android::hardware::wifi::supplicant::DppFailureCode /* code */,
+ const std::string& /* ssid */, const std::string& /* channelList */,
+ const std::vector<char16_t>& /* bandList */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppProgress(
+ ::aidl::android::hardware::wifi::supplicant::DppProgressCode /* code */)
+ override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppSuccess(
+ ::aidl::android::hardware::wifi::supplicant::DppEventType /* type */)
+ override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppSuccessConfigReceived(
+ const std::vector<uint8_t>& /* ssid */,
+ const std::string& /* password */,
+ const std::vector<uint8_t>& /* psk */,
+ ::aidl::android::hardware::wifi::supplicant::DppAkm /* securityAkm */)
+ override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppSuccessConfigSent() override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onEapFailure(int32_t /* errorCode */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onExtRadioWorkStart(int32_t /* id */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onExtRadioWorkTimeout(int32_t /* id */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onHs20DeauthImminentNotice(
+ const std::vector<uint8_t>& /* bssid */, int32_t /* reasonCode */,
+ int32_t /* reAuthDelayInSec */, const std::string& /* url */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onHs20IconQueryDone(
+ const std::vector<uint8_t>& /* bssid */,
+ const std::string& /* fileName */,
+ const std::vector<uint8_t>& /* data */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onHs20SubscriptionRemediation(
+ const std::vector<uint8_t>& /* bssid */,
+ ::aidl::android::hardware::wifi::supplicant::OsuMethod /* osuMethod */,
+ const std::string& /* url */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus
+ onHs20TermsAndConditionsAcceptanceRequestedNotification(
+ const std::vector<uint8_t>& /* bssid */,
+ const std::string& /* url */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onNetworkAdded(int32_t /* id */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onNetworkNotFound(
+ const std::vector<uint8_t>& /* ssid */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onNetworkRemoved(int32_t /* id */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onPmkCacheAdded(
+ int64_t /* expirationTimeInSec */,
+ const std::vector<uint8_t>& /* serializedEntry */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onStateChanged(
+ ::aidl::android::hardware::wifi::supplicant::
+ StaIfaceCallbackState /* newState */,
+ const std::vector<uint8_t>& /* bssid */, int32_t /* id */,
+ const std::vector<uint8_t>& /* ssid */,
+ bool /* filsHlpSent */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onWpsEventFail(
+ const std::vector<uint8_t>& /* bssid */,
+ ::aidl::android::hardware::wifi::supplicant::
+ WpsConfigError /* configError */,
+ ::aidl::android::hardware::wifi::supplicant::
+ WpsErrorIndication /* errorInd */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onWpsEventPbcOverlap() override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onWpsEventSuccess() override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+class SupplicantStaIfaceAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ initializeService();
+ supplicant_ = getSupplicant(GetParam().c_str());
+ ASSERT_NE(supplicant_, nullptr);
+ ASSERT_TRUE(supplicant_
+ ->setDebugParams(DebugLevel::EXCESSIVE,
+ true, // show timestamps
+ true)
+ .isOk());
+ EXPECT_TRUE(supplicant_->getStaInterface(getStaIfaceName(), &sta_iface_)
+ .isOk());
+ ASSERT_NE(sta_iface_, nullptr);
+ }
+
+ void TearDown() override {
+ stopSupplicantService();
+ startWifiFramework();
+ }
+
+ enum DppCallbackType {
+ ANY_CALLBACK = -2,
+ INVALID = -1,
+ EVENT_SUCCESS = 0,
+ EVENT_PROGRESS,
+ EVENT_FAILURE,
+ };
+
+ DppCallbackType dppCallbackType;
+ uint32_t code;
+
+ // Used as a mechanism to inform the test about data/event callback
+ inline void notify() {
+ std::unique_lock<std::mutex> lock(mtx_);
+ cv_.notify_one();
+ }
+
+ // Test code calls this function to wait for data/event callback
+ inline std::cv_status wait(DppCallbackType waitForCallbackType) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a
+ // non-void-returning method
+ auto now = std::chrono::system_clock::now();
+ std::cv_status status =
+ cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ return status;
+ }
+
+ protected:
+ std::shared_ptr<ISupplicant> supplicant_;
+ std::shared_ptr<ISupplicantStaIface> sta_iface_;
+
+ private:
+ // synchronization objects
+ std::mutex mtx_;
+ std::condition_variable cv_;
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RegisterCallback) {
+ std::shared_ptr<SupplicantStaIfaceCallback> callback =
+ ndk::SharedRefBase::make<SupplicantStaIfaceCallback>();
+ ASSERT_NE(callback, nullptr);
+ EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetConnectionCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetConnectionCapabilities) {
+ ConnectionCapabilities cap;
+ EXPECT_TRUE(sta_iface_->getConnectionCapabilities(&cap).isOk());
+}
+
+/*
+ * GetWpaDriverCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetWpaDriverCapabilities) {
+ WpaDriverCapabilitiesMask cap;
+ EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&cap).isOk());
+}
+
+/*
+ * GetKeyMgmtCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetKeyMgmtCapabilities) {
+ KeyMgmtMask cap;
+ EXPECT_TRUE(sta_iface_->getKeyMgmtCapabilities(&cap).isOk());
+
+ // Even though capabilities vary, these two are always set.
+ EXPECT_TRUE(!!(static_cast<uint32_t>(cap) &
+ static_cast<uint32_t>(KeyMgmtMask::NONE)));
+ EXPECT_TRUE(!!(static_cast<uint32_t>(cap) &
+ static_cast<uint32_t>(KeyMgmtMask::IEEE8021X)));
+}
+
+/*
+ * GetName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetName) {
+ std::string name;
+ EXPECT_TRUE(sta_iface_->getName(&name).isOk());
+ EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetType) {
+ IfaceType type;
+ EXPECT_TRUE(sta_iface_->getType(&type).isOk());
+ EXPECT_EQ(type, IfaceType::STA);
+}
+
+/*
+ * GetMacAddress
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetMacAddress) {
+ std::vector<uint8_t> macAddr;
+ EXPECT_TRUE(sta_iface_->getMacAddress(&macAddr).isOk());
+ EXPECT_EQ(macAddr.size(), 6);
+}
+
+/*
+ * ListNetworks
+ */
+TEST_P(SupplicantStaIfaceAidlTest, ListNetworks) {
+ std::vector<int32_t> networks;
+ EXPECT_TRUE(sta_iface_->listNetworks(&networks).isOk());
+}
+
+/*
+ * SetBtCoexistenceMode
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetBtCoexistenceMode) {
+ EXPECT_TRUE(
+ sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::ENABLED).isOk());
+ EXPECT_TRUE(
+ sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::DISABLED).isOk());
+ EXPECT_TRUE(
+ sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::SENSE).isOk());
+}
+
+/*
+ * SetBtCoexistenceScanModeEnabled
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetBtCoexistenceScanModeEnabled) {
+ EXPECT_TRUE(sta_iface_->setBtCoexistenceScanModeEnabled(true).isOk());
+ EXPECT_TRUE(sta_iface_->setBtCoexistenceScanModeEnabled(false).isOk());
+}
+
+/*
+ * SetSuspendModeEnabled
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetSuspendModeEnabled) {
+ EXPECT_TRUE(sta_iface_->setSuspendModeEnabled(true).isOk());
+ EXPECT_TRUE(sta_iface_->setSuspendModeEnabled(false).isOk());
+}
+
+/*
+ * SetCountryCode
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetCountryCode) {
+ const std::vector<uint8_t> countryCode = {'M', 'X'};
+ EXPECT_TRUE(sta_iface_->setCountryCode(countryCode).isOk());
+}
+
+/*
+ * SetWpsDeviceName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsDeviceName) {
+ const std::string deviceName = "TestWpsDeviceName";
+ EXPECT_TRUE(sta_iface_->setWpsDeviceName(deviceName).isOk());
+}
+
+/*
+ * SetWpsDeviceType
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsDeviceType) {
+ const std::vector<uint8_t> deviceType = {8, 0x1};
+ EXPECT_TRUE(sta_iface_->setWpsDeviceType(deviceType).isOk());
+}
+
+/*
+ * SetWpsManufacturer
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsManufacturer) {
+ const std::string wpsManufacturer = "TestManufacturer";
+ EXPECT_TRUE(sta_iface_->setWpsManufacturer(wpsManufacturer).isOk());
+}
+
+/*
+ * SetWpsModelName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsModelName) {
+ const std::string modelName = "TestModelName";
+ EXPECT_TRUE(sta_iface_->setWpsModelName(modelName).isOk());
+}
+
+/*
+ * SetWpsModelNumber
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsModelNumber) {
+ const std::string modelNumber = "TestModelNumber";
+ EXPECT_TRUE(sta_iface_->setWpsModelNumber(modelNumber).isOk());
+}
+
+/*
+ * SetWpsSerialNumber
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsSerialNumber) {
+ const std::string serialNumber = "TestSerialNumber";
+ EXPECT_TRUE(sta_iface_->setWpsSerialNumber(serialNumber).isOk());
+}
+
+/*
+ * SetWpsConfigMethods
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsConfigMethods) {
+ const WpsConfigMethods configMethods = WpsConfigMethods::KEYPAD;
+ EXPECT_TRUE(sta_iface_->setWpsConfigMethods(configMethods).isOk());
+}
+
+/*
+ * SetExternalSim
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetExternalSim) {
+ EXPECT_TRUE(sta_iface_->setExternalSim(true).isOk());
+ EXPECT_TRUE(sta_iface_->setExternalSim(false).isOk());
+}
+
+/*
+ * SetMboCellularDataStatus
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetMboCellularDataStatus) {
+ WpaDriverCapabilitiesMask cap;
+ EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&cap).isOk());
+
+ // Operation should succeed if MBO is supported, or fail if it's not.
+ bool mboSupported =
+ !!(static_cast<uint32_t>(cap) &
+ static_cast<uint32_t>(WpaDriverCapabilitiesMask::MBO));
+ EXPECT_EQ(mboSupported, sta_iface_->setMboCellularDataStatus(true).isOk());
+}
+
+/*
+ * InitiateTdlsDiscover
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsDiscover) {
+ EXPECT_TRUE(sta_iface_->initiateTdlsDiscover(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateTdlsSetup
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsSetup) {
+ EXPECT_TRUE(sta_iface_->initiateTdlsSetup(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateTdlsTeardown
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsTeardown) {
+ EXPECT_TRUE(sta_iface_->initiateTdlsTeardown(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateAnqpQuery
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateAnqpQuery) {
+ const std::vector<AnqpInfoId> anqpIds = {
+ AnqpInfoId::VENUE_NAME, AnqpInfoId::NAI_REALM, AnqpInfoId::DOMAIN_NAME};
+ const std::vector<Hs20AnqpSubtypes> hsTypes = {
+ Hs20AnqpSubtypes::WAN_METRICS,
+ Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME};
+
+ // Request should fail since the BSSID mentioned
+ // is not present in the scan results
+ EXPECT_FALSE(
+ sta_iface_->initiateAnqpQuery(kTestMacAddr, anqpIds, hsTypes).isOk());
+}
+
+/*
+ * InitiateHs20IconQuery
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateHs20IconQuery) {
+ // Request should fail since the BSSID mentioned
+ // is not present in the scan results
+ const std::string hs20IconFile = "TestFile";
+ EXPECT_FALSE(
+ sta_iface_->initiateHs20IconQuery(kTestMacAddr, hs20IconFile).isOk());
+}
+
+/*
+ * InitiateVenueUrlAnqpQuery.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateVenueUrlAnqpQuery) {
+ // Request should fail since the BSSID mentioned
+ // is not present in the scan results
+ EXPECT_FALSE(sta_iface_->initiateVenueUrlAnqpQuery(kTestMacAddr).isOk());
+}
+
+/*
+ * Reassociate
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Reassociate) {
+ EXPECT_TRUE(sta_iface_->reassociate().isOk());
+}
+
+/*
+ * Reconnect
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Reconnect) {
+ EXPECT_FALSE(sta_iface_->reconnect().isOk());
+}
+
+/*
+ * Disconnect
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Disconnect) {
+ EXPECT_TRUE(sta_iface_->disconnect().isOk());
+}
+
+/*
+ * SetPowerSave
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetPowerSave) {
+ EXPECT_TRUE(sta_iface_->setPowerSave(true).isOk());
+ EXPECT_TRUE(sta_iface_->setPowerSave(false).isOk());
+}
+
+/*
+ * StartRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartRxFilter) {
+ EXPECT_TRUE(sta_iface_->startRxFilter().isOk());
+}
+
+/*
+ * StopRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StopRxFilter) {
+ EXPECT_TRUE(sta_iface_->stopRxFilter().isOk());
+}
+
+/*
+ * AddRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddRxFilter) {
+ EXPECT_TRUE(sta_iface_->addRxFilter(RxFilterType::V4_MULTICAST).isOk());
+ EXPECT_TRUE(sta_iface_->addRxFilter(RxFilterType::V6_MULTICAST).isOk());
+}
+
+/*
+ * RemoveRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RemoveRxFilter) {
+ EXPECT_TRUE(sta_iface_->removeRxFilter(RxFilterType::V4_MULTICAST).isOk());
+ EXPECT_TRUE(sta_iface_->removeRxFilter(RxFilterType::V6_MULTICAST).isOk());
+}
+
+/*
+ * AddExtRadioWork
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddExtRadioWork) {
+ const std::string radioWorkName = "TestRadioWork";
+ const int32_t radioWorkFreq = 2412;
+ const int32_t radioWorkTimeout = 8;
+ int32_t radioWorkId;
+ EXPECT_TRUE(sta_iface_
+ ->addExtRadioWork(radioWorkName, radioWorkFreq,
+ radioWorkTimeout, &radioWorkId)
+ .isOk());
+ // removeExtRadio only succeeds if the added radio work hasn't started yet,
+ // so there is no guaranteed result from calling removeExtRadioWork here.
+ // Given that, we can't currently test removeExtRadioWork following
+ // a call to addExtRadioWork.
+}
+
+/*
+ * RemoveExtRadioWork
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RemoveExtRadioWork) {
+ // This fails because there is no ongoing radio work with radioWorkId
+ const int32_t radioWorkId = 16;
+ EXPECT_FALSE(sta_iface_->removeExtRadioWork(radioWorkId).isOk());
+}
+
+/*
+ * Add/Remove DppPeerUri
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddRemoveDppPeerUri) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+ // Add a peer URI and then remove it.
+ int32_t peerId;
+ EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peerId).isOk());
+ EXPECT_TRUE(sta_iface_->removeDppUri(peerId).isOk());
+}
+
+/*
+ * FilsHlpAddRequest
+ */
+TEST_P(SupplicantStaIfaceAidlTest, FilsHlpAddRequest) {
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
+ const std::vector<uint8_t> destMacAddr = {0x00, 0x11, 0x22,
+ 0x33, 0x44, 0x55};
+ const std::vector<uint8_t> pktBuffer = std::vector<uint8_t>(300, 0x3a);
+ EXPECT_TRUE(sta_iface_->filsHlpAddRequest(destMacAddr, pktBuffer).isOk());
+}
+
+/*
+ * FilsHlpFlushRequest
+ */
+TEST_P(SupplicantStaIfaceAidlTest, FilsHlpFlushRequest) {
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
+ EXPECT_TRUE(sta_iface_->filsHlpFlushRequest().isOk());
+}
+
+/*
+ * StartDppEnrolleeResponder
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppEnrolleeResponder) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+
+ const std::string deviceInfo = "DPP_Responder_Mode_VTS_Test";
+ const std::vector<uint8_t> mac_address = {0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77};
+
+ // Generate DPP bootstrap information.
+ DppResponderBootstrapInfo bootstrapInfo;
+ EXPECT_TRUE(
+ sta_iface_
+ ->generateDppBootstrapInfoForResponder(
+ mac_address, deviceInfo, DppCurve::PRIME256V1, &bootstrapInfo)
+ .isOk());
+ EXPECT_NE(-1, bootstrapInfo.bootstrapId);
+ EXPECT_NE(0, bootstrapInfo.bootstrapId);
+ EXPECT_NE(0, bootstrapInfo.listenChannel);
+ const uint32_t bootstrap_id = bootstrapInfo.bootstrapId;
+ const uint32_t listen_channel = bootstrapInfo.listenChannel;
+
+ // Start DPP as Enrollee-Responder.
+ EXPECT_TRUE(sta_iface_->startDppEnrolleeResponder(listen_channel).isOk());
+
+ // Stop DPP Enrollee-Responder mode, ie remove the URI and stop listen.
+ EXPECT_TRUE(sta_iface_->stopDppResponder(bootstrap_id).isOk());
+}
+
+class IfaceDppCallback : public SupplicantStaIfaceCallback {
+ SupplicantStaIfaceAidlTest& parent_;
+ ::ndk::ScopedAStatus onDppSuccess(
+ ::aidl::android::hardware::wifi::supplicant::DppEventType event)
+ override {
+ parent_.code = (uint32_t)event;
+ parent_.dppCallbackType =
+ SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_SUCCESS;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppProgress(
+ aidl::android::hardware::wifi::supplicant::DppProgressCode code)
+ override {
+ parent_.code = (uint32_t)code;
+ parent_.dppCallbackType =
+ SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_PROGRESS;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDppFailure(
+ aidl::android::hardware::wifi::supplicant::DppFailureCode code,
+ const std::string& ssid __attribute__((unused)),
+ const std::string& channelList __attribute__((unused)),
+ const std::vector<char16_t>& bandList
+ __attribute__((unused))) override {
+ parent_.code = (uint32_t)code;
+ parent_.dppCallbackType =
+ SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ public:
+ IfaceDppCallback(SupplicantStaIfaceAidlTest& parent) : parent_(parent){};
+};
+
+/*
+ * StartDppEnrolleeInitiator
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppEnrolleeInitiator) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+
+ // Register callback
+ std::shared_ptr<IfaceDppCallback> callback =
+ ndk::SharedRefBase::make<IfaceDppCallback>(*this);
+ EXPECT_NE(callback, nullptr);
+ EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+
+ // Add a peer URI
+ int32_t peer_id = 0;
+ EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peer_id).isOk());
+ EXPECT_NE(0, peer_id);
+ EXPECT_NE(-1, peer_id);
+
+ // Start DPP as Enrollee-Initiator. Since this operation requires two
+ // devices, we start the operation and expect a timeout.
+ EXPECT_TRUE(sta_iface_->startDppEnrolleeInitiator(peer_id, 0).isOk());
+
+ // Wait for the timeout callback
+ EXPECT_EQ(std::cv_status::no_timeout,
+ wait(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE));
+ EXPECT_EQ(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE,
+ dppCallbackType);
+
+ // ...and then remove the peer URI.
+ EXPECT_TRUE(sta_iface_->removeDppUri(peer_id).isOk());
+}
+
+/*
+ * StartDppConfiguratorInitiator
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppConfiguratorInitiator) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+
+ // Register callback
+ std::shared_ptr<IfaceDppCallback> callback =
+ ndk::SharedRefBase::make<IfaceDppCallback>(*this);
+ EXPECT_NE(callback, nullptr);
+ EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+
+ // Add a peer URI
+ int32_t peer_id = 0;
+ EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peer_id).isOk());
+ EXPECT_NE(0, peer_id);
+ EXPECT_NE(-1, peer_id);
+
+ const std::string ssid =
+ "6D795F746573745F73736964"; // 'my_test_ssid' encoded in hex
+ const std::string password =
+ "746F70736563726574"; // 'topsecret' encoded in hex
+
+ // Start DPP as Configurator-Initiator. Since this operation requires two
+ // devices, we start the operation and expect a timeout.
+ EXPECT_TRUE(sta_iface_
+ ->startDppConfiguratorInitiator(peer_id, 0, ssid, password,
+ "", DppNetRole::STA,
+ DppAkm::PSK)
+ .isOk());
+
+ // Wait for the timeout callback
+ ASSERT_EQ(std::cv_status::no_timeout,
+ wait(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE));
+ ASSERT_EQ(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE,
+ dppCallbackType);
+
+ // ...and then remove the peer URI.
+ EXPECT_TRUE(sta_iface_->removeDppUri(peer_id).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaIfaceAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ ISupplicant::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
new file mode 100644
index 0000000..a19b300
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -0,0 +1,791 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaNetworkCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::AuthAlgMask;
+using aidl::android::hardware::wifi::supplicant::BnSupplicantStaNetworkCallback;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::EapMethod;
+using aidl::android::hardware::wifi::supplicant::EapPhase2Method;
+using aidl::android::hardware::wifi::supplicant::GroupCipherMask;
+using aidl::android::hardware::wifi::supplicant::GroupMgmtCipherMask;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::
+ NetworkRequestEapSimGsmAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+ NetworkRequestEapSimUmtsAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+ NetworkResponseEapSimGsmAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+ NetworkResponseEapSimUmtsAuthParams;
+using aidl::android::hardware::wifi::supplicant::OcspType;
+using aidl::android::hardware::wifi::supplicant::PairwiseCipherMask;
+using aidl::android::hardware::wifi::supplicant::ProtoMask;
+using aidl::android::hardware::wifi::supplicant::SaeH2eMode;
+using aidl::android::hardware::wifi::supplicant::TransitionDisableIndication;
+using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
+using android::ProcessState;
+
+namespace {
+const std::vector<uint8_t> kTestIdentity = {0x45, 0x67, 0x98, 0x67, 0x56};
+const std::vector<uint8_t> kTestEncryptedIdentity = {0x35, 0x37, 0x58, 0x57,
+ 0x26};
+const std::string kTestSsidStr = "TestSsid1234";
+const std::vector<uint8_t> kTestSsid =
+ std::vector<uint8_t>(kTestSsidStr.begin(), kTestSsidStr.end());
+const std::vector<uint8_t> kTestBssid = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::string kTestPskPassphrase =
+ "\"123456780abcdef0123456780abcdef0deadbeef\"";
+const std::string kTestEapCert = "keystore://CERT";
+const std::string kTestEapMatch = "match";
+const KeyMgmtMask kTestKeyMgmt =
+ static_cast<KeyMgmtMask>(static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) |
+ static_cast<uint32_t>(KeyMgmtMask::WPA_EAP));
+
+} // namespace
+
+class SupplicantStaNetworkCallback : public BnSupplicantStaNetworkCallback {
+ public:
+ SupplicantStaNetworkCallback() = default;
+
+ ::ndk::ScopedAStatus onNetworkEapIdentityRequest() override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onNetworkEapSimGsmAuthRequest(
+ const NetworkRequestEapSimGsmAuthParams& /* params */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onNetworkEapSimUmtsAuthRequest(
+ const NetworkRequestEapSimUmtsAuthParams& /* params */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onTransitionDisable(
+ TransitionDisableIndication /* ind */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+class SupplicantStaNetworkAidlTest
+ : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ initializeService();
+ supplicant_ = getSupplicant(GetParam().c_str());
+ ASSERT_NE(supplicant_, nullptr);
+ ASSERT_TRUE(supplicant_
+ ->setDebugParams(DebugLevel::EXCESSIVE,
+ true, // show timestamps
+ true)
+ .isOk());
+ EXPECT_TRUE(supplicant_->getStaInterface(getStaIfaceName(), &sta_iface_)
+ .isOk());
+ ASSERT_NE(sta_iface_, nullptr);
+ EXPECT_TRUE(sta_iface_->addNetwork(&sta_network_).isOk());
+ ASSERT_NE(sta_network_, nullptr);
+ }
+
+ void TearDown() override {
+ stopSupplicantService();
+ startWifiFramework();
+ }
+
+ protected:
+ std::shared_ptr<ISupplicant> supplicant_;
+ std::shared_ptr<ISupplicantStaIface> sta_iface_;
+ std::shared_ptr<ISupplicantStaNetwork> sta_network_;
+
+ void removeNetwork() {
+ ASSERT_NE(sta_iface_, nullptr);
+ int32_t net_id;
+ EXPECT_TRUE(sta_network_->getId(&net_id).isOk());
+ EXPECT_TRUE(sta_iface_->removeNetwork(net_id).isOk());
+ }
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantStaNetworkAidlTest, RegisterCallback) {
+ std::shared_ptr<SupplicantStaNetworkCallback> callback =
+ ndk::SharedRefBase::make<SupplicantStaNetworkCallback>();
+ ASSERT_NE(callback, nullptr);
+ EXPECT_TRUE(sta_network_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetInterfaceName
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetInterfaceName) {
+ std::string name;
+ EXPECT_TRUE(sta_network_->getInterfaceName(&name).isOk());
+ EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetType) {
+ IfaceType type;
+ EXPECT_TRUE(sta_network_->getType(&type).isOk());
+ EXPECT_EQ(type, IfaceType::STA);
+}
+
+/*
+ * Set/Get ScanSsid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetScanSsid) {
+ bool scanSsid = false;
+ EXPECT_TRUE(sta_network_->setScanSsid(true).isOk());
+ EXPECT_TRUE(sta_network_->getScanSsid(&scanSsid).isOk());
+ EXPECT_TRUE(scanSsid);
+}
+
+/*
+ * Set/Get RequirePmf
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetRequirePmf) {
+ bool requirePmf = false;
+ EXPECT_TRUE(sta_network_->setRequirePmf(true).isOk());
+ EXPECT_TRUE(sta_network_->getRequirePmf(&requirePmf).isOk());
+ EXPECT_TRUE(requirePmf);
+}
+
+/*
+ * Set/Get IdStr
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetIdStr) {
+ const std::string savedIdStr = "TestIdstr";
+ EXPECT_TRUE(sta_network_->setIdStr(savedIdStr).isOk());
+
+ std::string retrievedIdStr;
+ EXPECT_TRUE(sta_network_->getIdStr(&retrievedIdStr).isOk());
+ EXPECT_EQ(retrievedIdStr, savedIdStr);
+}
+
+/*
+ * Set/Get EapMethod
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapMethod) {
+ const EapMethod savedMethod = EapMethod::PEAP;
+ EXPECT_TRUE(sta_network_->setEapMethod(savedMethod).isOk());
+
+ EapMethod retrievedMethod;
+ EXPECT_TRUE(sta_network_->getEapMethod(&retrievedMethod).isOk());
+ EXPECT_EQ(retrievedMethod, savedMethod);
+}
+
+/*
+ * Set/Get EapPhase2Method
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPhase2Method) {
+ const EapMethod savedEapMethod = EapMethod::PEAP;
+ EXPECT_TRUE(sta_network_->setEapMethod(savedEapMethod).isOk());
+
+ const EapPhase2Method savedPhase2Method = EapPhase2Method::NONE;
+ EXPECT_TRUE(sta_network_->setEapPhase2Method(savedPhase2Method).isOk());
+
+ EapPhase2Method retrievedMethod;
+ EXPECT_TRUE(sta_network_->getEapPhase2Method(&retrievedMethod).isOk());
+ EXPECT_EQ(retrievedMethod, savedPhase2Method);
+}
+
+/*
+ * Set/Get EapIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapIdentity) {
+ EXPECT_TRUE(sta_network_->setEapIdentity(kTestIdentity).isOk());
+
+ std::vector<uint8_t> retrievedIdentity;
+ EXPECT_TRUE(sta_network_->getEapIdentity(&retrievedIdentity).isOk());
+ EXPECT_EQ(retrievedIdentity, kTestIdentity);
+}
+
+/*
+ * Set/Get EapAnonymousIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapAnonymousIdentity) {
+ EXPECT_TRUE(sta_network_->setEapAnonymousIdentity(kTestIdentity).isOk());
+
+ std::vector<uint8_t> retrievedIdentity;
+ EXPECT_TRUE(
+ sta_network_->getEapAnonymousIdentity(&retrievedIdentity).isOk());
+ EXPECT_EQ(retrievedIdentity, kTestIdentity);
+}
+
+/*
+ * Set/Get EapPassword
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPassword) {
+ const std::string eapPasswdStr = "TestEapPasswd1234";
+ const std::vector<uint8_t> savedEapPasswd =
+ std::vector<uint8_t>(eapPasswdStr.begin(), eapPasswdStr.end());
+ ASSERT_TRUE(sta_network_->setEapPassword(savedEapPasswd).isOk());
+
+ std::vector<uint8_t> retrievedEapPasswd;
+ ASSERT_TRUE(sta_network_->getEapPassword(&retrievedEapPasswd).isOk());
+ ASSERT_EQ(retrievedEapPasswd, savedEapPasswd);
+}
+
+/*
+ * Set/Get EapCACert
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapCACert) {
+ EXPECT_TRUE(sta_network_->setEapCACert(kTestEapCert).isOk());
+
+ std::string retrievedCert;
+ EXPECT_TRUE(sta_network_->getEapCACert(&retrievedCert).isOk());
+ EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapCAPath
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapCAPath) {
+ EXPECT_TRUE(sta_network_->setEapCAPath(kTestEapCert).isOk());
+
+ std::string retrievedCert;
+ EXPECT_TRUE(sta_network_->getEapCAPath(&retrievedCert).isOk());
+ EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapClientCert
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapClientCert) {
+ EXPECT_TRUE(sta_network_->setEapClientCert(kTestEapCert).isOk());
+
+ std::string retrievedCert;
+ EXPECT_TRUE(sta_network_->getEapClientCert(&retrievedCert).isOk());
+ EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapPrivateKeyId
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPrivateKeyId) {
+ std::string savedKeyId = "key_id";
+ EXPECT_TRUE(sta_network_->setEapPrivateKeyId(savedKeyId).isOk());
+
+ std::string retrievedKeyId;
+ EXPECT_TRUE(sta_network_->getEapPrivateKeyId(&retrievedKeyId).isOk());
+ EXPECT_EQ(retrievedKeyId, savedKeyId);
+}
+
+/*
+ * Set/Get EapAltSubjectMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapAltSubjectMatch) {
+ EXPECT_TRUE(sta_network_->setEapAltSubjectMatch(kTestEapMatch).isOk());
+
+ std::string retrievedMatch;
+ EXPECT_TRUE(sta_network_->getEapAltSubjectMatch(&retrievedMatch).isOk());
+ EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapSubjectMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapSubjectMatch) {
+ EXPECT_TRUE(sta_network_->setEapSubjectMatch(kTestEapMatch).isOk());
+
+ std::string retrievedMatch;
+ EXPECT_TRUE(sta_network_->getEapSubjectMatch(&retrievedMatch).isOk());
+ EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapDomainSuffixMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapDomainSuffixMatch) {
+ EXPECT_TRUE(sta_network_->setEapDomainSuffixMatch(kTestEapMatch).isOk());
+
+ std::string retrievedMatch;
+ EXPECT_TRUE(sta_network_->getEapDomainSuffixMatch(&retrievedMatch).isOk());
+ EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapEngine
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapEngine) {
+ bool retrievedEapEngine = false;
+ EXPECT_TRUE(sta_network_->setEapEngine(true).isOk());
+ EXPECT_TRUE(sta_network_->getEapEngine(&retrievedEapEngine).isOk());
+ EXPECT_TRUE(retrievedEapEngine);
+}
+
+/*
+ * Set/Get EapEngineID
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapEngineId) {
+ const std::string savedEngineId = "engine_id";
+ EXPECT_TRUE(sta_network_->setEapEngineID(savedEngineId).isOk());
+
+ std::string retrievedId;
+ EXPECT_TRUE(sta_network_->getEapEngineId(&retrievedId).isOk());
+ EXPECT_EQ(retrievedId, savedEngineId);
+}
+
+/*
+ * Set/Get Ocsp
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetOcsp) {
+ const OcspType savedOcspType = OcspType::REQUEST_CERT_STATUS;
+ EXPECT_TRUE(sta_network_->setOcsp(savedOcspType).isOk());
+
+ const OcspType invalidOcspType = static_cast<OcspType>(-1);
+ EXPECT_FALSE(sta_network_->setOcsp(invalidOcspType).isOk());
+
+ OcspType retrievedOcspType;
+ EXPECT_TRUE(sta_network_->getOcsp(&retrievedOcspType).isOk());
+ EXPECT_EQ(retrievedOcspType, savedOcspType);
+}
+
+/*
+ * Set/Get KeyMgmt
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetKeyMgmt) {
+ KeyMgmtMask savedKeyMgmt = KeyMgmtMask::WAPI_PSK;
+ EXPECT_TRUE(sta_network_->setKeyMgmt(savedKeyMgmt).isOk());
+
+ KeyMgmtMask retrievedKeyMgmt;
+ EXPECT_TRUE(sta_network_->getKeyMgmt(&retrievedKeyMgmt).isOk());
+ EXPECT_EQ(retrievedKeyMgmt, savedKeyMgmt);
+
+ savedKeyMgmt = KeyMgmtMask::WAPI_CERT;
+ EXPECT_TRUE(sta_network_->setKeyMgmt(savedKeyMgmt).isOk());
+
+ EXPECT_TRUE(sta_network_->getKeyMgmt(&retrievedKeyMgmt).isOk());
+ EXPECT_EQ(retrievedKeyMgmt, savedKeyMgmt);
+}
+
+/*
+ * Set/Get Proto
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetProto) {
+ const ProtoMask savedProto = ProtoMask::WAPI;
+ EXPECT_TRUE(sta_network_->setProto(savedProto).isOk());
+
+ ProtoMask retrievedProto;
+ EXPECT_TRUE(sta_network_->getProto(&retrievedProto).isOk());
+ EXPECT_EQ(retrievedProto, savedProto);
+}
+
+/*
+ * Set/Get GroupCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetGroupCipher) {
+ const GroupCipherMask savedCipher = GroupCipherMask::SMS4;
+ EXPECT_TRUE(sta_network_->setGroupCipher(savedCipher).isOk());
+
+ GroupCipherMask retrievedCipher;
+ EXPECT_TRUE(sta_network_->getGroupCipher(&retrievedCipher).isOk());
+ EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get PairwiseCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetPairwiseCipher) {
+ const PairwiseCipherMask savedCipher = PairwiseCipherMask::SMS4;
+ EXPECT_TRUE(sta_network_->setPairwiseCipher(savedCipher).isOk());
+
+ PairwiseCipherMask retrievedCipher;
+ EXPECT_TRUE(sta_network_->getPairwiseCipher(&retrievedCipher).isOk());
+ EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get WapiCertSuite
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWapiCertSuite) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::WAPI_PSK)) {
+ GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+ }
+
+ const std::string savedCertSuite = "suite";
+ EXPECT_TRUE(sta_network_->setWapiCertSuite(savedCertSuite).isOk());
+
+ std::string retrievedCertSuite;
+ EXPECT_TRUE(sta_network_->getWapiCertSuite(&retrievedCertSuite).isOk());
+ EXPECT_EQ(retrievedCertSuite, savedCertSuite);
+}
+
+/*
+ * Set/Get WapiPsk
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWapiPsk) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::WAPI_PSK)) {
+ GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+ }
+
+ EXPECT_TRUE(sta_network_->setKeyMgmt(KeyMgmtMask::WAPI_PSK).isOk());
+ EXPECT_TRUE(sta_network_->setPskPassphrase(kTestPskPassphrase).isOk());
+
+ std::string retrievedPassphrase;
+ EXPECT_TRUE(sta_network_->getPskPassphrase(&retrievedPassphrase).isOk());
+ EXPECT_EQ(retrievedPassphrase, kTestPskPassphrase);
+
+ const std::string pskHex = "12345678";
+ EXPECT_TRUE(sta_network_->setPskPassphrase(pskHex).isOk());
+
+ EXPECT_TRUE(sta_network_->getPskPassphrase(&retrievedPassphrase).isOk());
+ EXPECT_EQ(retrievedPassphrase, pskHex);
+}
+
+/*
+ * Set/Get SaePassword
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSaePassword) {
+ const std::string savedPassword = "topsecret";
+ EXPECT_TRUE(sta_network_->setSaePassword(savedPassword).isOk());
+
+ std::string retrievedPassword;
+ EXPECT_TRUE(sta_network_->getSaePassword(&retrievedPassword).isOk());
+ EXPECT_EQ(retrievedPassword, savedPassword);
+}
+
+/*
+ * Set/Get SaePasswordId
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSaePasswordId) {
+ const std::string savedPasswdId = "id1";
+ EXPECT_TRUE(sta_network_->setSaePasswordId(savedPasswdId).isOk());
+
+ std::string retrievedPasswdId;
+ EXPECT_TRUE(sta_network_->getSaePasswordId(&retrievedPasswdId).isOk());
+ EXPECT_EQ(retrievedPasswdId, savedPasswdId);
+}
+
+/*
+ * Set/Get GroupMgmtCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetGroupMgmtCipher) {
+ const GroupMgmtCipherMask savedCipher = GroupMgmtCipherMask::BIP_GMAC_256;
+ EXPECT_TRUE(sta_network_->setGroupMgmtCipher(savedCipher).isOk());
+
+ GroupMgmtCipherMask retrievedCipher;
+ EXPECT_TRUE(sta_network_->getGroupMgmtCipher(&retrievedCipher).isOk());
+ EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get Ssid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSsid) {
+ EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+
+ std::vector<uint8_t> retrievedSsid;
+ EXPECT_TRUE(sta_network_->getSsid(&retrievedSsid).isOk());
+ EXPECT_EQ(retrievedSsid, kTestSsid);
+}
+
+/*
+ * Set/Get Bssid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetBssid) {
+ EXPECT_TRUE(sta_network_->setBssid(kTestBssid).isOk());
+
+ std::vector<uint8_t> retrievedBssid;
+ EXPECT_TRUE(sta_network_->getBssid(&retrievedBssid).isOk());
+ EXPECT_EQ(retrievedBssid, kTestBssid);
+}
+
+/*
+ * Set/Get KeyAuthAlg
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetAuthAlg) {
+ const AuthAlgMask savedAlg =
+ static_cast<AuthAlgMask>(static_cast<uint32_t>(AuthAlgMask::OPEN) |
+ static_cast<uint32_t>(AuthAlgMask::SHARED));
+ EXPECT_TRUE(sta_network_->setAuthAlg(savedAlg).isOk());
+
+ AuthAlgMask retrievedAlg;
+ EXPECT_TRUE(sta_network_->getAuthAlg(&retrievedAlg).isOk());
+ EXPECT_EQ(retrievedAlg, savedAlg);
+}
+
+/*
+ * Set/Get WepTxKeyIdx
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWepTxKeyIdx) {
+ const int32_t savedKeyIdx = 2;
+ EXPECT_TRUE(sta_network_->setWepTxKeyIdx(savedKeyIdx).isOk());
+
+ int32_t retrievedKeyIdx;
+ EXPECT_TRUE(sta_network_->getWepTxKeyIdx(&retrievedKeyIdx).isOk());
+ EXPECT_EQ(retrievedKeyIdx, savedKeyIdx);
+}
+
+/*
+ * Set SAE H2E (Hash-to-Element) mode
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetSaeH2eMode) {
+ EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::DISABLED).isOk());
+ EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::H2E_MANDATORY).isOk());
+ EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::H2E_OPTIONAL).isOk());
+}
+
+/*
+ * Set/Get Psk
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetPsk) {
+ const std::vector<uint8_t> savedPsk = std::vector<uint8_t>(32, 0x12);
+ EXPECT_TRUE(sta_network_->setPsk(savedPsk).isOk());
+
+ std::vector<uint8_t> retrievedPsk;
+ EXPECT_TRUE(sta_network_->getPsk(&retrievedPsk).isOk());
+ EXPECT_EQ(retrievedPsk, savedPsk);
+}
+
+/*
+ * Set/Get WepKeys
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWepKeys) {
+ const uint32_t maxKeys = 4;
+ const std::vector<uint8_t> testWepKey = {0x56, 0x67, 0x67, 0xf4, 0x56};
+
+ for (uint32_t i = 0; i < maxKeys; i++) {
+ std::vector<uint8_t> retrievedKey;
+ EXPECT_TRUE(sta_network_->setWepKey(i, testWepKey).isOk());
+ EXPECT_TRUE(sta_network_->getWepKey(i, &retrievedKey).isOk());
+ EXPECT_EQ(retrievedKey, testWepKey);
+ }
+}
+
+/*
+ * SetPmkCacheEntry
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetPmkCache) {
+ const std::vector<uint8_t> serializedEntry(128, 0);
+ EXPECT_TRUE(sta_network_->setPmkCache(serializedEntry).isOk());
+}
+
+/*
+ * SetEapErp
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetEapErp) {
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
+ EXPECT_TRUE(sta_network_->setEapErp(true).isOk());
+}
+
+/*
+ * SetUpdateIdentifier
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetUpdateIdentifier) {
+ const uint32_t updateIdentifier = 21;
+ EXPECT_TRUE(sta_network_->setUpdateIdentifier(updateIdentifier).isOk());
+}
+
+/*
+ * SetProactiveKeyCaching
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetProactiveKeyCaching) {
+ EXPECT_TRUE(sta_network_->setProactiveKeyCaching(true).isOk());
+ EXPECT_TRUE(sta_network_->setProactiveKeyCaching(false).isOk());
+}
+
+/*
+ * EnableSuiteBEapOpenSslCiphers
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableSuiteBEapOpenSslCiphers) {
+ EXPECT_TRUE(sta_network_->enableSuiteBEapOpenSslCiphers().isOk());
+}
+
+/*
+ * EnableTlsSuiteBEapPhase1Param
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableTlsSuiteBEapPhase1Param) {
+ EXPECT_TRUE(sta_network_->enableTlsSuiteBEapPhase1Param(true).isOk());
+ EXPECT_TRUE(sta_network_->enableTlsSuiteBEapPhase1Param(false).isOk());
+}
+
+/*
+ * SetEapEncryptedImsiIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetEapEncryptedImsiIdentity) {
+ EXPECT_TRUE(
+ sta_network_->setEapEncryptedImsiIdentity(kTestEncryptedIdentity)
+ .isOk());
+}
+
+/*
+ * SendNetworkEapIdentityResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapIdentityResponse) {
+ EXPECT_TRUE(sta_network_
+ ->sendNetworkEapIdentityResponse(kTestIdentity,
+ kTestEncryptedIdentity)
+ .isOk());
+}
+
+/*
+ * Enable SAE PK only mode
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableSaePkOnlyMode) {
+ // Check for SAE PK support
+ WpaDriverCapabilitiesMask caps;
+ EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&caps).isOk());
+ const bool saePkSupported =
+ !!(static_cast<uint32_t>(caps) &
+ static_cast<uint32_t>(WpaDriverCapabilitiesMask::SAE_PK));
+ LOG(INFO) << "SAE-PK Supported: " << saePkSupported;
+
+ // Operation will succeed if SAE PK is supported, or fail otherwise.
+ EXPECT_EQ(sta_network_->enableSaePkOnlyMode(true).isOk(), saePkSupported);
+ EXPECT_EQ(sta_network_->enableSaePkOnlyMode(false).isOk(), saePkSupported);
+}
+
+/*
+ * Enable
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Enable) {
+ // wpa_supplicant won't perform any connection initiation
+ // unless at least the SSID and key mgmt params are set.
+ EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+ EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+ EXPECT_TRUE(sta_network_->enable(false).isOk());
+ EXPECT_TRUE(sta_network_->enable(true).isOk());
+
+ // Now remove the network and ensure that the call fails.
+ removeNetwork();
+ ASSERT_FALSE(sta_network_->enable(true).isOk());
+}
+
+/*
+ * Disable
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Disable) {
+ // wpa_supplicant won't perform any connection initiation
+ // unless at least the SSID and key mgmt params are set.
+ EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+ EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+ EXPECT_TRUE(sta_network_->disable().isOk());
+
+ // Now remove the network and ensure that the call fails.
+ removeNetwork();
+ EXPECT_FALSE(sta_network_->disable().isOk());
+}
+
+/*
+ * Select
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Select) {
+ // wpa_supplicant won't perform any connection initiation
+ // unless at least the SSID and key mgmt params are set.
+ EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+ EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+ EXPECT_TRUE(sta_network_->select().isOk());
+
+ // Now remove the network and ensure that the call fails.
+ removeNetwork();
+ EXPECT_FALSE(sta_network_->select().isOk());
+}
+
+/*
+ * SendNetworkEapSimGsmAuthResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimGsmAuthResponse) {
+ NetworkResponseEapSimGsmAuthParams param;
+ param.kc =
+ std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4, 0x76, 0x87, 0x98, 0x12});
+ param.sres = std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4});
+ const std::vector<NetworkResponseEapSimGsmAuthParams> params = {param};
+ EXPECT_TRUE(sta_network_->sendNetworkEapSimGsmAuthResponse(params).isOk());
+}
+
+/*
+ * SendNetworkEapSimGsmAuthFailure
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimGsmAuthFailure) {
+ EXPECT_TRUE(sta_network_->sendNetworkEapSimGsmAuthFailure().isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAuthResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAuthResponse) {
+ NetworkResponseEapSimUmtsAuthParams params;
+ params.res = std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4, 0x67});
+ params.ik = std::vector<uint8_t>(16, 0x65);
+ params.ck = std::vector<uint8_t>(16, 0x45);
+ EXPECT_TRUE(sta_network_->sendNetworkEapSimUmtsAuthResponse(params).isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAuthFailure
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAuthFailure) {
+ EXPECT_TRUE(sta_network_->sendNetworkEapSimUmtsAuthFailure().isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAutsResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAutsResponse) {
+ const std::vector<uint8_t> testAutParam = std::vector<uint8_t>(14, 0xe1);
+ EXPECT_TRUE(
+ sta_network_->sendNetworkEapSimUmtsAutsResponse(testAutParam).isOk());
+}
+
+/*
+ * GetWpsNfcConfigurationToken
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetWpsNfcConfigurationToken) {
+ EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+ EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+ EXPECT_TRUE(sta_network_->setPskPassphrase(kTestPskPassphrase).isOk());
+
+ std::vector<uint8_t> retrievedToken;
+ EXPECT_TRUE(
+ sta_network_->getWpsNfcConfigurationToken(&retrievedToken).isOk());
+ EXPECT_NE(retrievedToken.size(), 0);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaNetworkAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ ISupplicant::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
new file mode 100644
index 0000000..17e0394
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SUPPLICANT_TEST_UTILS_H
+#define SUPPLICANT_TEST_UTILS_H
+
+#include <VtsCoreUtil.h>
+#include <android-base/logging.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <hidl/ServiceManagement.h>
+#include <supplicant_hidl_test_utils.h>
+#include <wifi_system/supplicant_manager.h>
+
+using aidl::android::hardware::wifi::supplicant::IfaceInfo;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using android::wifi_system::SupplicantManager;
+
+std::string getStaIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ property_get("wifi.interface", buffer.data(), "wlan0");
+ return std::string(buffer.data());
+}
+
+std::string getP2pIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ property_get("wifi.direct.interface", buffer.data(), "p2p0");
+ return std::string(buffer.data());
+}
+
+std::string getWifiInstanceName() {
+ const std::vector<std::string> instances =
+ android::hardware::getAllHalInstanceNames(
+ ::android::hardware::wifi::V1_0::IWifi::descriptor);
+ EXPECT_NE(0, instances.size());
+ return instances.size() != 0 ? instances[0] : "";
+}
+
+bool keyMgmtSupported(std::shared_ptr<ISupplicantStaIface> iface,
+ KeyMgmtMask expected) {
+ KeyMgmtMask caps;
+ if (!iface->getKeyMgmtCapabilities(&caps).isOk()) {
+ return false;
+ }
+ return !!(static_cast<uint32_t>(caps) & static_cast<uint32_t>(expected));
+}
+
+bool isFilsSupported(std::shared_ptr<ISupplicantStaIface> iface) {
+ KeyMgmtMask filsMask = static_cast<KeyMgmtMask>(
+ static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256) |
+ static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384));
+ return keyMgmtSupported(iface, filsMask);
+}
+
+void startSupplicant() {
+ initializeDriverAndFirmware(getWifiInstanceName());
+ SupplicantManager supplicant_manager;
+ ASSERT_TRUE(supplicant_manager.StartSupplicant());
+ ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
+}
+
+// Wrapper around the implementation in supplicant_hidl_test_util.
+void stopSupplicantService() { stopSupplicant(getWifiInstanceName()); }
+
+void initializeService() {
+ ASSERT_TRUE(stopWifiFramework());
+ std::system("/system/bin/start");
+ ASSERT_TRUE(waitForFrameworkReady());
+ stopSupplicantService();
+ startSupplicant();
+}
+
+void addStaIface(const std::shared_ptr<ISupplicant> supplicant) {
+ ASSERT_TRUE(supplicant.get());
+ std::shared_ptr<ISupplicantStaIface> iface;
+ ASSERT_TRUE(supplicant->addStaInterface(getStaIfaceName(), &iface).isOk());
+}
+
+void addP2pIface(const std::shared_ptr<ISupplicant> supplicant) {
+ ASSERT_TRUE(supplicant.get());
+ std::shared_ptr<ISupplicantP2pIface> iface;
+ ASSERT_TRUE(supplicant->addP2pInterface(getP2pIfaceName(), &iface).isOk());
+}
+
+std::shared_ptr<ISupplicant> getSupplicant(const char* supplicant_name) {
+ std::shared_ptr<ISupplicant> supplicant = ISupplicant::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(supplicant_name)));
+ addStaIface(supplicant);
+ if (testing::deviceSupportsFeature("android.hardware.wifi.direct")) {
+ addP2pIface(supplicant);
+ }
+ return supplicant;
+}
+
+#endif // SUPPLICANT_TEST_UTILS_H
\ No newline at end of file